Commit 7c7f5266 authored by Filipa Lacerda's avatar Filipa Lacerda

[ci skip] Fix more rules

parent 1525b005
......@@ -89,6 +89,7 @@ export default {
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath"
:update-filters="true" />
:update-filters="true"
/>
</li>
</template>
......@@ -77,12 +77,12 @@ which incur additional costs. See %{pricingLink}`)),
return sprintf(
_.escape(s__(`ClusterIntegration|Prometheus is an open-source monitoring system
with %{gitlabIntegrationLink} to monitor deployed applications.`)),
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
</a>`,
},
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
</a>`,
},
false,
);
},
......
......@@ -12,7 +12,7 @@
props: {
items: {
type: Array,
default: []
default: () => [],
},
stage: {
type: Object,
......
......@@ -13,7 +13,7 @@
props: {
items: {
type: Array,
default: []
default: () => [],
},
stage: {
type: Object,
......
......@@ -14,7 +14,7 @@
props: {
items: {
type: Array,
default: []
default: () => [],
},
stage: {
type: Object,
......@@ -81,8 +81,7 @@
name="fork"
:size="16"
/>
<a
:href="mergeRequest.branch.url">
<a :href="mergeRequest.branch.url">
{{ mergeRequest.branch.name }}
</a>
</span>
......
......@@ -15,7 +15,7 @@
props: {
items: {
type: Array,
default: []
default: () => [],
},
stage: {
type: Object,
......@@ -69,7 +69,7 @@
<a
:href="build.commitUrl"
class="commit-sha"
>
>
{{ build.shortSha }}
</a>
</h5>
......@@ -77,7 +77,7 @@
<a
:href="build.url"
class="build-date"
>
>
{{ build.date }}
</a>
{{ s__('ByAuthor|by') }}
......
......@@ -6,15 +6,21 @@
import icon from '../../vue_shared/components/icon.vue';
export default {
props: {
items: Array,
stage: Object,
},
components: {
totalTime,
limitWarning,
icon,
},
props: {
items: {
type: Array,
default: () => [],
},
stage: {
type: Object,
default: () => ({}),
},
},
computed: {
iconBuildStatus() {
return iconBuildStatus;
......@@ -35,29 +41,59 @@
<li
v-for="(build, i) in items"
:key="i"
class="stage-event-item item-build-component">
class="stage-event-item item-build-component"
>
<div class="item-details">
<h5 class="item-title">
<span class="icon-build-status" v-html="iconBuildStatus"></span>
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
<span
class="icon-build-status"
v-html="iconBuildStatus"
>
</span>
<a
:href="build.url"
class="item-build-name"
>
{{ build.name }}
</a>
&middot;
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
<a
:href="build.url"
class="pipeline-id"
>
#{{ build.id }}
</a>
<icon
name="fork"
:size="16">
</icon>
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
<span class="icon-branch" v-html="iconBranch"></span>
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
:size="16"
/>
<a
:href="build.branch.url"
class="ref-name"
>
{{ build.branch.name }}
</a>
<span
class="icon-branch"
v-html="iconBranch"
>
</span>
<a
:href="build.commitUrl"
class="commit-sha">
{{ build.shortSha }}
</a>
</h5>
<span>
<a :href="build.url" class="issue-date">
<a
:href="build.url"
class="issue-date">
{{ build.date }}
</a>
</span>
</div>
<div class="item-time">
<total-time :time="build.totalTime"/>
<total-time :time="build.totalTime" />
</div>
</li>
</ul>
......
......@@ -17,10 +17,30 @@
<template>
<span class="total-time">
<template v-if="hasData">
<template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template>
<template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template>
<template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template>
<template v-if="time.seconds && hasData === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template>
<template v-if="time.days">
{{ time.days }}
<span>
{{ n__('day', 'days', time.days) }}
</span>
</template>
<template v-if="time.hours">
{{ time.hours }}
<span>
{{ n__('Time|hr', 'Time|hrs', time.hours) }}
</span>
</template>
<template v-if="time.mins && !time.days">
{{ time.mins }}
<span>
{{ n__('Time|min', 'Time|mins', time.mins) }}
</span>
</template>
<template v-if="time.seconds && hasData === 1 || time.seconds === 0">
{{ time.seconds }}
<span>
{{ s__('Time|s') }}
</span>
</template>
</template>
<template v-else>
--
......
......@@ -3,10 +3,8 @@
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
data() {
return {
isLoading: false,
};
components: {
loadingIcon,
},
props: {
deployKey: {
......@@ -23,11 +21,16 @@
default: 'btn-default',
},
},
components: {
loadingIcon,
data() {
return {
isLoading: false,
};
},
computed: {
text() {
return `${this.type.charAt(0).toUpperCase()}${this.type.slice(1)}`;
},
},
methods: {
doAction() {
this.isLoading = true;
......@@ -37,11 +40,6 @@
});
},
},
computed: {
text() {
return `${this.type.charAt(0).toUpperCase()}${this.type.slice(1)}`;
},
},
};
</script>
......
......@@ -7,11 +7,9 @@
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
data() {
return {
isLoading: false,
store: new DeployKeysStore(),
};
components: {
keysPanel,
loadingIcon,
},
props: {
endpoint: {
......@@ -19,6 +17,12 @@
required: true,
},
},
data() {
return {
isLoading: false,
store: new DeployKeysStore(),
};
},
computed: {
hasKeys() {
return Object.keys(this.keys).length;
......@@ -27,9 +31,20 @@
return this.store.keys;
},
},
components: {
keysPanel,
loadingIcon,
created() {
this.service = new DeployKeysService(this.endpoint);
eventHub.$on('enable.key', this.enableKey);
eventHub.$on('remove.key', this.disableKey);
eventHub.$on('disable.key', this.disableKey);
},
mounted() {
this.fetchKeys();
},
beforeDestroy() {
eventHub.$off('enable.key', this.enableKey);
eventHub.$off('remove.key', this.disableKey);
eventHub.$off('disable.key', this.disableKey);
},
methods: {
fetchKeys() {
......@@ -59,21 +74,6 @@
}
},
},
created() {
this.service = new DeployKeysService(this.endpoint);
eventHub.$on('enable.key', this.enableKey);
eventHub.$on('remove.key', this.disableKey);
eventHub.$on('disable.key', this.disableKey);
},
mounted() {
this.fetchKeys();
},
beforeDestroy() {
eventHub.$off('enable.key', this.enableKey);
eventHub.$off('remove.key', this.disableKey);
eventHub.$off('disable.key', this.disableKey);
},
};
</script>
......
......@@ -3,6 +3,9 @@
import { getTimeago } from '../../lib/utils/datetime_utility';
export default {
components: {
actionBtn,
},
props: {
deployKey: {
type: Object,
......@@ -17,9 +20,6 @@
required: true,
},
},
components: {
actionBtn,
},
computed: {
timeagoDate() {
return getTimeago().format(this.deployKey.created_at);
......@@ -61,9 +61,10 @@
</div>
<div class="deploy-key-content prepend-left-default deploy-key-projects">
<a
v-for="project in deployKey.projects"
v-for="(project, i) in deployKey.projects"
class="label deploy-project-label"
:href="project.full_path"
:key="i"
>
{{ project.full_name }}
</a>
......
......@@ -2,6 +2,9 @@
import key from './key.vue';
export default {
components: {
key,
},
props: {
title: {
type: String,
......@@ -25,9 +28,6 @@
required: true,
},
},
components: {
key,
},
};
</script>
......@@ -37,12 +37,14 @@
{{ title }}
({{ keys.length }})
</h5>
<ul class="well-list"
<ul
class="well-list"
v-if="keys.length"
>
<li
v-for="deployKey in keys"
:key="deployKey.id">
:key="deployKey.id"
>
<key
:deploy-key="deployKey"
:store="store"
......
......@@ -4,6 +4,11 @@
import environmentTable from '../components/environments_table.vue';
export default {
components: {
environmentTable,
loadingIcon,
tablePagination,
},
props: {
isLoading: {
type: Boolean,
......@@ -26,12 +31,6 @@
required: true,
},
},
components: {
environmentTable,
loadingIcon,
tablePagination,
},
methods: {
onChangePage(page) {
this.$emit('onChangePage', page);
......@@ -47,7 +46,7 @@
label="Loading environments"
v-if="isLoading"
size="3"
/>
/>
<slot name="emptyState"></slot>
......@@ -59,13 +58,13 @@
:environments="environments"
:can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
/>
/>
<table-pagination
v-if="pagination && pagination.totalPages > 1"
:change="onChangePage"
:pageInfo="pagination"
/>
:page-info="pagination"
/>
</div>
</div>
</template>
<script>
export default {
name: 'environmentsEmptyState',
name: 'EnvironmentsEmptyState',
props: {
newPath: {
type: String,
......@@ -21,21 +21,22 @@
<div class="blank-state-row">
<div class="blank-state-center">
<h2 class="blank-state-title js-blank-state-title">
{{s__("Environments|You don't have any environments right now.")}}
{{ s__("Environments|You don't have any environments right now.") }}
</h2>
<p class="blank-state-text">
{{s__("Environments|Environments are places where code gets deployed, such as staging or production.")}}
{{ s__("Environments|Environments are places where code gets deployed, such as staging or production.") }}
<br />
<a :href="helpPath">
{{s__("Environments|Read more about environments")}}
{{ s__("Environments|Read more about environments") }}
</a>
</p>
<a
v-if="canCreateEnvironment"
:href="newPath"
class="btn btn-create js-new-environment-button">
{{s__("Environments|New environment")}}
class="btn btn-create js-new-environment-button"
>
{{ s__("Environments|New environment") }}
</a>
</div>
</div>
......
<script>
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
actions: {
type: Array,
required: false,
default: () => [],
export default {
directives: {
tooltip,
},
},
directives: {
tooltip,
},
components: {
loadingIcon,
},
components: {
loadingIcon,
},
props: {
actions: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
playIconSvg,
isLoading: false,
};
},
data() {
return {
playIconSvg,
isLoading: false,
};
},
computed: {
title() {
return 'Deploy to...';
computed: {
title() {
return 'Deploy to...';
},
},
},
methods: {
onClickAction(endpoint) {
this.isLoading = true;
methods: {
onClickAction(endpoint) {
this.isLoading = true;
eventHub.$emit('postAction', endpoint);
},
eventHub.$emit('postAction', endpoint);
},
isActionDisabled(action) {
if (action.playable === undefined) {
return false;
}
isActionDisabled(action) {
if (action.playable === undefined) {
return false;
}
return !action.playable;
return !action.playable;
},
},
},
};
};
</script>
<template>
<div
......@@ -63,27 +62,32 @@ export default {
data-toggle="dropdown"
:title="title"
:aria-label="title"
:disabled="isLoading">
:disabled="isLoading"
>
<span>
<span v-html="playIconSvg"></span>
<i
class="fa fa-caret-down"
aria-hidden="true"/>
aria-hidden="true"
/>
<loading-icon v-if="isLoading" />
</span>
</button>
<ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions">
<li
v-for="(action, i) in actions"
:key="i">
<button
type="button"
class="js-manual-action-link no-btn btn"
@click="onClickAction(action.play_path)"
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)">
:disabled="isActionDisabled(action)"
>
<span v-html="playIconSvg"></span>
<span>
{{action.name}}
{{ action.name }}
</span>
</button>
</li>
......
<script>
import tooltip from '../../vue_shared/directives/tooltip';
import { s__ } from '../../locale';
import tooltip from '../../vue_shared/directives/tooltip';
import { s__ } from '../../locale';
/**
* Renders the external url link in environments table.
*/
export default {
props: {
externalUrl: {
type: String,
required: true,
/**
* Renders the external url link in environments table.
*/
export default {
directives: {
tooltip,
},
props: {
externalUrl: {
type: String,
required: true,
},
},
},
directives: {
tooltip,
},
computed: {
title() {
return s__('Environments|Open');
computed: {
title() {
return s__('Environments|Open');
},
},
},
};
};
</script>
<template>
<a
......@@ -33,9 +32,12 @@ export default {
rel="noopener noreferrer nofollow"
:title="title"
:aria-label="title"
:href="externalUrl">
:href="externalUrl"
>
<i
class="fa fa-external-link"
aria-hidden="true" />
aria-hidden="true"
>
</i>
</a>
</template>
<script>
import Timeago from 'timeago.js';
import _ from 'underscore';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '../../lib/utils/text_utility';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop.vue';
import RollbackComponent from './environment_rollback.vue';
import TerminalButtonComponent from './environment_terminal_button.vue';
import MonitoringButtonComponent from './environment_monitoring.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import eventHub from '../event_hub';
/**
* Envrionment Item Component
*
* Renders a table row for each environment.
*/
const timeagoInstance = new Timeago();
export default {
components: {
userAvatarLink,
'commit-component': CommitComponent,
'actions-component': ActionsComponent,
'external-url-component': ExternalUrlComponent,
'stop-component': StopComponent,
'rollback-component': RollbackComponent,
'terminal-button-component': TerminalButtonComponent,
'monitoring-button-component': MonitoringButtonComponent,
},
props: {
model: {
type: Object,
required: true,
default: () => ({}),
import Timeago from 'timeago.js';
import _ from 'underscore';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '../../lib/utils/text_utility';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop.vue';
import RollbackComponent from './environment_rollback.vue';
import TerminalButtonComponent from './environment_terminal_button.vue';
import MonitoringButtonComponent from './environment_monitoring.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import eventHub from '../event_hub';
/**
* Envrionment Item Component
*
* Renders a table row for each environment.
*/
const timeagoInstance = new Timeago();
export default {
components: {
userAvatarLink,
'commit-component': CommitComponent,
'actions-component': ActionsComponent,
'external-url-component': ExternalUrlComponent,
'stop-component': StopComponent,
'rollback-component': RollbackComponent,
'terminal-button-component': TerminalButtonComponent,
'monitoring-button-component': MonitoringButtonComponent,
},
canCreateDeployment: {
type: Boolean,
required: false,
default: false,
props: {
model: {
type: Object,
required: true,
default: () => ({}),
},
canCreateDeployment: {
type: Boolean,
required: false,
default: false,
},
canReadEnvironment: {
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 &&
!_.isEmpty(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: humanize(action.name),
play_path: action.play_path,
playable: action.playable,
};
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) {
const deployable = this.model.last_deployment.deployable;
return `${deployable.name} #${deployable.id}`;
}
return '';
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 &&
!_.isEmpty(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: humanize(action.name),
play_path: action.play_path,
playable: action.playable,
};
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) {
const deployable = this.model.last_deployment.deployable;
return `${deployable.name} #${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 &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
this.model.last_deployment.iid !== undefined;
},
environmentPath() {
if (this.model && this.model.environment_path) {
return this.model.environment_path;
}
return '';
},
monitoringUrl() {
if (this.model && this.model.metrics_path) {
return this.model.metrics_path;
}
return '';
},
displayEnvironmentActions() {
return this.hasManualActions ||
this.externalURL ||
this.monitoringUrl ||
this.hasStopAction ||
this.canRetry;
},
},
/**
* 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 '';
methods: {
onClickFolder() {
eventHub.$emit('toggleFolder', this.model);
},
},
/**
* Verifies if the user object is present under last_deployment object.
*
* @returns {Boolean}
*/
deploymentHasUser() {
return this.model &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
!_.isEmpty(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 &&
!_.isEmpty(this.model.last_deployment) &&
this.model.last_deployment.iid !== undefined;
},
environmentPath() {
if (this.model && this.model.environment_path) {
return this.model.environment_path;
}
return '';
},
monitoringUrl() {
if (this.model && this.model.metrics_path) {
return this.model.metrics_path;
}
return '';
},
displayEnvironmentActions() {
return this.hasManualActions ||
this.externalURL ||
this.monitoringUrl ||
this.hasStopAction ||
this.canRetry;
},
},
methods: {
onClickFolder() {
eventHub.$emit('toggleFolder', this.model);
},
},
};
};
</script>
<template>
<div
......@@ -428,18 +428,22 @@ export default {
'folder-row': model.isFolder,
}"
role="row">
<div class="table-section section-10" role="gridcell">
<div
class="table-section section-10"
role="gridcell"
>
<div
v-if="!model.isFolder"
class="table-mobile-header"
role="rowheader">
{{s__("Environments|Environment")}}
role="rowheader"
>
{{ s__("Environments|Environment") }}
</div>
<a
v-if="!model.isFolder"
class="environment-name flex-truncate-parent table-mobile-content"
:href="environmentPath">
<span class="flex-truncate-child">{{model.name}}</span>
<span class="flex-truncate-child">{{ model.name }}</span>
</a>
<span
v-else
......@@ -451,17 +455,22 @@ export default {
<i
v-show="model.isOpen"
class="fa fa-caret-down"
aria-hidden="true" />
aria-hidden="true"
>
</i>
<i
v-show="!model.isOpen"
class="fa fa-caret-right"
aria-hidden="true"/>
aria-hidden="true"
>
</i>
</span>
<span class="folder-icon">
<i
class="fa fa-folder"
aria-hidden="true" />
aria-hidden="true">
</i>
</span>
<span>
......@@ -491,22 +500,29 @@ export default {
</span>
</div>
<div class="table-section section-15 hidden-xs hidden-sm" role="gridcell">
<div
class="table-section section-15 hidden-xs hidden-sm"
role="gridcell"
>
<a
v-if="shouldRenderBuildName"
class="build-link flex-truncate-parent"
:href="buildPath">
<span class="flex-truncate-child">{{buildName}}</span>
:href="buildPath"
>
<span class="flex-truncate-child">{{ buildName }}</span>
</a>
</div>
<div
v-if="!model.isFolder"
class="table-section section-25" role="gridcell">
class="table-section section-25"
role="gridcell"
>
<div
role="rowheader"
class="table-mobile-header">
{{s__("Environments|Commit")}}
class="table-mobile-header"
>
{{ s__("Environments|Commit") }}
</div>
<div
v-if="hasLastDeploymentKey"
......@@ -522,22 +538,24 @@ export default {
<div
v-if="!hasLastDeploymentKey"
class="commit-title table-mobile-content">
{{s__("Environments|No deployments yet")}}
{{ s__("Environments|No deployments yet") }}
</div>
</div>
<div
v-if="!model.isFolder"
class="table-section section-10" role="gridcell">
class="table-section section-10"
role="gridcell"
>
<div
role="rowheader"
class="table-mobile-header">
{{s__("Environments|Updated")}}
{{ s__("Environments|Updated") }}
</div>
<span
v-if="canShowDate"
class="environment-created-date-timeago table-mobile-content">
{{createdDate}}
{{ createdDate }}
</span>
</div>
......@@ -553,33 +571,33 @@ export default {
<actions-component
v-if="hasManualActions && canCreateDeployment"
:actions="manualActions"
/>
/>
<external-url-component
v-if="externalURL && canReadEnvironment"
:external-url="externalURL"
/>
/>
<monitoring-button-component
v-if="monitoringUrl && canReadEnvironment"
:monitoring-url="monitoringUrl"
/>
/>
<terminal-button-component
v-if="model && model.terminal_path"
:terminal-path="model.terminal_path"
/>
/>
<stop-component
v-if="hasStopAction && canCreateDeployment"
:stop-url="model.stop_path"
/>
/>
<rollback-component
v-if="canRetry && canCreateDeployment"
:is-last-deployment="isLastDeployment"
:retry-url="retryUrl"
/>
/>
</div>
</div>
</div>
......
......@@ -56,7 +56,10 @@
this.updateTaskStatusText();
},
},
mounted() {
this.renderGFM();
this.updateTaskStatusText();
},
methods: {
renderGFM() {
$(this.$refs['gfm-content']).renderGFM();
......@@ -91,7 +94,7 @@
$tasksShort.text(
`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ?
's' :
''}`
''}`,
);
} else {
$tasks.text('');
......@@ -99,10 +102,6 @@
}
},
},
mounted() {
this.renderGFM();
this.updateTaskStatusText();
},
};
</script>
......@@ -112,7 +111,8 @@
class="description"
:class="{
'js-task-list-container': canUpdate
}">
}"
>
<div
class="wiki"
:class="{
......
<script>
import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
export default {
props: {
updatedAt: {
type: String,
required: false,
default: '',
export default {
components: {
timeAgoTooltip,
},
updatedByName: {
type: String,
required: false,
default: '',
props: {
updatedAt: {
type: String,
required: false,
default: '',
},
updatedByName: {
type: String,
required: false,
default: '',
},
updatedByPath: {
type: String,
required: false,
default: '',
},
},
updatedByPath: {
type: String,
required: false,
default: '',
computed: {
hasUpdatedBy() {
return this.updatedByName && this.updatedByPath;
},
},
},
components: {
timeAgoTooltip,
},
computed: {
hasUpdatedBy() {
return this.updatedByName && this.updatedByPath;
},
},
};
};
</script>
<template>
......@@ -48,7 +48,7 @@ export default {
class="author_link"
:href="updatedByPath"
>
<span>{{updatedByName}}</span>
<span>{{ updatedByName }}</span>
</a>
</span>
</small>
......
......@@ -4,6 +4,9 @@
export default {
mixins: [updateMixin],
components: {
markdownField,
},
props: {
formState: {
type: Object,
......@@ -28,9 +31,6 @@
default: true,
},
},
components: {
markdownField,
},
mounted() {
this.$refs.textarea.focus();
},
......
......@@ -6,6 +6,13 @@
import descriptionTemplate from './fields/description_template.vue';
export default {
components: {
lockedWarning,
titleField,
descriptionField,
descriptionTemplate,
editActions,
},
props: {
canDestroy: {
type: Boolean,
......@@ -52,13 +59,6 @@
default: true,
},
},
components: {
lockedWarning,
titleField,
descriptionField,
descriptionTemplate,
editActions,
},
computed: {
hasIssuableTemplates() {
return this.issuableTemplates.length;
......@@ -78,16 +78,19 @@
:form-state="formState"
:issuable-templates="issuableTemplates"
:project-path="projectPath"
:project-namespace="projectNamespace" />
:project-namespace="projectNamespace"
/>
</div>
<div
:class="{
'col-sm-8 col-lg-9': hasIssuableTemplates,
'col-xs-12': !hasIssuableTemplates,
}">
}"
>
<title-field
:form-state="formState"
:issuable-templates="issuableTemplates" />
:issuable-templates="issuableTemplates"
/>
</div>
</div>
<description-field
......@@ -100,6 +103,7 @@
<edit-actions
:form-state="formState"
:can-destroy="canDestroy"
:show-delete-button="showDeleteButton" />
:show-delete-button="showDeleteButton"
/>
</form>
</template>
......@@ -6,12 +6,8 @@
export default {
mixins: [animateMixin],
data() {
return {
preAnimation: false,
pulseAnimation: false,
titleEl: document.querySelector('title'),
};
directives: {
tooltip,
},
props: {
issuableRef: {
......@@ -37,8 +33,17 @@
default: false,
},
},
directives: {
tooltip,
data() {
return {
preAnimation: false,
pulseAnimation: false,
titleEl: document.querySelector('title'),
};
},
computed: {
pencilIcon() {
return spriteIcon('pencil', 'link-highlight');
},
},
watch: {
titleHtml() {
......@@ -46,11 +51,6 @@
this.animateChange();
},
},
computed: {
pencilIcon() {
return spriteIcon('pencil', 'link-highlight');
},
},
methods: {
setPageTitle() {
const currentPageTitleScope = this.titleEl.innerText.split('·');
......@@ -85,7 +85,7 @@
data-placement="bottom"
data-container="body"
@click="edit"
>
>
</button>
</div>
</template>
......@@ -4,6 +4,10 @@
export default {
name: 'jobHeaderSection',
components: {
ciHeader,
loadingIcon,
},
props: {
job: {
type: Object,
......@@ -14,10 +18,6 @@
required: true,
},
},
components: {
ciHeader,
loadingIcon,
},
data() {
return {
actions: this.getActions(),
......@@ -31,6 +31,11 @@
return !this.isLoading && Object.keys(this.job).length;
},
},
watch: {
job() {
this.actions = this.getActions();
},
},
methods: {
getActions() {
const actions = [];
......@@ -46,11 +51,6 @@
return actions;
},
},
watch: {
job() {
this.actions = this.getActions();
},
},
};
</script>
<template>
......@@ -63,11 +63,11 @@
:time="job.created_at"
:user="job.user"
:actions="actions"
:hasSidebarButton="true"
/>
:has-sidebar-button="true"
/>
<loading-icon
v-if="isLoading"
size="2"
/>
/>
</div>
</template>
......@@ -23,9 +23,10 @@
<p class="build-detail-row">
<span
v-if="hasTitle"
class="build-light-text">
{{title}}:
class="build-light-text"
>
{{ title }}:
</span>
{{value}}
{{ value }}
</p>
</template>
......@@ -6,6 +6,13 @@
export default {
name: 'SidebarDetailsBlock',
components: {
detailRow,
loadingIcon,
},
mixins: [
timeagoMixin,
],
props: {
job: {
type: Object,
......@@ -16,13 +23,6 @@
required: true,
},
},
mixins: [
timeagoMixin,
],
components: {
detailRow,
loadingIcon,
},
computed: {
shouldRenderContent() {
return !this.isLoading && Object.keys(this.job).length > 0;
......@@ -58,11 +58,13 @@
<template v-if="shouldRenderContent">
<div
class="block retry-link"
v-if="job.retry_path || job.new_issue_path">
v-if="job.retry_path || job.new_issue_path"
>
<a
v-if="job.new_issue_path"
class="js-new-issue btn btn-new btn-inverted"
:href="job.new_issue_path">
:href="job.new_issue_path"
>
New issue
</a>
<a
......@@ -70,20 +72,21 @@
class="js-retry-job btn btn-inverted-secondary"
:href="job.retry_path"
data-method="post"
rel="nofollow">
rel="nofollow"
>
Retry
</a>
</div>
<div :class="{block : renderBlock }">
<p
class="build-detail-row js-job-mr"
v-if="job.merge_request">
<span
class="build-light-text">
v-if="job.merge_request"
>
<span class="build-light-text">
Merge Request:
</span>
<a :href="job.merge_request.path">
!{{job.merge_request.iid}}
!{{ job.merge_request.iid }}
</a>
</p>
......@@ -92,49 +95,49 @@
v-if="job.duration"
title="Duration"
:value="duration"
/>
/>
<detail-row
class="js-job-finished"
v-if="job.finished_at"
title="Finished"
:value="timeFormated(job.finished_at)"
/>
/>
<detail-row
class="js-job-erased"
v-if="job.erased_at"
title="Erased"
:value="timeFormated(job.erased_at)"
/>
/>
<detail-row
class="js-job-queued"
v-if="job.queued"
title="Queued"
:value="queued"
/>
/>
<detail-row
class="js-job-runner"
v-if="job.runner"
title="Runner"
:value="runnerId"
/>
/>
<detail-row
class="js-job-coverage"
v-if="job.coverage"
title="Coverage"
:value="coverage"
/>
/>
<p
class="build-detail-row js-job-tags"
v-if="job.tags.length">
<span
class="build-light-text">
v-if="job.tags.length"
>
<span class="build-light-text">
Tags:
</span>
<span
v-for="tag in job.tags"
key="tag"
v-for="(tag, i) in job.tags"
:key="i"
class="label label-primary">
{{tag}}
{{ tag }}
</span>
</p>
......@@ -146,7 +149,8 @@
class="js-cancel-job btn btn-sm btn-default"
:href="job.cancel_path"
data-method="post"
rel="nofollow">
rel="nofollow"
>
Cancel
</a>
</div>
......@@ -156,6 +160,6 @@
class="prepend-top-10"
v-if="isLoading"
size="2"
/>
/>
</div>
</template>
......@@ -11,6 +11,12 @@
export default {
components: {
Graph,
GraphGroup,
EmptyState,
},
data() {
const metricsData = document.querySelector('#prometheus-graphs').dataset;
const store = new MonitoringStore();
......@@ -36,12 +42,30 @@
};
},
components: {
Graph,
GraphGroup,
EmptyState,
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
});
eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$on('hoverChanged', this.hoverChanged);
},
beforeDestroy() {
eventHub.$off('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$off('hoverChanged', this.hoverChanged);
window.removeEventListener('resize', this.resizeThrottled, false);
},
mounted() {
this.resizeThrottled = _.throttle(this.resize, 600);
if (!this.hasMetrics) {
this.state = 'gettingStarted';
} else {
this.getGraphsData();
window.addEventListener('resize', this.resizeThrottled, false);
}
},
methods: {
getGraphsData() {
this.state = 'loading';
......@@ -72,36 +96,14 @@
this.hoverData = data;
},
},
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
});
eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$on('hoverChanged', this.hoverChanged);
},
beforeDestroy() {
eventHub.$off('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$off('hoverChanged', this.hoverChanged);
window.removeEventListener('resize', this.resizeThrottled, false);
},
mounted() {
this.resizeThrottled = _.throttle(this.resize, 600);
if (!this.hasMetrics) {
this.state = 'gettingStarted';
} else {
this.getGraphsData();
window.addEventListener('resize', this.resizeThrottled, false);
}
},
};
</script>
<template>
<div v-if="!showEmptyState" class="prometheus-graphs">
<div
v-if="!showEmptyState"
class="prometheus-graphs"
>
<graph-group
v-for="(groupData, index) in store.groups"
:key="index"
......
......@@ -76,20 +76,26 @@ If this takes a long time, ensure that data is available.`,
<template>
<div class="prometheus-state">
<div class="state-svg svg-content">
<img :src="currentState.svgUrl"/>
<img :src="currentState.svgUrl" />
</div>
<h4 class="state-title">
{{currentState.title}}
{{ currentState.title }}
</h4>
<p class="state-description">
{{currentState.description}}
<a v-if="showButtonDescription" :href="settingsPath">
{{ currentState.description }}
<a
v-if="showButtonDescription"
:href="settingsPath"
>
Prometheus server
</a>
</p>
<div class="state-button">
<a class="btn btn-success" :href="buttonPath">
{{currentState.buttonText}}
<a
class="btn btn-success"
:href="buttonPath"
>
{{ currentState.buttonText }}
</a>
</div>
</div>
......
......@@ -3,10 +3,10 @@
import { axisLeft, axisBottom } from 'd3-axis';
import { max, extent } from 'd3-array';
import { select } from 'd3-selection';
import GraphLegend from './graph/legend.vue';
import GraphFlag from './graph/flag.vue';
import GraphDeployment from './graph/deployment.vue';
import GraphPath from './graph/path.vue';
import graphLegend from './graph/legend.vue';
import graphFlag from './graph/flag.vue';
import graphDeployment from './graph/deployment.vue';
import graphPath from './graph/path.vue';
import MonitoringMixin from '../mixins/monitoring_mixins';
import eventHub from '../event_hub';
import measurements from '../utils/measurements';
......@@ -17,6 +17,16 @@
const d3 = { scaleLinear, scaleTime, axisLeft, axisBottom, max, extent, select };
export default {
components: {
graphLegend,
graphFlag,
graphDeployment,
graphPath,
},
mixins: [MonitoringMixin],
props: {
graphData: {
type: Object,
......@@ -45,8 +55,6 @@
},
},
mixins: [MonitoringMixin],
data() {
return {
baseGraphHeight: 450,
......@@ -74,13 +82,6 @@
};
},
components: {
GraphLegend,
GraphFlag,
GraphDeployment,
GraphPath,
},
computed: {
outerViewBox() {
return `0 0 ${this.baseGraphWidth} ${this.baseGraphHeight}`;
......@@ -104,6 +105,26 @@
},
},
watch: {
updateAspectRatio() {
if (this.updateAspectRatio) {
this.graphHeight = 450;
this.graphWidth = 600;
this.measurements = measurements.large;
this.draw();
eventHub.$emit('toggleAspectRatio');
}
},
hoverData() {
this.positionFlag();
},
},
mounted() {
this.draw();
},
methods: {
draw() {
const breakpointSize = bp.getBreakpointSize();
......@@ -192,36 +213,16 @@
}); // This will select all of the ticks once they're rendered
},
},
watch: {
updateAspectRatio() {
if (this.updateAspectRatio) {
this.graphHeight = 450;
this.graphWidth = 600;
this.measurements = measurements.large;
this.draw();
eventHub.$emit('toggleAspectRatio');
}
},
hoverData() {
this.positionFlag();
},
},
mounted() {
this.draw();
},
};
</script>
<template>
<div
<div
class="prometheus-graph"
@mouseover="showFlagContent = true"
@mouseleave="showFlagContent = false">
<h5 class="text-center graph-title">
{{graphData.title}}
{{ graphData.title }}
</h5>
<div
class="prometheus-svg-container"
......@@ -231,12 +232,12 @@
ref="baseSvg">
<g
class="x-axis"
:transform="axisTransform">
</g>
:transform="axisTransform"
/>
<g
class="y-axis"
transform="translate(70, 20)">
</g>
transform="translate(70, 20)"
/>
<graph-legend
:graph-width="graphWidth"
:graph-height="graphHeight"
......@@ -251,40 +252,41 @@
<svg
class="graph-data"
:viewBox="innerViewBox"
ref="graphData">
<graph-path
v-for="(path, index) in timeSeries"
:key="index"
:generated-line-path="path.linePath"
:generated-area-path="path.areaPath"
:line-style="path.lineStyle"
:line-color="path.lineColor"
:area-color="path.areaColor"
/>
<rect
class="prometheus-graph-overlay"
:width="(graphWidth - 70)"
:height="(graphHeight - 100)"
transform="translate(-5, 20)"
ref="graphOverlay"
@mousemove="handleMouseOverGraph($event)">
</rect>
<graph-deployment
:show-deploy-info="showDeployInfo"
:deployment-data="reducedDeploymentData"
:graph-width="graphWidth"
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
/>
<graph-flag
v-if="showFlag"
:current-x-coordinate="currentXCoordinate"
:current-data="currentData"
:current-flag-position="currentFlagPosition"
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
:show-flag-content="showFlagContent"
/>
ref="graphData"
>
<graph-path
v-for="(path, index) in timeSeries"
:key="index"
:generated-line-path="path.linePath"
:generated-area-path="path.areaPath"
:line-style="path.lineStyle"
:line-color="path.lineColor"
:area-color="path.areaColor"
/>
<rect
class="prometheus-graph-overlay"
:width="(graphWidth - 70)"
:height="(graphHeight - 100)"
transform="translate(-5, 20)"
ref="graphOverlay"
@mousemove="handleMouseOverGraph($event)"
/>
<graph-deployment
:show-deploy-info="showDeployInfo"
:deployment-data="reducedDeploymentData"
:graph-width="graphWidth"
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
/>
<graph-flag
v-if="showFlag"
:current-x-coordinate="currentXCoordinate"
:current-data="currentData"
:current-flag-position="currentFlagPosition"
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
:show-flag-content="showFlagContent"
/>
</svg>
</svg>
</div>
......
<script>
import { dateFormatWithName, timeFormat } from '../../utils/date_time_formatters';
import Icon from '../../../vue_shared/components/icon.vue';
import icon from '../../../vue_shared/components/icon.vue';
export default {
components: {
icon,
},
props: {
showDeployInfo: {
type: Boolean,
......@@ -26,10 +29,6 @@
},
},
components: {
Icon,
},
computed: {
calculatedHeight() {
return this.graphHeight - this.graphHeightOffset;
......@@ -83,51 +82,55 @@
v-for="(deployment, index) in deploymentData"
:key="index"
:class="nameDeploymentClass(deployment)"
:transform="transformDeploymentGroup(deployment)">
:transform="transformDeploymentGroup(deployment)"
>
<rect
x="0"
y="0"
:height="calculatedHeight"
width="3"
fill="url(#shadow-gradient)">
</rect>
fill="url(#shadow-gradient)"
/>
<line
class="deployment-line"
x1="0"
y1="0"
x2="0"
:y2="calculatedHeight"
stroke="#000">
</line>
stroke="#000"
/>
<svg
v-if="deployment.showDeploymentFlag"
class="js-deploy-info-box"
:x="positionFlag(deployment)"
y="0"
width="134"
:height="svgContainerHeight(deployment.tag)">
:height="svgContainerHeight(deployment.tag)"
>
<rect
class="rect-text-metric deploy-info-rect rect-metric"
x="1"
y="1"
rx="2"
width="132"
:height="svgContainerHeight(deployment.tag) - 2">
</rect>
:height="svgContainerHeight(deployment.tag) - 2"
/>
<text
class="deploy-info-text text-metric-bold"
transform="translate(5, 2)">
transform="translate(5, 2)"
>
Deployed
</text>
<!--The date info-->
<g transform="translate(5, 20)">
<text class="deploy-info-text">
{{formatDate(deployment.time)}}
{{ formatDate(deployment.time) }}
</text>
<text
<text
class="deploy-info-text text-metric-bold"
x="62">
{{formatTime(deployment.time)}}
x="62"
>
{{ formatTime(deployment.time) }}
</text>
</g>
<line
......@@ -136,40 +139,41 @@
y1="38"
x2="132"
:y2="38"
stroke="#000">
</line>
stroke="#000"
/>
<!--Commit information-->
<g transform="translate(5, 40)">
<icon
name="commit"
:width="12"
:height="12"
:y="3">
</icon>
:y="3"
/>
<a :xlink:href="deployment.commitUrl">
<text
class="deploy-info-text deploy-info-text-link"
transform="translate(20, 2)">
{{refText(deployment)}}
{{ refText(deployment) }}
</text>
</a>
</g>
<!--Tag information-->
<g
transform="translate(5, 55)"
transform="translate(5, 55)"
v-if="deployment.tag">
<icon
name="label"
:width="12"
:height="12"
:y="5">
</icon>
:y="5"
/>
<a :xlink:href="deployment.tagUrl">
<text
class="deploy-info-text deploy-info-text-link"
transform="translate(20, 2)"
y="2">
{{deployment.tag}}
y="2"
>
{{ deployment.tag }}
</text>
</a>
</g>
......@@ -177,20 +181,20 @@
</g>
<svg
height="0"
width="0">
width="0"
>
<defs>
<linearGradient
id="shadow-gradient">
<linearGradient id="shadow-gradient">
<stop
offset="0%"
stop-color="#000"
stop-opacity="0.4">
</stop>
stop-opacity="0.4"
/>
<stop
offset="100%"
stop-color="#000"
stop-opacity="0">
</stop>
stop-opacity="0"
/>
</linearGradient>
</defs>
</svg>
......
......@@ -58,13 +58,14 @@
:y1="0"
:x2="currentXCoordinate"
:y2="calculatedHeight"
transform="translate(-5, 20)">
</line>
<svg
transform="translate(-5, 20)"
/>
<svg
v-if="showFlagContent"
class="rect-text-metric"
:x="currentFlagPosition"
y="0">
y="0"
>
<rect
class="rect-metric"
x="4"
......@@ -72,21 +73,23 @@
rx="2"
width="90"
height="40"
transform="translate(-3, 20)">
</rect>
transform="translate(-3, 20)"
/>
<text
class="text-metric text-metric-bold"
x="16"
y="35"
transform="translate(-5, 20)">
{{formatTime}}
transform="translate(-5, 20)"
>
{{ formatTime }}
</text>
<text
class="text-metric"
x="16"
y="15"
transform="translate(-5, 20)">
{{formatDate}}
transform="translate(-5, 20)"
>
{{ formatDate }}
</text>
</svg>
</g>
......
......@@ -73,6 +73,21 @@
},
},
mounted() {
this.$nextTick(() => {
const bbox = this.$refs.ylabel.getBBox();
this.metricUsageXPosition = 0;
this.seriesXPosition = 0;
if (this.$refs.legendTitleSvg != null) {
this.seriesXPosition = this.$refs.legendTitleSvg[0].getBBox().width;
}
if (this.$refs.seriesTitleSvg != null) {
this.metricUsageXPosition = this.$refs.seriesTitleSvg[0].getBBox().width;
}
this.yLabelWidth = bbox.width + 10; // Added some padding
this.yLabelHeight = bbox.height + 5;
});
},
methods: {
translateLegendGroup(index) {
return `translate(0, ${12 * (index)})`;
......@@ -100,26 +115,10 @@
return null;
},
},
mounted() {
this.$nextTick(() => {
const bbox = this.$refs.ylabel.getBBox();
this.metricUsageXPosition = 0;
this.seriesXPosition = 0;
if (this.$refs.legendTitleSvg != null) {
this.seriesXPosition = this.$refs.legendTitleSvg[0].getBBox().width;
}
if (this.$refs.seriesTitleSvg != null) {
this.metricUsageXPosition = this.$refs.seriesTitleSvg[0].getBBox().width;
}
this.yLabelWidth = bbox.width + 10; // Added some padding
this.yLabelHeight = bbox.height + 5;
});
},
};
</script>
<template>
<g
class="axis-label-container">
<g class="axis-label-container">
<line
class="label-x-axis-line"
stroke="#000000"
......@@ -127,8 +126,8 @@
x1="10"
:y1="yPosition"
:x2="graphWidth + 20"
:y2="yPosition">
</line>
:y2="yPosition"
/>
<line
class="label-y-axis-line"
stroke="#000000"
......@@ -136,39 +135,43 @@
x1="10"
y1="0"
:x2="10"
:y2="yPosition">
</line>
:y2="yPosition"
/>
<rect
class="rect-axis-text"
:transform="rectTransform"
:width="yLabelWidth"
:height="yLabelHeight">
</rect>
:height="yLabelHeight"
/>
<text
class="label-axis-text y-label-text"
text-anchor="middle"
:transform="textTransform"
ref="ylabel">
{{yAxisLabel}}
ref="ylabel"
>
{{ yAxisLabel }}
</text>
<rect
class="rect-axis-text"
:x="xPosition + 60"
:y="graphHeight - 80"
width="35"
height="50">
</rect>
height="50"
/>
<text
class="label-axis-text x-label-text"
:x="xPosition + 60"
:y="yPosition"
dy=".35em">
dy=".35em"
>
Time
</text>
<g class="legend-group"
<g
class="legend-group"
v-for="(series, index) in timeSeries"
:key="index"
:transform="translateLegendGroup(index)">
:transform="translateLegendGroup(index)"
>
<line
:stroke="series.lineColor"
:stroke-width="measurements.legends.height"
......@@ -176,23 +179,25 @@
:x1="measurements.legends.offsetX"
:x2="measurements.legends.offsetX + measurements.legends.width"
:y1="graphHeight - measurements.legends.offsetY"
:y2="graphHeight - measurements.legends.offsetY">
</line>
:y2="graphHeight - measurements.legends.offsetY"
/>
<text
v-if="timeSeries.length > 1"
class="legend-metric-title"
ref="legendTitleSvg"
x="38"
:y="graphHeight - 30">
{{createSeriesString(index, series)}}
:y="graphHeight - 30"
>
{{ createSeriesString(index, series) }}
</text>
<text
v-else
class="legend-metric-title"
ref="legendTitleSvg"
x="38"
:y="graphHeight - 30">
{{legendTitle}} {{formatMetricUsage(series)}}
:y="graphHeight - 30"
>
{{ legendTitle }} {{ formatMetricUsage(series) }}
</text>
</g>
</g>
......
......@@ -12,6 +12,7 @@
lineStyle: {
type: String,
required: false,
default: '',
},
lineColor: {
type: String,
......@@ -37,8 +38,8 @@
class="metric-area"
:d="generatedAreaPath"
:fill="areaColor"
transform="translate(-5, 20)">
</path>
transform="translate(-5, 20)"
/>
<path
class="metric-line"
:d="generatedLinePath"
......@@ -46,7 +47,7 @@
fill="none"
stroke-width="1"
:stroke-dasharray="strokeDashArray"
transform="translate(-5, 20)">
</path>
transform="translate(-5, 20)"
/>
</g>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true,
export default {
props: {
name: {
type: String,
required: true,
},
},
},
};
};
</script>
<template>
<div class="panel panel-default prometheus-panel">
<div class="panel-heading">
<h4>{{name}}</h4>
<h4>{{ name }}</h4>
</div>
<div class="panel-body prometheus-graph-group">
<slot />
......
......@@ -64,6 +64,13 @@
return this.getUserDataByProp('id');
},
},
created() {
this.emojiSmiling = emojiSmiling;
this.emojiSmile = emojiSmile;
this.emojiSmiley = emojiSmiley;
this.editSvg = editSvg;
this.ellipsisSvg = ellipsisSvg;
},
methods: {
onEdit() {
this.$emit('handleEdit');
......@@ -72,13 +79,6 @@
this.$emit('handleDelete');
},
},
created() {
this.emojiSmiling = emojiSmiling;
this.emojiSmile = emojiSmile;
this.emojiSmiley = emojiSmiley;
this.editSvg = editSvg;
this.ellipsisSvg = ellipsisSvg;
},
};
</script>
......@@ -86,7 +86,9 @@
<div class="note-actions">
<span
v-if="accessLevel"
class="note-role user-access-role">{{accessLevel}}</span>
class="note-role user-access-role">
{{ accessLevel }}
</span>
<div
v-if="canAddAwardEmoji"
class="note-actions-item">
......@@ -126,10 +128,10 @@
class="note-action-button js-note-edit btn btn-transparent"
data-container="body"
data-placement="bottom">
<span
v-html="editSvg"
class="link-highlight">
</span>
<span
v-html="editSvg"
class="link-highlight">
</span>
</button>
</div>
<div
......@@ -143,10 +145,10 @@
data-toggle="dropdown"
data-container="body"
data-placement="bottom">
<span
class="icon"
v-html="ellipsisSvg">
</span>
<span
class="icon"
v-html="ellipsisSvg">
</span>
</button>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
......
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