Commit 623da080 authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-03-08' into 'master'

CE upstream - 2018-03-08 18:24 UTC

See merge request !4904
parents 193c4fce bab8d02a
Pipeline #18618946 passed with stages
in 65 minutes and 40 seconds
<script>
import statusCodes from '../../lib/utils/http_status';
import { bytesToMiB } from '../../lib/utils/number_utils';
import { backOff } from '../../lib/utils/common_utils';
import MemoryGraph from '../../vue_shared/components/memory_graph';
import MemoryGraph from '../../vue_shared/components/memory_graph.vue';
import MRWidgetService from '../services/mr_widget_service';
export default {
name: 'MemoryUsage',
components: {
MemoryGraph,
},
props: {
metricsUrl: {
type: String,
......@@ -28,9 +32,6 @@ export default {
backOffRequestCounter: 0,
};
},
components: {
'mr-memory-graph': MemoryGraph,
},
computed: {
shouldShowLoading() {
return this.loadingMetrics && !this.hasMetrics && !this.loadFailed;
......@@ -57,6 +58,10 @@ export default {
return 'unchanged';
},
},
mounted() {
this.loadingMetrics = true;
this.loadMetrics();
},
methods: {
getMegabytes(bytesString) {
const valueInBytes = Number(bytesString).toFixed(2);
......@@ -114,40 +119,42 @@ export default {
});
},
},
mounted() {
this.loadingMetrics = true;
this.loadMetrics();
},
template: `
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<p
v-if="shouldShowLoading"
class="usage-info js-usage-info usage-info-loading">
<i
class="fa fa-spinner fa-spin usage-info-load-spinner"
aria-hidden="true" />Loading deployment statistics
</p>
<p
v-if="shouldShowMemoryGraph"
class="usage-info js-usage-info">
<a :href="metricsMonitoringUrl">Memory</a> usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB
</p>
<p
v-if="shouldShowLoadFailure"
class="usage-info js-usage-info usage-info-failed">
Failed to load deployment statistics
</p>
<p
v-if="shouldShowMetricsUnavailable"
class="usage-info js-usage-info usage-info-unavailable">
Deployment statistics are not available currently
</p>
<mr-memory-graph
v-if="shouldShowMemoryGraph"
:metrics="memoryMetrics"
:deploymentTime="deploymentTime"
height="25"
width="100" />
</div>
`,
};
</script>
<template>
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<p
v-if="shouldShowLoading"
class="usage-info js-usage-info usage-info-loading">
<i
class="fa fa-spinner fa-spin usage-info-load-spinner"
aria-hidden="true">
</i>Loading deployment statistics
</p>
<p
v-if="shouldShowMemoryGraph"
class="usage-info js-usage-info">
<a
:href="metricsMonitoringUrl"
>Memory</a> usage <b>{{ memoryChangeType }}</b> from {{ memoryFrom }}MB to {{ memoryTo }}MB
</p>
<p
v-if="shouldShowLoadFailure"
class="usage-info js-usage-info usage-info-failed">
Failed to load deployment statistics
</p>
<p
v-if="shouldShowMetricsUnavailable"
class="usage-info js-usage-info usage-info-unavailable">
Deployment statistics are not available currently
</p>
<memory-graph
v-if="shouldShowMemoryGraph"
:metrics="memoryMetrics"
:deployment-time="deploymentTime"
height="25"
width="100"
/>
</div>
</template>
import { getTimeago } from '~/lib/utils/datetime_utility';
import { visitUrl } from '../../lib/utils/url_utility';
import Flash from '../../flash';
import MemoryUsage from './mr_widget_memory_usage';
import MemoryUsage from './memory_usage.vue';
import StatusIcon from './mr_widget_status_icon.vue';
import MRWidgetService from '../services/mr_widget_service';
......@@ -12,8 +12,8 @@ export default {
service: { type: Object, required: true },
},
components: {
'mr-widget-memory-usage': MemoryUsage,
'status-icon': StatusIcon,
MemoryUsage,
StatusIcon,
},
methods: {
formatDate(date) {
......@@ -100,7 +100,7 @@ export default {
class="btn btn-default btn-xs">
Stop environment
</button>
<mr-widget-memory-usage
<memory-usage
v-if="deployment.metrics_url"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
......
<script>
import { getTimeago } from '../../lib/utils/datetime_utility';
export default {
......@@ -22,6 +23,9 @@ export default {
return `Deployed ${deployedSince}`;
},
},
mounted() {
this.renderGraph(this.deploymentTime, this.metrics);
},
methods: {
/**
* Returns metric value index in metrics array
......@@ -103,15 +107,27 @@ export default {
this.dotY = dotY;
},
},
mounted() {
this.renderGraph(this.deploymentTime, this.metrics);
},
template: `
<div class="memory-graph-container">
<svg class="has-tooltip" :title="getFormattedMedian" :width="width" :height="height" xmlns="http://www.w3.org/2000/svg">
<path :d="pathD" :viewBox="pathViewBox" />
<circle r="1.5" :cx="dotX" :cy="dotY" tranform="translate(0 -1)" />
</svg>
</div>
`,
};
</script>
<template>
<div class="memory-graph-container">
<svg
class="has-tooltip"
:title="getFormattedMedian"
:width="width"
:height="height"
xmlns="http://www.w3.org/2000/svg">
<path
:d="pathD"
:viewBox="pathViewBox"
/>
<circle
r="1.5"
:cx="dotX"
:cy="dotY"
tranform="translate(0 -1)"
/>
</svg>
</div>
</template>
......@@ -68,7 +68,7 @@ module Projects
def enabling_wiki?
return false if @project.wiki_enabled?
params[:project_feature_attributes][:wiki_access_level].to_i > ProjectFeature::DISABLED
params.dig(:project_feature_attributes, :wiki_access_level).to_i > ProjectFeature::DISABLED
end
def ensure_wiki_exists
......
......@@ -63,13 +63,13 @@
= link_to 'Close Milestone', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-xs btn-close btn-grouped"
%button.js-delete-milestone-button.btn.btn-xs.btn-grouped.btn-danger{ data: { toggle: 'modal',
target: '#delete-milestone-modal',
milestone_id: milestone.id,
milestone_title: markdown_field(milestone, :title),
milestone_url: project_milestone_path(milestone.project, milestone),
milestone_issue_count: milestone.issues.count,
milestone_merge_request_count: milestone.merge_requests.count },
disabled: true }
= _('Delete')
= icon('spin spinner', class: 'js-loading-icon hidden' )
%button.js-delete-milestone-button.btn.btn-xs.btn-grouped.btn-danger{ data: { toggle: 'modal',
target: '#delete-milestone-modal',
milestone_id: milestone.id,
milestone_title: markdown_field(milestone, :title),
milestone_url: project_milestone_path(milestone.project, milestone),
milestone_issue_count: milestone.issues.count,
milestone_merge_request_count: milestone.merge_requests.count },
disabled: true }
= _('Delete')
= icon('spin spinner', class: 'js-loading-icon hidden' )
---
title: Move MemoryGraph and MemoryUsage vue components
merge_request: 17533
author: George Tsiolis
type: performance
......@@ -45,7 +45,7 @@ We basically have 4 types of files:
1. Ruby files: basically Models and Controllers.
1. HAML files: these are the view files.
1. ERB files: used for email templates.
1. JavaScript files: we mostly need to work with VUE JS templates.
1. JavaScript files: we mostly need to work with Vue templates.
### Ruby files
......
......@@ -97,4 +97,15 @@ feature 'Milestone' do
end
end
end
feature 'Deleting a milestone' do
scenario "The delete milestone button does not show for unauthorized users" do
create(:milestone, project: project, title: 8.7)
sign_out(user)
visit group_milestones_path(group)
expect(page).to have_selector('.js-delete-milestone-button', count: 0)
end
end
end
import Vue from 'vue';
import memoryUsageComponent from '~/vue_merge_request_widget/components/mr_widget_memory_usage';
import MemoryUsage from '~/vue_merge_request_widget/components/memory_usage.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
const url = '/root/acets-review-apps/environments/15/deployments/1/metrics';
......@@ -34,7 +34,7 @@ const metricsMockData = {
};
const createComponent = () => {
const Component = Vue.extend(memoryUsageComponent);
const Component = Vue.extend(MemoryUsage);
return new Component({
el: document.createElement('div'),
......@@ -67,21 +67,9 @@ describe('MemoryUsage', () => {
el = vm.$el;
});
describe('props', () => {
it('should have props with defaults', () => {
const { metricsUrl } = memoryUsageComponent.props;
const MetricsUrlTypeClass = metricsUrl.type;
Vue.nextTick(() => {
expect(new MetricsUrlTypeClass() instanceof String).toBeTruthy();
expect(metricsUrl.required).toBeTruthy();
});
});
});
describe('data', () => {
it('should have default data', () => {
const data = memoryUsageComponent.data();
const data = MemoryUsage.data();
expect(Array.isArray(data.memoryMetrics)).toBeTruthy();
expect(data.memoryMetrics.length).toBe(0);
......
import Vue from 'vue';
import memoryGraphComponent from '~/vue_shared/components/memory_graph';
import MemoryGraph from '~/vue_shared/components/memory_graph.vue';
import { mockMetrics, mockMedian, mockMedianIndex } from './mock_data';
const defaultHeight = '25';
const defaultWidth = '100';
const createComponent = () => {
const Component = Vue.extend(memoryGraphComponent);
const Component = Vue.extend(MemoryGraph);
return new Component({
el: document.createElement('div'),
......@@ -32,29 +32,9 @@ describe('MemoryGraph', () => {
el = vm.$el;
});
describe('props', () => {
it('should have props with defaults', (done) => {
const { metrics, deploymentTime, width, height } = memoryGraphComponent.props;
Vue.nextTick(() => {
const typeClassMatcher = (propItem, expectedType) => {
const PropItemTypeClass = propItem.type;
expect(new PropItemTypeClass() instanceof expectedType).toBeTruthy();
expect(propItem.required).toBeTruthy();
};
typeClassMatcher(metrics, Array);
typeClassMatcher(deploymentTime, Number);
typeClassMatcher(width, String);
typeClassMatcher(height, String);
done();
});
});
});
describe('data', () => {
it('should have default data', () => {
const data = memoryGraphComponent.data();
const data = MemoryGraph.data();
const dataValidator = (dataItem, expectedType, defaultVal) => {
expect(typeof dataItem).toBe(expectedType);
expect(dataItem).toBe(defaultVal);
......
......@@ -133,6 +133,15 @@ describe Projects::UpdateService, '#execute' do
expect(result).to eq({ status: :success })
expect(project.wiki_repository_exists?).to be false
end
it 'handles empty project feature attributes' do
project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED)
result = update_project(project, user, { name: 'test1' })
expect(result).to eq({ status: :success })
expect(project.wiki_repository_exists?).to be false
end
end
context 'when enabling a wiki' do
......
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