Commit bab8d02a authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-03-08

parents d020e657 bd30d0b5
<script>
import statusCodes from '../../lib/utils/http_status'; import statusCodes from '../../lib/utils/http_status';
import { bytesToMiB } from '../../lib/utils/number_utils'; import { bytesToMiB } from '../../lib/utils/number_utils';
import { backOff } from '../../lib/utils/common_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'; import MRWidgetService from '../services/mr_widget_service';
export default { export default {
name: 'MemoryUsage', name: 'MemoryUsage',
components: {
MemoryGraph,
},
props: { props: {
metricsUrl: { metricsUrl: {
type: String, type: String,
...@@ -28,9 +32,6 @@ export default { ...@@ -28,9 +32,6 @@ export default {
backOffRequestCounter: 0, backOffRequestCounter: 0,
}; };
}, },
components: {
'mr-memory-graph': MemoryGraph,
},
computed: { computed: {
shouldShowLoading() { shouldShowLoading() {
return this.loadingMetrics && !this.hasMetrics && !this.loadFailed; return this.loadingMetrics && !this.hasMetrics && !this.loadFailed;
...@@ -57,6 +58,10 @@ export default { ...@@ -57,6 +58,10 @@ export default {
return 'unchanged'; return 'unchanged';
}, },
}, },
mounted() {
this.loadingMetrics = true;
this.loadMetrics();
},
methods: { methods: {
getMegabytes(bytesString) { getMegabytes(bytesString) {
const valueInBytes = Number(bytesString).toFixed(2); const valueInBytes = Number(bytesString).toFixed(2);
...@@ -114,23 +119,25 @@ export default { ...@@ -114,23 +119,25 @@ export default {
}); });
}, },
}, },
mounted() { };
this.loadingMetrics = true; </script>
this.loadMetrics();
}, <template>
template: `
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage"> <div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<p <p
v-if="shouldShowLoading" v-if="shouldShowLoading"
class="usage-info js-usage-info usage-info-loading"> class="usage-info js-usage-info usage-info-loading">
<i <i
class="fa fa-spinner fa-spin usage-info-load-spinner" class="fa fa-spinner fa-spin usage-info-load-spinner"
aria-hidden="true" />Loading deployment statistics aria-hidden="true">
</i>Loading deployment statistics
</p> </p>
<p <p
v-if="shouldShowMemoryGraph" v-if="shouldShowMemoryGraph"
class="usage-info js-usage-info"> class="usage-info js-usage-info">
<a :href="metricsMonitoringUrl">Memory</a> usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB <a
:href="metricsMonitoringUrl"
>Memory</a> usage <b>{{ memoryChangeType }}</b> from {{ memoryFrom }}MB to {{ memoryTo }}MB
</p> </p>
<p <p
v-if="shouldShowLoadFailure" v-if="shouldShowLoadFailure"
...@@ -142,12 +149,12 @@ export default { ...@@ -142,12 +149,12 @@ export default {
class="usage-info js-usage-info usage-info-unavailable"> class="usage-info js-usage-info usage-info-unavailable">
Deployment statistics are not available currently Deployment statistics are not available currently
</p> </p>
<mr-memory-graph <memory-graph
v-if="shouldShowMemoryGraph" v-if="shouldShowMemoryGraph"
:metrics="memoryMetrics" :metrics="memoryMetrics"
:deploymentTime="deploymentTime" :deployment-time="deploymentTime"
height="25" height="25"
width="100" /> width="100"
/>
</div> </div>
`, </template>
};
import { getTimeago } from '~/lib/utils/datetime_utility'; import { getTimeago } from '~/lib/utils/datetime_utility';
import { visitUrl } from '../../lib/utils/url_utility'; import { visitUrl } from '../../lib/utils/url_utility';
import Flash from '../../flash'; 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 StatusIcon from './mr_widget_status_icon.vue';
import MRWidgetService from '../services/mr_widget_service'; import MRWidgetService from '../services/mr_widget_service';
...@@ -12,8 +12,8 @@ export default { ...@@ -12,8 +12,8 @@ export default {
service: { type: Object, required: true }, service: { type: Object, required: true },
}, },
components: { components: {
'mr-widget-memory-usage': MemoryUsage, MemoryUsage,
'status-icon': StatusIcon, StatusIcon,
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
...@@ -100,7 +100,7 @@ export default { ...@@ -100,7 +100,7 @@ export default {
class="btn btn-default btn-xs"> class="btn btn-default btn-xs">
Stop environment Stop environment
</button> </button>
<mr-widget-memory-usage <memory-usage
v-if="deployment.metrics_url" v-if="deployment.metrics_url"
:metrics-url="deployment.metrics_url" :metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url" :metrics-monitoring-url="deployment.metrics_monitoring_url"
......
<script>
import { getTimeago } from '../../lib/utils/datetime_utility'; import { getTimeago } from '../../lib/utils/datetime_utility';
export default { export default {
...@@ -22,6 +23,9 @@ export default { ...@@ -22,6 +23,9 @@ export default {
return `Deployed ${deployedSince}`; return `Deployed ${deployedSince}`;
}, },
}, },
mounted() {
this.renderGraph(this.deploymentTime, this.metrics);
},
methods: { methods: {
/** /**
* Returns metric value index in metrics array * Returns metric value index in metrics array
...@@ -103,15 +107,27 @@ export default { ...@@ -103,15 +107,27 @@ export default {
this.dotY = dotY; this.dotY = dotY;
}, },
}, },
mounted() { };
this.renderGraph(this.deploymentTime, this.metrics); </script>
},
template: ` <template>
<div class="memory-graph-container"> <div class="memory-graph-container">
<svg class="has-tooltip" :title="getFormattedMedian" :width="width" :height="height" xmlns="http://www.w3.org/2000/svg"> <svg
<path :d="pathD" :viewBox="pathViewBox" /> class="has-tooltip"
<circle r="1.5" :cx="dotX" :cy="dotY" tranform="translate(0 -1)" /> :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> </svg>
</div> </div>
`, </template>
};
...@@ -68,7 +68,7 @@ module Projects ...@@ -68,7 +68,7 @@ module Projects
def enabling_wiki? def enabling_wiki?
return false if @project.wiki_enabled? 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 end
def ensure_wiki_exists def ensure_wiki_exists
......
---
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: ...@@ -45,7 +45,7 @@ We basically have 4 types of files:
1. Ruby files: basically Models and Controllers. 1. Ruby files: basically Models and Controllers.
1. HAML files: these are the view files. 1. HAML files: these are the view files.
1. ERB files: used for email templates. 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 ### Ruby files
......
...@@ -97,4 +97,15 @@ feature 'Milestone' do ...@@ -97,4 +97,15 @@ feature 'Milestone' do
end end
end 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 end
import Vue from 'vue'; 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'; import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
const url = '/root/acets-review-apps/environments/15/deployments/1/metrics'; const url = '/root/acets-review-apps/environments/15/deployments/1/metrics';
...@@ -34,7 +34,7 @@ const metricsMockData = { ...@@ -34,7 +34,7 @@ const metricsMockData = {
}; };
const createComponent = () => { const createComponent = () => {
const Component = Vue.extend(memoryUsageComponent); const Component = Vue.extend(MemoryUsage);
return new Component({ return new Component({
el: document.createElement('div'), el: document.createElement('div'),
...@@ -67,21 +67,9 @@ describe('MemoryUsage', () => { ...@@ -67,21 +67,9 @@ describe('MemoryUsage', () => {
el = vm.$el; 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', () => { describe('data', () => {
it('should have default data', () => { it('should have default data', () => {
const data = memoryUsageComponent.data(); const data = MemoryUsage.data();
expect(Array.isArray(data.memoryMetrics)).toBeTruthy(); expect(Array.isArray(data.memoryMetrics)).toBeTruthy();
expect(data.memoryMetrics.length).toBe(0); expect(data.memoryMetrics.length).toBe(0);
......
import Vue from 'vue'; 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'; import { mockMetrics, mockMedian, mockMedianIndex } from './mock_data';
const defaultHeight = '25'; const defaultHeight = '25';
const defaultWidth = '100'; const defaultWidth = '100';
const createComponent = () => { const createComponent = () => {
const Component = Vue.extend(memoryGraphComponent); const Component = Vue.extend(MemoryGraph);
return new Component({ return new Component({
el: document.createElement('div'), el: document.createElement('div'),
...@@ -32,29 +32,9 @@ describe('MemoryGraph', () => { ...@@ -32,29 +32,9 @@ describe('MemoryGraph', () => {
el = vm.$el; 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', () => { describe('data', () => {
it('should have default data', () => { it('should have default data', () => {
const data = memoryGraphComponent.data(); const data = MemoryGraph.data();
const dataValidator = (dataItem, expectedType, defaultVal) => { const dataValidator = (dataItem, expectedType, defaultVal) => {
expect(typeof dataItem).toBe(expectedType); expect(typeof dataItem).toBe(expectedType);
expect(dataItem).toBe(defaultVal); expect(dataItem).toBe(defaultVal);
......
...@@ -133,6 +133,15 @@ describe Projects::UpdateService, '#execute' do ...@@ -133,6 +133,15 @@ describe Projects::UpdateService, '#execute' do
expect(result).to eq({ status: :success }) expect(result).to eq({ status: :success })
expect(project.wiki_repository_exists?).to be false expect(project.wiki_repository_exists?).to be false
end 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 end
context 'when enabling a wiki' do 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