Commit 6429dc94 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'fix/49388' into 'master'

Fix metrics graphs environments dropdown

Closes #49388

See merge request gitlab-org/gitlab-ce!24441
parents c1e9b9e8 db054bc1
...@@ -143,7 +143,7 @@ export default { ...@@ -143,7 +143,7 @@ export default {
*/ */
created() { created() {
this.service = new EnvironmentsService(this.endpoint); this.service = new EnvironmentsService(this.endpoint);
this.requestData = { page: this.page, scope: this.scope }; this.requestData = { page: this.page, scope: this.scope, nested: true };
this.poll = new Poll({ this.poll = new Poll({
resource: this.service, resource: this.service,
......
...@@ -7,8 +7,8 @@ export default class EnvironmentsService { ...@@ -7,8 +7,8 @@ export default class EnvironmentsService {
} }
fetchEnvironments(options = {}) { fetchEnvironments(options = {}) {
const { scope, page } = options; const { scope, page, nested } = options;
return axios.get(this.environmentsEndpoint, { params: { scope, page } }); return axios.get(this.environmentsEndpoint, { params: { scope, page, nested } });
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
......
...@@ -20,7 +20,8 @@ export default class EnvironmentsStore { ...@@ -20,7 +20,8 @@ export default class EnvironmentsStore {
* *
* Stores the received environments. * Stores the received environments.
* *
* In the main environments endpoint, each environment has the following schema * In the main environments endpoint (with { nested: true } in params), each folder
* has the following schema:
* { name: String, size: Number, latest: Object } * { name: String, size: Number, latest: Object }
* In the endpoint to retrieve environments from each folder, the environment does * In the endpoint to retrieve environments from each folder, the environment does
* not have the `latest` key and the data is all in the root level. * not have the `latest` key and the data is all in the root level.
......
...@@ -196,13 +196,13 @@ export default { ...@@ -196,13 +196,13 @@ export default {
class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up" class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up"
> >
<ul> <ul>
<li v-for="environment in store.environmentsData" :key="environment.latest.id"> <li v-for="environment in store.environmentsData" :key="environment.id">
<a <a
:href="environment.latest.metrics_path" :href="environment.metrics_path"
:class="{ 'is-active': environment.latest.name == currentEnvironmentName }" :class="{ 'is-active': environment.name == currentEnvironmentName }"
class="dropdown-item" class="dropdown-item"
> >
{{ environment.latest.name }} {{ environment.name }}
</a> </a>
</li> </li>
</ul> </ul>
......
...@@ -66,9 +66,7 @@ export default class MonitoringStore { ...@@ -66,9 +66,7 @@ export default class MonitoringStore {
} }
storeEnvironmentsData(environmentsData = []) { storeEnvironmentsData(environmentsData = []) {
this.environmentsData = environmentsData.filter( this.environmentsData = environmentsData.filter(environment => !!environment.last_deployment);
environment => !!environment.latest.last_deployment,
);
} }
getMetricsCount() { getMetricsCount() {
......
...@@ -15,6 +15,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -15,6 +15,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
push_frontend_feature_flag(:area_chart, project) push_frontend_feature_flag(:area_chart, project)
end end
# Returns all environments or all folders based on the :nested param
def index def index
@environments = project.environments @environments = project.environments
.with_state(params[:scope] || :available) .with_state(params[:scope] || :available)
...@@ -25,11 +26,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -25,11 +26,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
Gitlab::PollingInterval.set_header(response, interval: 3_000) Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: { render json: {
environments: EnvironmentSerializer environments: serialize_environments(request, response, params[:nested]),
.new(project: @project, current_user: @current_user)
.with_pagination(request, response)
.within_folders
.represent(@environments),
available_count: project.environments.available.count, available_count: project.environments.available.count,
stopped_count: project.environments.stopped.count stopped_count: project.environments.stopped.count
} }
...@@ -37,6 +34,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -37,6 +34,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end end
end end
# Returns all environments for a given folder
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def folder def folder
folder_environments = project.environments.where(environment_type: params[:id]) folder_environments = project.environments.where(environment_type: params[:id])
...@@ -48,10 +46,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -48,10 +46,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
format.html format.html
format.json do format.json do
render json: { render json: {
environments: EnvironmentSerializer environments: serialize_environments(request, response),
.new(project: @project, current_user: @current_user)
.with_pagination(request, response)
.represent(@environments),
available_count: folder_environments.available.count, available_count: folder_environments.available.count,
stopped_count: folder_environments.stopped.count stopped_count: folder_environments.stopped.count
} }
...@@ -186,6 +181,14 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -186,6 +181,14 @@ class Projects::EnvironmentsController < Projects::ApplicationController
@environment ||= project.environments.find(params[:id]) @environment ||= project.environments.find(params[:id])
end end
def serialize_environments(request, response, nested = false)
serializer = EnvironmentSerializer
.new(project: @project, current_user: @current_user)
.with_pagination(request, response)
serializer = serializer.within_folders if nested
serializer.represent(@environments)
end
def authorize_stop_environment! def authorize_stop_environment!
access_denied! unless can?(current_user, :stop_environment, environment) access_denied! unless can?(current_user, :stop_environment, environment)
end end
......
---
title: Update metrics environment dropdown to show complete option set
merge_request: 24441
author:
type: fixed
...@@ -47,9 +47,43 @@ describe Projects::EnvironmentsController do ...@@ -47,9 +47,43 @@ describe Projects::EnvironmentsController do
let(:environments) { json_response['environments'] } let(:environments) { json_response['environments'] }
context 'with default parameters' do
before do
get :index, params: environment_params(format: :json)
end
it 'responds with a flat payload describing available environments' do
expect(environments.count).to eq 3
expect(environments.first['name']).to eq 'production'
expect(environments.second['name']).to eq 'staging/review-1'
expect(environments.third['name']).to eq 'staging/review-2'
expect(json_response['available_count']).to eq 3
expect(json_response['stopped_count']).to eq 1
end
it 'sets the polling interval header' do
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Poll-Interval']).to eq("3000")
end
end
context 'when a folder-based nested structure is requested' do
before do
get :index, params: environment_params(format: :json, nested: true)
end
it 'responds with a payload containing the latest environment for each folder' do
expect(environments.count).to eq 2
expect(environments.first['name']).to eq 'production'
expect(environments.second['name']).to eq 'staging'
expect(environments.second['size']).to eq 2
expect(environments.second['latest']['name']).to eq 'staging/review-2'
end
end
context 'when requesting available environments scope' do context 'when requesting available environments scope' do
before do before do
get :index, params: environment_params(format: :json, scope: :available) get :index, params: environment_params(format: :json, nested: true, scope: :available)
end end
it 'responds with a payload describing available environments' do it 'responds with a payload describing available environments' do
...@@ -64,16 +98,11 @@ describe Projects::EnvironmentsController do ...@@ -64,16 +98,11 @@ describe Projects::EnvironmentsController do
expect(json_response['available_count']).to eq 3 expect(json_response['available_count']).to eq 3
expect(json_response['stopped_count']).to eq 1 expect(json_response['stopped_count']).to eq 1
end end
it 'sets the polling interval header' do
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Poll-Interval']).to eq("3000")
end
end end
context 'when requesting stopped environments scope' do context 'when requesting stopped environments scope' do
before do before do
get :index, params: environment_params(format: :json, scope: :stopped) get :index, params: environment_params(format: :json, nested: true, scope: :stopped)
end end
it 'responds with a payload describing stopped environments' do it 'responds with a payload describing stopped environments' do
......
...@@ -6597,58 +6597,46 @@ export function convertDatesMultipleSeries(multipleSeries) { ...@@ -6597,58 +6597,46 @@ export function convertDatesMultipleSeries(multipleSeries) {
export const environmentData = [ export const environmentData = [
{ {
id: 34,
name: 'production', name: 'production',
size: 1, state: 'available',
latest: { external_url: 'http://root-autodevops-deploy.my-fake-domain.com',
id: 34, environment_type: null,
name: 'production', stop_action: false,
state: 'available', metrics_path: '/root/hello-prometheus/environments/34/metrics',
external_url: 'http://root-autodevops-deploy.my-fake-domain.com', environment_path: '/root/hello-prometheus/environments/34',
environment_type: null, stop_path: '/root/hello-prometheus/environments/34/stop',
stop_action: false, terminal_path: '/root/hello-prometheus/environments/34/terminal',
metrics_path: '/root/hello-prometheus/environments/34/metrics', folder_path: '/root/hello-prometheus/environments/folders/production',
environment_path: '/root/hello-prometheus/environments/34', created_at: '2018-06-29T16:53:38.301Z',
stop_path: '/root/hello-prometheus/environments/34/stop', updated_at: '2018-06-29T16:57:09.825Z',
terminal_path: '/root/hello-prometheus/environments/34/terminal', last_deployment: {
folder_path: '/root/hello-prometheus/environments/folders/production', id: 127,
created_at: '2018-06-29T16:53:38.301Z',
updated_at: '2018-06-29T16:57:09.825Z',
last_deployment: {
id: 127,
},
}, },
}, },
{ {
name: 'review', id: 35,
size: 1, name: 'review/noop-branch',
latest: { state: 'available',
id: 35, external_url: 'http://root-autodevops-deploy-review-noop-branc-die93w.my-fake-domain.com',
name: 'review/noop-branch', environment_type: 'review',
state: 'available', stop_action: true,
external_url: 'http://root-autodevops-deploy-review-noop-branc-die93w.my-fake-domain.com', metrics_path: '/root/hello-prometheus/environments/35/metrics',
environment_type: 'review', environment_path: '/root/hello-prometheus/environments/35',
stop_action: true, stop_path: '/root/hello-prometheus/environments/35/stop',
metrics_path: '/root/hello-prometheus/environments/35/metrics', terminal_path: '/root/hello-prometheus/environments/35/terminal',
environment_path: '/root/hello-prometheus/environments/35', folder_path: '/root/hello-prometheus/environments/folders/review',
stop_path: '/root/hello-prometheus/environments/35/stop', created_at: '2018-07-03T18:39:41.702Z',
terminal_path: '/root/hello-prometheus/environments/35/terminal', updated_at: '2018-07-03T18:44:54.010Z',
folder_path: '/root/hello-prometheus/environments/folders/review', last_deployment: {
created_at: '2018-07-03T18:39:41.702Z', id: 128,
updated_at: '2018-07-03T18:44:54.010Z',
last_deployment: {
id: 128,
},
}, },
}, },
{ {
name: 'no-deployment', id: 36,
size: 1, name: 'no-deployment/noop-branch',
latest: { state: 'available',
id: 36, created_at: '2018-07-04T18:39:41.702Z',
name: 'no-deployment/noop-branch', updated_at: '2018-07-04T18:44:54.010Z',
state: 'available',
created_at: '2018-07-04T18:39:41.702Z',
updated_at: '2018-07-04T18:44:54.010Z',
},
}, },
]; ];
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