Commit d6ae01da authored by Filipa Lacerda's avatar Filipa Lacerda

Use CJS in all environments components

parent 8f3678f1
/* eslint-disable no-param-reassign, no-new */ /* eslint-disable no-param-reassign, no-new */
/* global Vue */
/* global EnvironmentsService */
/* global Flash */ /* global Flash */
window.Vue = require('vue'); const Vue = require('vue');
window.Vue.use(require('vue-resource')); Vue.use(require('vue-resource'));
const EnvironmentsService = require('../services/environments_service'); const EnvironmentsService = require('../services/environments_service');
require('./environment_item'); const EnvironmentItem = require('./environment_item');
const Store = require('../stores/environments_store'); const Store = require('../stores/environments_store');
(() => { module.exports = Vue.component('environment-component', {
window.gl = window.gl || {};
components: {
gl.environmentsList.EnvironmentsComponent = Vue.component('environment-component', { 'environment-item': EnvironmentItem,
},
components: {
'environment-item': gl.environmentsList.EnvironmentItem, data() {
}, const environmentsData = document.querySelector('#environments-list-view').dataset;
const store = new Store();
data() {
const environmentsData = document.querySelector('#environments-list-view').dataset; return {
const store = new Store(); store,
state: store.state,
return { visibility: 'available',
store, isLoading: false,
state: store.state, cssContainerClass: environmentsData.cssClass,
visibility: 'available', endpoint: environmentsData.environmentsDataEndpoint,
isLoading: false, canCreateDeployment: environmentsData.canCreateDeployment,
cssContainerClass: environmentsData.cssClass, canReadEnvironment: environmentsData.canReadEnvironment,
endpoint: environmentsData.environmentsDataEndpoint, canCreateEnvironment: environmentsData.canCreateEnvironment,
canCreateDeployment: environmentsData.canCreateDeployment, projectEnvironmentsPath: environmentsData.projectEnvironmentsPath,
canReadEnvironment: environmentsData.canReadEnvironment, projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath,
canCreateEnvironment: environmentsData.canCreateEnvironment, newEnvironmentPath: environmentsData.newEnvironmentPath,
projectEnvironmentsPath: environmentsData.projectEnvironmentsPath, helpPagePath: environmentsData.helpPagePath,
projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath, commitIconSvg: environmentsData.commitIconSvg,
newEnvironmentPath: environmentsData.newEnvironmentPath, playIconSvg: environmentsData.playIconSvg,
helpPagePath: environmentsData.helpPagePath, terminalIconSvg: environmentsData.terminalIconSvg,
commitIconSvg: environmentsData.commitIconSvg, };
playIconSvg: environmentsData.playIconSvg, },
terminalIconSvg: environmentsData.terminalIconSvg,
}; computed: {
scope() {
return this.$options.getQueryParameter('scope');
}, },
computed: { canReadEnvironmentParsed() {
scope() { return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
return this.$options.getQueryParameter('scope');
},
canReadEnvironmentParsed() {
return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
},
canCreateEnvironmentParsed() {
return this.$options.convertPermissionToBoolean(this.canCreateEnvironment);
},
}, },
/** canCreateDeploymentParsed() {
* Fetches all the environments and stores them. return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
* Toggles loading property.
*/
created() {
const scope = this.$options.getQueryParameter('scope') || this.visibility;
const endpoint = `${this.endpoint}?scope=${scope}`;
const service = new EnvironmentsService(endpoint);
this.isLoading = true;
return service.all()
.then(resp => resp.json())
.then((json) => {
this.store.storeAvailableCount(json.available_count);
this.store.storeStoppedCount(json.stopped_count);
this.store.storeEnvironments(json.environments);
})
.then(() => {
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the environments.', 'alert');
});
}, },
/** canCreateEnvironmentParsed() {
* Transforms the url parameter into an object and return this.$options.convertPermissionToBoolean(this.canCreateEnvironment);
* 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];
}, },
},
/**
* Converts permission provided as strings to booleans. /**
* @param {String} string * Fetches all the environments and stores them.
* @returns {Boolean} * Toggles loading property.
*/ */
convertPermissionToBoolean(string) { created() {
return string === 'true'; const scope = this.$options.getQueryParameter('scope') || this.visibility;
const endpoint = `${this.endpoint}?scope=${scope}`;
const service = new EnvironmentsService(endpoint);
this.isLoading = true;
return service.all()
.then(resp => resp.json())
.then((json) => {
this.store.storeAvailableCount(json.available_count);
this.store.storeStoppedCount(json.stopped_count);
this.store.storeEnvironments(json.environments);
})
.then(() => {
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the environments.', 'alert');
});
},
/**
* 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];
},
/**
* 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);
}, },
},
template: `
<div :class="cssContainerClass">
<div class="top-area">
<ul v-if="!isLoading" class="nav-links">
<li v-bind:class="{ 'active': scope === undefined }">
<a :href="projectEnvironmentsPath">
Available
<span class="badge js-available-environments-count">
{{state.availableCounter}}
</span>
</a>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped' }">
<a :href="projectStoppedEnvironmentsPath">
Stopped
<span class="badge js-stopped-environments-count">
{{state.stoppedCounter}}
</span>
</a>
</li>
</ul>
<div v-if="canCreateEnvironmentParsed && !isLoading" class="nav-controls">
<a :href="newEnvironmentPath" class="btn btn-create">
New environment
</a>
</div>
</div>
methods: { <div class="environments-container">
toggleRow(model) { <div class="environments-list-loading text-center" v-if="isLoading">
return this.store.toggleFolder(model.name); <i class="fa fa-spinner fa-spin"></i>
}, </div>
},
template: ` <div class="blank-state blank-state-no-icon"
<div :class="cssContainerClass"> v-if="!isLoading && state.environments.length === 0">
<div class="top-area"> <h2 class="blank-state-title js-blank-state-title">
<ul v-if="!isLoading" class="nav-links"> You don't have any environments right now.
<li v-bind:class="{ 'active': scope === undefined }"> </h2>
<a :href="projectEnvironmentsPath"> <p class="blank-state-text">
Available Environments are places where code gets deployed, such as staging or production.
<span class="badge js-available-environments-count"> <br />
{{state.availableCounter}} <a :href="helpPagePath">
</span> Read more about environments
</a>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped' }">
<a :href="projectStoppedEnvironmentsPath">
Stopped
<span class="badge js-stopped-environments-count">
{{state.stoppedCounter}}
</span>
</a>
</li>
</ul>
<div v-if="canCreateEnvironmentParsed && !isLoading" class="nav-controls">
<a :href="newEnvironmentPath" class="btn btn-create">
New environment
</a> </a>
</div> </p>
<a v-if="canCreateEnvironmentParsed"
:href="newEnvironmentPath"
class="btn btn-create js-new-environment-button">
New Environment
</a>
</div> </div>
<div class="environments-container"> <div class="table-holder"
<div class="environments-list-loading text-center" v-if="isLoading"> v-if="!isLoading && state.environments.length > 0">
<i class="fa fa-spinner fa-spin"></i> <table class="table ci-table environments">
</div> <thead>
<tr>
<div class="blank-state blank-state-no-icon" <th class="environments-name">Environment</th>
v-if="!isLoading && state.environments.length === 0"> <th class="environments-deploy">Last deployment</th>
<h2 class="blank-state-title js-blank-state-title"> <th class="environments-build">Job</th>
You don't have any environments right now. <th class="environments-commit">Commit</th>
</h2> <th class="environments-date">Updated</th>
<p class="blank-state-text"> <th class="hidden-xs environments-actions"></th>
Environments are places where code gets deployed, such as staging or production. </tr>
<br /> </thead>
<a :href="helpPagePath"> <tbody>
Read more about environments <template v-for="model in state.environments"
</a> v-bind:model="model">
</p> <tr is="environment-item"
:model="model"
<a v-if="canCreateEnvironmentParsed" :can-create-deployment="canCreateDeploymentParsed"
:href="newEnvironmentPath" :can-read-environment="canReadEnvironmentParsed"
class="btn btn-create js-new-environment-button"> :play-icon-svg="playIconSvg"
New Environment :terminal-icon-svg="terminalIconSvg"
</a> :commit-icon-svg="commitIconSvg"></tr>
</div> </template>
</tbody>
<div class="table-holder" </table>
v-if="!isLoading && state.environments.length > 0">
<table class="table ci-table environments">
<thead>
<tr>
<th class="environments-name">Environment</th>
<th class="environments-deploy">Last deployment</th>
<th class="environments-build">Job</th>
<th class="environments-commit">Commit</th>
<th class="environments-date">Updated</th>
<th class="hidden-xs environments-actions"></th>
</tr>
</thead>
<tbody>
<template v-for="model in state.environments"
v-bind:model="model">
<tr is="environment-item"
:model="model"
:can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"
:play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg"></tr>
</template>
</tbody>
</table>
</div>
</div> </div>
</div> </div>
`, </div>
}); `,
})(); });
/* global Vue */ const Vue = require('vue');
window.Vue = require('vue'); module.exports = Vue.component('actions-component', {
props: {
(() => { actions: {
window.gl = window.gl || {}; type: Array,
window.gl.environmentsList = window.gl.environmentsList || {}; required: false,
default: () => [],
gl.environmentsList.ActionsComponent = Vue.component('actions-component', {
props: {
actions: {
type: Array,
required: false,
default: () => [],
},
playIconSvg: {
type: String,
required: false,
},
}, },
template: ` playIconSvg: {
<div class="inline"> type: String,
<div class="dropdown"> required: false,
<a class="dropdown-new btn btn-default" data-toggle="dropdown"> },
<span class="js-dropdown-play-icon-container" v-html="playIconSvg"></span> },
<i class="fa fa-caret-down"></i>
</a> template: `
<div class="inline">
<ul class="dropdown-menu dropdown-menu-align-right"> <div class="dropdown">
<li v-for="action in actions"> <a class="dropdown-new btn btn-default" data-toggle="dropdown">
<a :href="action.play_path" <span class="js-dropdown-play-icon-container" v-html="playIconSvg"></span>
data-method="post" <i class="fa fa-caret-down"></i>
rel="nofollow" </a>
class="js-manual-action-link">
<ul class="dropdown-menu dropdown-menu-align-right">
<span class="js-action-play-icon-container" v-html="playIconSvg"></span> <li v-for="action in actions">
<a :href="action.play_path"
<span> data-method="post"
{{action.name}} rel="nofollow"
</span> class="js-manual-action-link">
</a>
</li> <span class="js-action-play-icon-container" v-html="playIconSvg"></span>
</ul>
</div> <span>
{{action.name}}
</span>
</a>
</li>
</ul>
</div> </div>
`, </div>
}); `,
})(); });
/* global Vue */ /**
* Renders the external url link in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue'); module.exports = Vue.component('external-url-component', {
props: {
(() => { externalUrl: {
window.gl = window.gl || {}; type: String,
window.gl.environmentsList = window.gl.environmentsList || {}; default: '',
gl.environmentsList.ExternalUrlComponent = Vue.component('external-url-component', {
props: {
externalUrl: {
type: String,
default: '',
},
}, },
},
template: ` template: `
<a class="btn external_url" :href="externalUrl" target="_blank"> <a class="btn external_url" :href="externalUrl" target="_blank">
<i class="fa fa-external-link"></i> <i class="fa fa-external-link"></i>
</a> </a>
`, `,
}); });
})();
/* global Vue */
/* global timeago */
window.Vue = require('vue'); const Vue = require('vue');
window.timeago = require('vendor/timeago'); const Timeago = require('vendor/timeago');
require('../../lib/utils/text_utility'); require('../../lib/utils/text_utility');
require('../../vue_shared/components/commit'); require('../../vue_shared/components/commit');
require('./environment_actions'); const ActionsComponent = require('./environment_actions');
require('./environment_external_url'); const ExternalUrlComponent = require('./environment_external_url');
require('./environment_stop'); const StopComponent = require('./environment_stop');
require('./environment_rollback'); const RollbackComponent = require('./environment_rollback');
require('./environment_terminal_button'); const TerminalButtonComponent = require('./environment_terminal_button');
/**
* Envrionment Item Component
*
* Renders a table row for each environment.
*/
const timeagoInstance = new Timeago();
module.exports = Vue.component('environment-item', {
components: {
'commit-component': gl.CommitComponent,
'actions-component': ActionsComponent,
'external-url-component': ExternalUrlComponent,
'stop-component': StopComponent,
'rollback-component': RollbackComponent,
'terminal-button-component': TerminalButtonComponent,
},
props: {
model: {
type: Object,
required: true,
default: () => ({}),
},
(() => { canCreateDeployment: {
/** type: Boolean,
* Envrionment Item Component required: false,
* default: false,
* Renders a table row for each environment. },
*/
window.gl = window.gl || {}; canReadEnvironment: {
window.gl.environmentsList = window.gl.environmentsList || {}; type: Boolean,
window.gl.environmentsList.timeagoInstance = new timeago(); // eslint-disable-line required: false,
default: false,
},
gl.environmentsList.EnvironmentItem = Vue.component('environment-item', { commitIconSvg: {
type: String,
required: false,
},
components: { playIconSvg: {
'commit-component': gl.CommitComponent, type: String,
'actions-component': gl.environmentsList.ActionsComponent, required: false,
'external-url-component': gl.environmentsList.ExternalUrlComponent,
'stop-component': gl.environmentsList.StopComponent,
'rollback-component': gl.environmentsList.RollbackComponent,
'terminal-button-component': gl.environmentsList.TerminalButtonComponent,
}, },
props: { terminalIconSvg: {
model: { type: String,
type: Object, required: false,
required: true,
default: () => ({}),
},
canCreateDeployment: {
type: Boolean,
required: false,
default: false,
},
canReadEnvironment: {
type: Boolean,
required: false,
default: false,
},
commitIconSvg: {
type: String,
required: false,
},
playIconSvg: {
type: String,
required: false,
},
terminalIconSvg: {
type: String,
required: false,
},
}, },
},
computed: { computed: {
/** /**
* Verifies if `last_deployment` key exists in the current Envrionment. * Verifies if `last_deployment` key exists in the current Envrionment.
* This key is required to render most of the html - this method works has * This key is required to render most of the html - this method works has
* an helper. * an helper.
* *
* @returns {Boolean} * @returns {Boolean}
*/ */
hasLastDeploymentKey() { hasLastDeploymentKey() {
if (this.model.latest.last_deployment && if (this.model.latest.last_deployment &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment)) { !this.$options.isObjectEmpty(this.model.latest.last_deployment)) {
return true; return true;
} }
return false; return false;
}, },
/** /**
* Verifies is the given environment has manual actions. * Verifies is the given environment has manual actions.
* Used to verify if we should render them or nor. * Used to verify if we should render them or nor.
* *
* @returns {Boolean|Undefined} * @returns {Boolean|Undefined}
*/ */
hasManualActions() { hasManualActions() {
return this.model.latest.last_deployment && return this.model.latest.last_deployment &&
this.model.latest.last_deployment.manual_actions && this.model.latest.last_deployment.manual_actions &&
this.model.latest.last_deployment.manual_actions.length > 0; this.model.latest.last_deployment.manual_actions.length > 0;
}, },
/** /**
* Returns the value of the `stop_action?` key provided in the response. * Returns the value of the `stop_action?` key provided in the response.
* *
* @returns {Boolean} * @returns {Boolean}
*/ */
hasStopAction() { hasStopAction() {
return this.model['stop_action?']; return this.model['stop_action?'];
}, },
/** /**
* Verifies if the `deployable` key is present in `last_deployment` key. * Verifies if the `deployable` key is present in `last_deployment` key.
* Used to verify whether we should or not render the rollback partial. * Used to verify whether we should or not render the rollback partial.
* *
* @returns {Boolean|Undefined} * @returns {Boolean|Undefined}
*/ */
canRetry() { canRetry() {
return this.hasLastDeploymentKey && return this.hasLastDeploymentKey &&
this.model.latest.last_deployment && this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable; this.model.latest.last_deployment.deployable;
}, },
/** /**
* Verifies if the date to be shown is present. * Verifies if the date to be shown is present.
* *
* @returns {Boolean|Undefined} * @returns {Boolean|Undefined}
*/ */
canShowDate() { canShowDate() {
return this.model.latest.last_deployment && return this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable && this.model.latest.last_deployment.deployable &&
this.model.latest.last_deployment.deployable !== undefined; this.model.latest.last_deployment.deployable !== undefined;
}, },
/** /**
* Human readable date. * Human readable date.
* *
* @returns {String} * @returns {String}
*/ */
createdDate() { createdDate() {
return gl.environmentsList.timeagoInstance.format( return timeagoInstance.format(this.model.latest.last_deployment.deployable.created_at);
this.model.latest.last_deployment.deployable.created_at,
);
},
/**
* Returns the manual actions with the name parsed.
*
* @returns {Array.<Object>|Undefined}
*/
manualActions() {
if (this.hasManualActions) {
return this.model.latest.last_deployment.manual_actions.map((action) => {
const parsedAction = {
name: gl.text.humanize(action.name),
play_path: action.play_path,
};
return parsedAction;
});
}
return [];
},
/**
* Builds the string used in the user image alt attribute.
*
* @returns {String}
*/
userImageAltDescription() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.user &&
this.model.latest.last_deployment.user.username) {
return `${this.model.latest.last_deployment.user.username}'s avatar'`;
}
return '';
},
/**
* If provided, returns the commit tag.
*
* @returns {String|Undefined}
*/
commitTag() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.tag) {
return this.model.latest.last_deployment.tag;
}
return undefined;
},
/**
* If provided, returns the commit ref.
*
* @returns {Object|Undefined}
*/
commitRef() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.ref) {
return this.model.latest.last_deployment.ref;
}
return undefined;
},
/**
* If provided, returns the commit url.
*
* @returns {String|Undefined}
*/
commitUrl() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.commit_path) {
return this.model.latest.last_deployment.commit.commit_path;
}
return undefined;
},
/**
* If provided, returns the commit short sha.
*
* @returns {String|Undefined}
*/
commitShortSha() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.short_id) {
return this.model.latest.last_deployment.commit.short_id;
}
return undefined;
},
/**
* If provided, returns the commit title.
*
* @returns {String|Undefined}
*/
commitTitle() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.title) {
return this.model.latest.last_deployment.commit.title;
}
return undefined;
},
/**
* If provided, returns the commit tag.
*
* @returns {Object|Undefined}
*/
commitAuthor() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.author) {
return this.model.latest.last_deployment.commit.author;
}
return undefined;
},
/**
* Verifies if the `retry_path` key is present and returns its value.
*
* @returns {String|Undefined}
*/
retryUrl() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable &&
this.model.latest.last_deployment.deployable.retry_path) {
return this.model.latest.last_deployment.deployable.retry_path;
}
return undefined;
},
/**
* Verifies if the `last?` key is present and returns its value.
*
* @returns {Boolean|Undefined}
*/
isLastDeployment() {
return this.model.latest.last_deployment &&
this.model.latest.last_deployment['last?'];
},
/**
* Builds the name of the builds needed to display both the name and the id.
*
* @returns {String}
*/
buildName() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable) {
return `${this.model.latest.last_deployment.deployable.name} #${this.model.latest.last_deployment.deployable.id}`;
}
return '';
},
/**
* Builds the needed string to show the internal id.
*
* @returns {String}
*/
deploymentInternalId() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.iid) {
return `#${this.model.latest.last_deployment.iid}`;
}
return '';
},
/**
* Verifies if the user object is present under last_deployment object.
*
* @returns {Boolean}
*/
deploymentHasUser() {
return !this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.user);
},
/**
* Returns the user object nested with the last_deployment object.
* Used to render the template.
*
* @returns {Object}
*/
deploymentUser() {
if (!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.user)) {
return this.model.latest.last_deployment.user;
}
return {};
},
/**
* Verifies if the build name column should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderBuildName() {
return !this.model.isFolder &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.deployable);
},
/**
* Verifies if deplyment internal ID should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderDeploymentID() {
return !this.model.isFolder &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
this.model.latest.last_deployment.iid !== undefined;
},
}, },
/** /**
* Helper to verify if certain given object are empty. * Returns the manual actions with the name parsed.
* Should be replaced by lodash _.isEmpty - https://lodash.com/docs/4.17.2#isEmpty *
* @param {Object} object * @returns {Array.<Object>|Undefined}
* @returns {Bollean}
*/ */
isObjectEmpty(object) { manualActions() {
for (const key in object) { // eslint-disable-line if (this.hasManualActions) {
if (hasOwnProperty.call(object, key)) { return this.model.latest.last_deployment.manual_actions.map((action) => {
return false; const parsedAction = {
} name: gl.text.humanize(action.name),
play_path: action.play_path,
};
return parsedAction;
});
} }
return true; return [];
}, },
template: ` /**
<tr> * Builds the string used in the user image alt attribute.
<td> *
<a v-if="!model.isFolder" * @returns {String}
class="environment-name" */
:href="model.latest.environment_path"> userImageAltDescription() {
{{model.name}} if (this.model.latest.last_deployment &&
</a> this.model.latest.last_deployment.user &&
<a v-else class="folder-name"> this.model.latest.last_deployment.user.username) {
<span class="folder-icon"> return `${this.model.latest.last_deployment.user.username}'s avatar'`;
<i class="fa fa-caret-right" aria-hidden="true"></i> }
<i class="fa fa-folder" aria-hidden="true"></i> return '';
</span> },
<span> /**
{{model.name}} * If provided, returns the commit tag.
</span> *
* @returns {String|Undefined}
<span class="badge"> */
{{model.size}} commitTag() {
</span> if (this.model.latest.last_deployment &&
</a> this.model.latest.last_deployment.tag) {
</td> return this.model.latest.last_deployment.tag;
}
return undefined;
},
/**
* If provided, returns the commit ref.
*
* @returns {Object|Undefined}
*/
commitRef() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.ref) {
return this.model.latest.last_deployment.ref;
}
return undefined;
},
/**
* If provided, returns the commit url.
*
* @returns {String|Undefined}
*/
commitUrl() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.commit_path) {
return this.model.latest.last_deployment.commit.commit_path;
}
return undefined;
},
/**
* If provided, returns the commit short sha.
*
* @returns {String|Undefined}
*/
commitShortSha() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.short_id) {
return this.model.latest.last_deployment.commit.short_id;
}
return undefined;
},
/**
* If provided, returns the commit title.
*
* @returns {String|Undefined}
*/
commitTitle() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.title) {
return this.model.latest.last_deployment.commit.title;
}
return undefined;
},
/**
* If provided, returns the commit tag.
*
* @returns {Object|Undefined}
*/
commitAuthor() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.commit &&
this.model.latest.last_deployment.commit.author) {
return this.model.latest.last_deployment.commit.author;
}
return undefined;
},
/**
* Verifies if the `retry_path` key is present and returns its value.
*
* @returns {String|Undefined}
*/
retryUrl() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable &&
this.model.latest.last_deployment.deployable.retry_path) {
return this.model.latest.last_deployment.deployable.retry_path;
}
return undefined;
},
/**
* Verifies if the `last?` key is present and returns its value.
*
* @returns {Boolean|Undefined}
*/
isLastDeployment() {
return this.model.latest.last_deployment &&
this.model.latest.last_deployment['last?'];
},
/**
* Builds the name of the builds needed to display both the name and the id.
*
* @returns {String}
*/
buildName() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.deployable) {
return `${this.model.latest.last_deployment.deployable.name} #${this.model.latest.last_deployment.deployable.id}`;
}
return '';
},
<td class="deployment-column"> /**
<span v-if="shouldRenderDeploymentID"> * Builds the needed string to show the internal id.
{{deploymentInternalId}} *
* @returns {String}
*/
deploymentInternalId() {
if (this.model.latest.last_deployment &&
this.model.latest.last_deployment.iid) {
return `#${this.model.latest.last_deployment.iid}`;
}
return '';
},
/**
* Verifies if the user object is present under last_deployment object.
*
* @returns {Boolean}
*/
deploymentHasUser() {
return !this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.user);
},
/**
* Returns the user object nested with the last_deployment object.
* Used to render the template.
*
* @returns {Object}
*/
deploymentUser() {
if (!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.user)) {
return this.model.latest.last_deployment.user;
}
return {};
},
/**
* Verifies if the build name column should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderBuildName() {
return !this.model.isFolder &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment.deployable);
},
/**
* Verifies if deplyment internal ID should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderDeploymentID() {
return !this.model.isFolder &&
!this.$options.isObjectEmpty(this.model.latest.last_deployment) &&
this.model.latest.last_deployment.iid !== undefined;
},
},
/**
* Helper to verify if certain given object are empty.
* Should be replaced by lodash _.isEmpty - https://lodash.com/docs/4.17.2#isEmpty
* @param {Object} object
* @returns {Bollean}
*/
isObjectEmpty(object) {
for (const key in object) { // eslint-disable-line
if (hasOwnProperty.call(object, key)) {
return false;
}
}
return true;
},
template: `
<tr>
<td>
<a v-if="!model.isFolder"
class="environment-name"
:href="model.latest.environment_path">
{{model.name}}
</a>
<a v-else class="folder-name">
<span class="folder-icon">
<i class="fa fa-caret-right" aria-hidden="true"></i>
<i class="fa fa-folder" aria-hidden="true"></i>
</span> </span>
<span v-if="!model.isFolder && deploymentHasUser"> <span>
by {{model.name}}
<a :href="deploymentUser.web_url" class="js-deploy-user-container">
<img class="avatar has-tooltip s20"
:src="deploymentUser.avatar_url"
:alt="userImageAltDescription"
:title="deploymentUser.username" />
</a>
</span> </span>
</td>
<td class="environments-build-cell"> <span class="badge">
<a v-if="shouldRenderBuildName" {{model.size}}
class="build-link" </span>
:href="model.latest.last_deployment.deployable.build_path"> </a>
{{buildName}} </td>
<td class="deployment-column">
<span v-if="shouldRenderDeploymentID">
{{deploymentInternalId}}
</span>
<span v-if="!model.isFolder && deploymentHasUser">
by
<a :href="deploymentUser.web_url" class="js-deploy-user-container">
<img class="avatar has-tooltip s20"
:src="deploymentUser.avatar_url"
:alt="userImageAltDescription"
:title="deploymentUser.username" />
</a> </a>
</td> </span>
</td>
<td>
<div v-if="!model.isFolder && hasLastDeploymentKey" class="js-commit-component"> <td class="environments-build-cell">
<commit-component <a v-if="shouldRenderBuildName"
:tag="commitTag" class="build-link"
:commit-ref="commitRef" :href="model.latest.last_deployment.deployable.build_path">
:commit-url="commitUrl" {{buildName}}
:short-sha="commitShortSha" </a>
:title="commitTitle" </td>
:author="commitAuthor"
:commit-icon-svg="commitIconSvg"> <td>
</commit-component> <div v-if="!model.isFolder && hasLastDeploymentKey" class="js-commit-component">
<commit-component
:tag="commitTag"
:commit-ref="commitRef"
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
:author="commitAuthor"
:commit-icon-svg="commitIconSvg">
</commit-component>
</div>
<p v-if="!model.isFolder && !hasLastDeploymentKey" class="commit-title">
No deployments yet
</p>
</td>
<td>
<span v-if="!model.isFolder && canShowDate"
class="environment-created-date-timeago">
{{createdDate}}
</span>
</td>
<td class="hidden-xs">
<div v-if="!model.isFolder">
<div v-if="hasManualActions && canCreateDeployment"
class="inline js-manual-actions-container">
<actions-component
:play-icon-svg="playIconSvg"
:actions="manualActions">
</actions-component>
</div> </div>
<p v-if="!model.isFolder && !hasLastDeploymentKey" class="commit-title">
No deployments yet <div v-if="model.latest.external_url && canReadEnvironment"
</p> class="inline js-external-url-container">
</td> <external-url-component
:external-url="model.latest.external_url">
<td> </external-url-component>
<span v-if="!model.isFolder && canShowDate" </div>
class="environment-created-date-timeago">
{{createdDate}} <div v-if="hasStopAction && canCreateDeployment"
</span> class="inline js-stop-component-container">
</td> <stop-component
:stop-url="model.latest.stop_path">
<td class="hidden-xs"> </stop-component>
<div v-if="!model.isFolder"> </div>
<div v-if="hasManualActions && canCreateDeployment"
class="inline js-manual-actions-container"> <div v-if="model.latest.terminal_path"
<actions-component class="inline js-terminal-button-container">
:play-icon-svg="playIconSvg" <terminal-button-component
:actions="manualActions"> :terminal-icon-svg="terminalIconSvg"
</actions-component> :terminal-path="model.latest.terminal_path">
</div> </terminal-button-component>
</div>
<div v-if="model.latest.external_url && canReadEnvironment"
class="inline js-external-url-container"> <div v-if="canRetry && canCreateDeployment"
<external-url-component class="inline js-rollback-component-container">
:external-url="model.latest.external_url"> <rollback-component
</external-url-component> :is-last-deployment="isLastDeployment"
</div> :retry-url="retryUrl">
</rollback-component>
<div v-if="hasStopAction && canCreateDeployment"
class="inline js-stop-component-container">
<stop-component
:stop-url="model.latest.stop_path">
</stop-component>
</div>
<div v-if="model.latest.terminal_path"
class="inline js-terminal-button-container">
<terminal-button-component
:terminal-icon-svg="terminalIconSvg"
:terminal-path="model.latest.terminal_path">
</terminal-button-component>
</div>
<div v-if="canRetry && canCreateDeployment"
class="inline js-rollback-component-container">
<rollback-component
:is-last-deployment="isLastDeployment"
:retry-url="retryUrl">
</rollback-component>
</div>
</div> </div>
</td> </div>
</tr> </td>
`, </tr>
}); `,
})(); });
/* global Vue */ /**
* Renders Rollback or Re deploy button in environments table depending
* of the provided property `isLastDeployment`
*/
const Vue = require('vue');
window.Vue = require('vue'); module.exports = Vue.component('rollback-component', {
props: {
(() => { retryUrl: {
window.gl = window.gl || {}; type: String,
window.gl.environmentsList = window.gl.environmentsList || {}; default: '',
},
gl.environmentsList.RollbackComponent = Vue.component('rollback-component', {
props: {
retryUrl: {
type: String,
default: '',
},
isLastDeployment: { isLastDeployment: {
type: Boolean, type: Boolean,
default: true, default: true,
},
}, },
},
template: ` template: `
<a class="btn" :href="retryUrl" data-method="post" rel="nofollow"> <a class="btn" :href="retryUrl" data-method="post" rel="nofollow">
<span v-if="isLastDeployment"> <span v-if="isLastDeployment">
Re-deploy Re-deploy
</span> </span>
<span v-else> <span v-else>
Rollback Rollback
</span> </span>
</a> </a>
`, `,
}); });
})();
/* global Vue */ /**
* Renders the stop "button" that allows stop an environment.
* Used in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue'); module.exports = Vue.component('stop-component', {
props: {
(() => { stopUrl: {
window.gl = window.gl || {}; type: String,
window.gl.environmentsList = window.gl.environmentsList || {}; default: '',
gl.environmentsList.StopComponent = Vue.component('stop-component', {
props: {
stopUrl: {
type: String,
default: '',
},
}, },
},
template: ` template: `
<a class="btn stop-env-link" <a class="btn stop-env-link"
:href="stopUrl" :href="stopUrl"
data-confirm="Are you sure you want to stop this environment?" data-confirm="Are you sure you want to stop this environment?"
data-method="post" data-method="post"
rel="nofollow"> rel="nofollow">
<i class="fa fa-stop stop-env-icon"></i> <i class="fa fa-stop stop-env-icon" aria-hidden="true"></i>
</a> </a>
`, `,
}); });
})();
/* global Vue */ /**
* Renders a terminal button to open a web terminal.
* Used in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue'); module.exports = Vue.component('terminal-button-component', {
props: {
(() => { terminalPath: {
window.gl = window.gl || {}; type: String,
window.gl.environmentsList = window.gl.environmentsList || {}; default: '',
},
gl.environmentsList.TerminalButtonComponent = Vue.component('terminal-button-component', { terminalIconSvg: {
props: { type: String,
terminalPath: { default: '',
type: String,
default: '',
},
terminalIconSvg: {
type: String,
default: '',
},
}, },
},
template: ` template: `
<a class="btn terminal-button" <a class="btn terminal-button"
:href="terminalPath"> :href="terminalPath">
<span class="js-terminal-icon-container" v-html="terminalIconSvg"></span> <span class="js-terminal-icon-container" v-html="terminalIconSvg"></span>
</a> </a>
`, `,
}); });
})();
window.Vue = require('vue'); const EnvironmentsComponent = require('./components/environment');
require('./components/environment');
require('../vue_shared/vue_resource_interceptor'); require('../vue_shared/vue_resource_interceptor');
$(() => { $(() => {
...@@ -9,7 +8,7 @@ $(() => { ...@@ -9,7 +8,7 @@ $(() => {
gl.EnvironmentsListApp.$destroy(true); gl.EnvironmentsListApp.$destroy(true);
} }
gl.EnvironmentsListApp = new gl.environmentsList.EnvironmentsComponent({ gl.EnvironmentsListApp = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'), el: document.querySelector('#environments-list-view'),
}); });
}); });
const Vue = window.Vue = require('vue'); const Vue = require('vue');
class EnvironmentsService { class EnvironmentsService {
constructor(endpoint) { constructor(endpoint) {
......
/* global Vue */ /* global Vue */
window.Vue = require('vue');
(() => { (() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
......
require('~/environments/components/environment_actions'); const ActionsComponent = require('~/environments/components/environment_actions');
describe('Actions Component', () => { describe('Actions Component', () => {
preloadFixtures('static/environments/element.html.raw'); preloadFixtures('static/environments/element.html.raw');
...@@ -19,7 +19,7 @@ describe('Actions Component', () => { ...@@ -19,7 +19,7 @@ describe('Actions Component', () => {
}, },
]; ];
const component = new window.gl.environmentsList.ActionsComponent({ const component = new ActionsComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
actions: actionsMock, actions: actionsMock,
...@@ -47,7 +47,7 @@ describe('Actions Component', () => { ...@@ -47,7 +47,7 @@ describe('Actions Component', () => {
}, },
]; ];
const component = new window.gl.environmentsList.ActionsComponent({ const component = new ActionsComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
actions: actionsMock, actions: actionsMock,
......
require('~/environments/components/environment_external_url'); const ExternalUrlComponent = require('~/environments/components/environment_external_url');
describe('External URL Component', () => { describe('External URL Component', () => {
preloadFixtures('static/environments/element.html.raw'); preloadFixtures('static/environments/element.html.raw');
...@@ -8,7 +8,7 @@ describe('External URL Component', () => { ...@@ -8,7 +8,7 @@ describe('External URL Component', () => {
it('should link to the provided externalUrl prop', () => { it('should link to the provided externalUrl prop', () => {
const externalURL = 'https://gitlab.com'; const externalURL = 'https://gitlab.com';
const component = new window.gl.environmentsList.ExternalUrlComponent({ const component = new ExternalUrlComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
externalUrl: externalURL, externalUrl: externalURL,
......
window.timeago = require('vendor/timeago'); window.timeago = require('vendor/timeago');
require('~/environments/components/environment_item'); const EnvironmentItem = require('~/environments/components/environment_item');
fdescribe('Environment item', () => { describe('Environment item', () => {
preloadFixtures('static/environments/table.html.raw'); preloadFixtures('static/environments/table.html.raw');
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/table.html.raw'); loadFixtures('static/environments/table.html.raw');
...@@ -21,7 +21,7 @@ fdescribe('Environment item', () => { ...@@ -21,7 +21,7 @@ fdescribe('Environment item', () => {
}, },
}; };
component = new window.gl.environmentsList.EnvironmentItem({ component = new EnvironmentItem({
el: document.querySelector('tr#environment-row'), el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: mockItem, model: mockItem,
...@@ -111,7 +111,7 @@ fdescribe('Environment item', () => { ...@@ -111,7 +111,7 @@ fdescribe('Environment item', () => {
}, },
}; };
component = new window.gl.environmentsList.EnvironmentItem({ component = new EnvironmentItem({
el: document.querySelector('tr#environment-row'), el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: environment, model: environment,
......
require('~/environments/components/environment_rollback'); const RollbackComponent = require('~/environments/components/environment_rollback');
describe('Rollback Component', () => { describe('Rollback Component', () => {
preloadFixtures('static/environments/element.html.raw'); preloadFixtures('static/environments/element.html.raw');
...@@ -10,7 +10,7 @@ describe('Rollback Component', () => { ...@@ -10,7 +10,7 @@ describe('Rollback Component', () => {
}); });
it('Should link to the provided retryUrl', () => { it('Should link to the provided retryUrl', () => {
const component = new window.gl.environmentsList.RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
...@@ -22,7 +22,7 @@ describe('Rollback Component', () => { ...@@ -22,7 +22,7 @@ describe('Rollback Component', () => {
}); });
it('Should render Re-deploy label when isLastDeployment is true', () => { it('Should render Re-deploy label when isLastDeployment is true', () => {
const component = new window.gl.environmentsList.RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
...@@ -34,7 +34,7 @@ describe('Rollback Component', () => { ...@@ -34,7 +34,7 @@ describe('Rollback Component', () => {
}); });
it('Should render Rollback label when isLastDeployment is false', () => { it('Should render Rollback label when isLastDeployment is false', () => {
const component = new window.gl.environmentsList.RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
......
/* global Vue, environment */ const Vue = require('vue');
require('~/flash'); require('~/flash');
require('~/environments/components/environment'); const EnvironmentsComponent = require('~/environments/components/environment');
const { environment } = require('./mock_data'); const { environment } = require('./mock_data');
describe('Environment', () => { describe('Environment', () => {
...@@ -32,7 +31,7 @@ describe('Environment', () => { ...@@ -32,7 +31,7 @@ describe('Environment', () => {
}); });
it('should render the empty state', (done) => { it('should render the empty state', (done) => {
component = new gl.environmentsList.EnvironmentsComponent({ component = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'), el: document.querySelector('#environments-list-view'),
}); });
...@@ -72,7 +71,7 @@ describe('Environment', () => { ...@@ -72,7 +71,7 @@ describe('Environment', () => {
}); });
it('should render a table with environments', (done) => { it('should render a table with environments', (done) => {
component = new gl.environmentsList.EnvironmentsComponent({ component = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'), el: document.querySelector('#environments-list-view'),
}); });
...@@ -104,7 +103,7 @@ describe('Environment', () => { ...@@ -104,7 +103,7 @@ describe('Environment', () => {
}); });
it('should render empty state', (done) => { it('should render empty state', (done) => {
component = new gl.environmentsList.EnvironmentsComponent({ component = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'), el: document.querySelector('#environments-list-view'),
}); });
......
require('~/environments/components/environment_stop'); const StopComponent = require('~/environments/components/environment_stop');
describe('Stop Component', () => { describe('Stop Component', () => {
preloadFixtures('static/environments/element.html.raw'); preloadFixtures('static/environments/element.html.raw');
...@@ -10,7 +10,7 @@ describe('Stop Component', () => { ...@@ -10,7 +10,7 @@ describe('Stop Component', () => {
loadFixtures('static/environments/element.html.raw'); loadFixtures('static/environments/element.html.raw');
stopURL = '/stop'; stopURL = '/stop';
component = new window.gl.environmentsList.StopComponent({ component = new StopComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
stopUrl: stopURL, stopUrl: stopURL,
......
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