const Vue = require('vue'); const Timeago = require('timeago.js'); require('../../lib/utils/text_utility'); require('../../vue_shared/components/commit'); const ActionsComponent = require('./environment_actions'); const ExternalUrlComponent = require('./environment_external_url'); const StopComponent = require('./environment_stop'); const RollbackComponent = require('./environment_rollback'); 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, required: false, default: false, }, canReadEnvironment: { type: Boolean, required: false, default: false, }, }, computed: { /** * Verifies if `last_deployment` key exists in the current Envrionment. * This key is required to render most of the html - this method works has * an helper. * * @returns {Boolean} */ hasLastDeploymentKey() { if (this.model && this.model.last_deployment && !this.$options.isObjectEmpty(this.model.last_deployment)) { return true; } return false; }, /** * Verifies is the given environment has manual actions. * Used to verify if we should render them or nor. * * @returns {Boolean|Undefined} */ hasManualActions() { return this.model && this.model.last_deployment && this.model.last_deployment.manual_actions && this.model.last_deployment.manual_actions.length > 0; }, /** * Returns the value of the `stop_action?` key provided in the response. * * @returns {Boolean} */ hasStopAction() { return this.model && this.model['stop_action?']; }, /** * Verifies if the `deployable` key is present in `last_deployment` key. * Used to verify whether we should or not render the rollback partial. * * @returns {Boolean|Undefined} */ canRetry() { return this.model && this.hasLastDeploymentKey && this.model.last_deployment && this.model.last_deployment.deployable; }, /** * Verifies if the date to be shown is present. * * @returns {Boolean|Undefined} */ canShowDate() { return this.model && this.model.last_deployment && this.model.last_deployment.deployable && this.model.last_deployment.deployable !== undefined; }, /** * Human readable date. * * @returns {String} */ createdDate() { if (this.model && this.model.last_deployment && this.model.last_deployment.deployable && this.model.last_deployment.deployable.created_at) { return timeagoInstance.format(this.model.last_deployment.deployable.created_at); } return ''; }, /** * Returns the manual actions with the name parsed. * * @returns {Array.<Object>|Undefined} */ manualActions() { if (this.hasManualActions) { return this.model.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 && this.model.last_deployment && this.model.last_deployment.user && this.model.last_deployment.user.username) { return `${this.model.last_deployment.user.username}'s avatar'`; } return ''; }, /** * If provided, returns the commit tag. * * @returns {String|Undefined} */ commitTag() { if (this.model && this.model.last_deployment && this.model.last_deployment.tag) { return this.model.last_deployment.tag; } return undefined; }, /** * If provided, returns the commit ref. * * @returns {Object|Undefined} */ commitRef() { if (this.model && this.model.last_deployment && this.model.last_deployment.ref) { return this.model.last_deployment.ref; } return undefined; }, /** * If provided, returns the commit url. * * @returns {String|Undefined} */ commitUrl() { if (this.model && this.model.last_deployment && this.model.last_deployment.commit && this.model.last_deployment.commit.commit_path) { return this.model.last_deployment.commit.commit_path; } return undefined; }, /** * If provided, returns the commit short sha. * * @returns {String|Undefined} */ commitShortSha() { if (this.model && this.model.last_deployment && this.model.last_deployment.commit && this.model.last_deployment.commit.short_id) { return this.model.last_deployment.commit.short_id; } return undefined; }, /** * If provided, returns the commit title. * * @returns {String|Undefined} */ commitTitle() { if (this.model && this.model.last_deployment && this.model.last_deployment.commit && this.model.last_deployment.commit.title) { return this.model.last_deployment.commit.title; } return undefined; }, /** * If provided, returns the commit tag. * * @returns {Object|Undefined} */ commitAuthor() { if (this.model && this.model.last_deployment && this.model.last_deployment.commit && this.model.last_deployment.commit.author) { return this.model.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 && this.model.last_deployment && this.model.last_deployment.deployable && this.model.last_deployment.deployable.retry_path) { return this.model.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 && this.model.last_deployment && this.model.last_deployment['last?']; }, /** * Builds the name of the builds needed to display both the name and the id. * * @returns {String} */ buildName() { if (this.model && this.model.last_deployment && this.model.last_deployment.deployable) { return `${this.model.last_deployment.deployable.name} #${this.model.last_deployment.deployable.id}`; } return ''; }, /** * Builds the needed string to show the internal id. * * @returns {String} */ deploymentInternalId() { if (this.model && this.model.last_deployment && this.model.last_deployment.iid) { return `#${this.model.last_deployment.iid}`; } return ''; }, /** * Verifies if the user object is present under last_deployment object. * * @returns {Boolean} */ deploymentHasUser() { return this.model && !this.$options.isObjectEmpty(this.model.last_deployment) && !this.$options.isObjectEmpty(this.model.last_deployment.user); }, /** * Returns the user object nested with the last_deployment object. * Used to render the template. * * @returns {Object} */ deploymentUser() { if (this.model && !this.$options.isObjectEmpty(this.model.last_deployment) && !this.$options.isObjectEmpty(this.model.last_deployment.user)) { return this.model.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.last_deployment) && !this.$options.isObjectEmpty(this.model.last_deployment.deployable); }, /** * Verifies the presence of all the keys needed to render the buil_path. * * @return {String} */ buildPath() { if (this.model && this.model.last_deployment && this.model.last_deployment.deployable && this.model.last_deployment.deployable.build_path) { return this.model.last_deployment.deployable.build_path; } return ''; }, /** * Verifies the presence of all the keys needed to render the external_url. * * @return {String} */ externalURL() { if (this.model && this.model.external_url) { return this.model.external_url; } return ''; }, /** * 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.last_deployment) && this.model.last_deployment.iid !== undefined; }, environmentPath() { if (this.model && this.model.environment_path) { return this.model.environment_path; } return ''; }, /** * Constructs folder URL based on the current location and the folder id. * * @return {String} */ folderUrl() { return `${window.location.pathname}/folders/${this.model.folderName}`; }, }, /** * 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="environmentPath"> {{model.name}} </a> <a v-else class="folder-name" :href="folderUrl"> <span class="folder-icon"> <i class="fa fa-folder" aria-hidden="true"></i> </span> <span> {{model.folderName}} </span> <span class="badge"> {{model.size}} </span> </a> </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> </span> </td> <td class="environments-build-cell"> <a v-if="shouldRenderBuildName" class="build-link" :href="buildPath"> {{buildName}} </a> </td> <td> <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"/> </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 environments-actions"> <div v-if="!model.isFolder" class="btn-group" role="group"> <actions-component v-if="hasManualActions && canCreateDeployment" :actions="manualActions"/> <external-url-component v-if="externalURL && canReadEnvironment" :external-url="externalURL"/> <stop-component v-if="hasStopAction && canCreateDeployment" :stop-url="model.stop_path"/> <terminal-button-component v-if="model && model.terminal_path" :terminal-path="model.terminal_path"/> <rollback-component v-if="canRetry && canCreateDeployment" :is-last-deployment="isLastDeployment" :retry-url="retryUrl"/> </div> </td> </tr> `, });