Commit fa0e92fe authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '119429-decouple-webhooks-from-integrations-within-project-settings' into 'master'

Decouple Webhooks from Integrations within Project > Settings

See merge request gitlab-org/gitlab!23136
parents a96760d0 45f6f105
import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.js-webhooks-moved-alert');
PersistentUserCallout.factory(callout);
});
...@@ -12,7 +12,8 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -12,7 +12,8 @@ class Projects::HooksController < Projects::ApplicationController
layout "project_settings" layout "project_settings"
def index def index
redirect_to project_settings_integrations_path(@project) @hooks = @project.hooks
@hook = ProjectHook.new
end end
def create def create
...@@ -24,7 +25,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -24,7 +25,7 @@ class Projects::HooksController < Projects::ApplicationController
flash[:alert] = @hook.errors.full_messages.join.html_safe flash[:alert] = @hook.errors.full_messages.join.html_safe
end end
redirect_to project_settings_integrations_path(@project) redirect_to action: :index
end end
def edit def edit
...@@ -33,7 +34,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -33,7 +34,7 @@ class Projects::HooksController < Projects::ApplicationController
def update def update
if hook.update(hook_params) if hook.update(hook_params)
flash[:notice] = _('Hook was successfully updated.') flash[:notice] = _('Hook was successfully updated.')
redirect_to project_settings_integrations_path(@project) redirect_to action: :index
else else
render 'edit' render 'edit'
end end
...@@ -44,13 +45,13 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -44,13 +45,13 @@ class Projects::HooksController < Projects::ApplicationController
set_hook_execution_notice(result) set_hook_execution_notice(result)
redirect_back_or_default(default: { action: 'index' }) redirect_back_or_default(default: { action: :index })
end end
def destroy def destroy
hook.destroy hook.destroy
redirect_to project_settings_integrations_path(@project), status: :found redirect_to action: :index, status: :found
end end
private private
......
...@@ -9,10 +9,6 @@ module Projects ...@@ -9,10 +9,6 @@ module Projects
layout "project_settings" layout "project_settings"
def show def show
@hooks = @project.hooks
@hook = ProjectHook.new
# Services
@services = @project.find_or_initialize_services(exceptions: service_exceptions) @services = @project.find_or_initialize_services(exceptions: service_exceptions)
end end
......
...@@ -669,6 +669,9 @@ module ProjectsHelper ...@@ -669,6 +669,9 @@ module ProjectsHelper
project_members#index project_members#index
integrations#show integrations#show
services#edit services#edit
hooks#index
hooks#edit
hook_logs#show
repository#show repository#show
ci_cd#show ci_cd#show
operations#show operations#show
......
...@@ -5,6 +5,7 @@ module UserCalloutsHelper ...@@ -5,6 +5,7 @@ module UserCalloutsHelper
GCP_SIGNUP_OFFER = 'gcp_signup_offer' GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed' SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight' TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
WEBHOOKS_MOVED = 'webhooks_moved'
def show_gke_cluster_integration_callout?(project) def show_gke_cluster_integration_callout?(project)
can?(current_user, :create_cluster, project) && can?(current_user, :create_cluster, project) &&
...@@ -33,6 +34,10 @@ module UserCalloutsHelper ...@@ -33,6 +34,10 @@ module UserCalloutsHelper
current_user && !user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test? current_user && !user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test?
end end
def show_webhooks_moved_alert?
!user_dismissed?(WEBHOOKS_MOVED)
end
private private
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil) def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
......
...@@ -21,7 +21,7 @@ class ProjectHook < WebHook ...@@ -21,7 +21,7 @@ class ProjectHook < WebHook
validates :project, presence: true validates :project, presence: true
def pluralized_name def pluralized_name
_('Project Hooks') _('Webhooks')
end end
end end
......
...@@ -15,7 +15,8 @@ module UserCalloutEnums ...@@ -15,7 +15,8 @@ module UserCalloutEnums
gcp_signup_offer: 2, gcp_signup_offer: 2,
cluster_security_warning: 3, cluster_security_warning: 3,
suggest_popover_dismissed: 9, suggest_popover_dismissed: 9,
tabs_position_highlight: 10 tabs_position_highlight: 10,
webhooks_moved: 13
} }
end end
end end
......
...@@ -366,10 +366,14 @@ ...@@ -366,10 +366,14 @@
%span %span
= _('Members') = _('Members')
- if can_edit - if can_edit
= nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do = nav_link(controller: [:integrations, :services]) do
= link_to project_settings_integrations_path(@project), title: _('Integrations'), data: { qa_selector: 'integrations_settings_link' } do = link_to project_settings_integrations_path(@project), title: _('Integrations'), data: { qa_selector: 'integrations_settings_link' } do
%span %span
= _('Integrations') = _('Integrations')
= nav_link(controller: [:hooks, :hook_logs]) do
= link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do
%span
= _('Webhooks')
= nav_link(controller: :repository) do = nav_link(controller: :repository) do
= link_to project_settings_repository_path(@project), title: _('Repository') do = link_to project_settings_repository_path(@project), title: _('Repository') do
%span %span
......
- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
- page_title _('Webhook Logs')
.row.prepend-top-default.append-bottom-default .row.prepend-top-default.append-bottom-default
.col-lg-3 .col-lg-3
%h4.prepend-top-0 %h4.prepend-top-0
......
- add_to_breadcrumbs _('ProjectService|Integrations'), namespace_project_settings_integrations_path - @content_class = 'limit-container-width' unless fluid_layout
- page_title _('Edit Project Hook') - add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
- page_title _('Webhook')
.row.prepend-top-default .row.prepend-top-default
.col-lg-3 .col-lg-3
......
- @content_class = 'limit-container-width' unless fluid_layout
- breadcrumb_title _('Webhook Settings')
- page_title _('Webhooks')
.row.prepend-top-default .row.prepend-top-default
.col-lg-4 .col-lg-4
= render 'shared/web_hooks/title_and_docs', hook: @hook = render 'shared/web_hooks/title_and_docs', hook: @hook
......
.row.prepend-top-default.append-bottom-default .row.prepend-top-default
.col-lg-4 .col-lg-4
%h4.prepend-top-0 %h4.prepend-top-0
= s_("ProjectService|Project services") = _('Integrations')
%p= s_("ProjectService|Project services allow you to integrate GitLab with other applications") %p= _('Integrations allow you to integrate GitLab with other applications')
.col-lg-8 .col-lg-8
%table.table %table.table
%colgroup %colgroup
......
- breadcrumb_title @service.title - breadcrumb_title @service.title
- add_to_breadcrumbs _('Integration Settings'), project_settings_integrations_path(@project)
- page_title @service.title, s_("ProjectService|Services") - page_title @service.title, s_("ProjectService|Services")
- add_to_breadcrumbs(s_("ProjectService|Settings"), edit_project_path(@project))
- add_to_breadcrumbs(s_("ProjectService|Integrations"), project_settings_integrations_path(@project))
= render 'deprecated_message' if @service.deprecation_message = render 'deprecated_message' if @service.deprecation_message
......
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- breadcrumb_title _("Integrations Settings") - breadcrumb_title _('Integration Settings')
- page_title _('Integrations') - page_title _('Integrations')
= render 'projects/hooks/index'
- if show_webhooks_moved_alert?
.gl-alert.gl-alert-info.js-webhooks-moved-alert.prepend-top-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::WEBHOOKS_MOVED, dismiss_endpoint: user_callouts_path } }
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', size: 16, css_class: 'gl-icon')
.gl-alert-body
= _('Webhooks have moved. They can now be found under the Settings menu.')
.gl-alert-actions
= link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'btn gl-alert-action btn-info new-gl-button'
= render 'projects/services/index' = render 'projects/services/index'
...@@ -15,62 +15,62 @@ ...@@ -15,62 +15,62 @@
= form.check_box :push_events, class: 'form-check-input' = form.check_box :push_events, class: 'form-check-input'
= form.label :push_events, class: 'list-label form-check-label ml-1' do = form.label :push_events, class: 'list-label form-check-label ml-1' do
%strong Push events %strong Push events
%p.light.ml-1 = form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%p.text-muted.ml-1
This URL will be triggered by a push to the repository This URL will be triggered by a push to the repository
= form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%li %li
= form.check_box :tag_push_events, class: 'form-check-input' = form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label ml-1' do = form.label :tag_push_events, class: 'list-label form-check-label ml-1' do
%strong Tag push events %strong Tag push events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when a new tag is pushed to the repository This URL will be triggered when a new tag is pushed to the repository
%li %li
= form.check_box :note_events, class: 'form-check-input' = form.check_box :note_events, class: 'form-check-input'
= form.label :note_events, class: 'list-label form-check-label ml-1' do = form.label :note_events, class: 'list-label form-check-label ml-1' do
%strong Comments %strong Comments
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when someone adds a comment This URL will be triggered when someone adds a comment
%li %li
= form.check_box :confidential_note_events, class: 'form-check-input' = form.check_box :confidential_note_events, class: 'form-check-input'
= form.label :confidential_note_events, class: 'list-label form-check-label ml-1' do = form.label :confidential_note_events, class: 'list-label form-check-label ml-1' do
%strong Confidential Comments %strong Confidential Comments
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when someone adds a comment on a confidential issue This URL will be triggered when someone adds a comment on a confidential issue
%li %li
= form.check_box :issues_events, class: 'form-check-input' = form.check_box :issues_events, class: 'form-check-input'
= form.label :issues_events, class: 'list-label form-check-label ml-1' do = form.label :issues_events, class: 'list-label form-check-label ml-1' do
%strong Issues events %strong Issues events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when an issue is created/updated/merged This URL will be triggered when an issue is created/updated/merged
%li %li
= form.check_box :confidential_issues_events, class: 'form-check-input' = form.check_box :confidential_issues_events, class: 'form-check-input'
= form.label :confidential_issues_events, class: 'list-label form-check-label ml-1' do = form.label :confidential_issues_events, class: 'list-label form-check-label ml-1' do
%strong Confidential Issues events %strong Confidential Issues events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when a confidential issue is created/updated/merged This URL will be triggered when a confidential issue is created/updated/merged
%li %li
= form.check_box :merge_requests_events, class: 'form-check-input' = form.check_box :merge_requests_events, class: 'form-check-input'
= form.label :merge_requests_events, class: 'list-label form-check-label ml-1' do = form.label :merge_requests_events, class: 'list-label form-check-label ml-1' do
%strong Merge request events %strong Merge request events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when a merge request is created/updated/merged This URL will be triggered when a merge request is created/updated/merged
%li %li
= form.check_box :job_events, class: 'form-check-input' = form.check_box :job_events, class: 'form-check-input'
= form.label :job_events, class: 'list-label form-check-label ml-1' do = form.label :job_events, class: 'list-label form-check-label ml-1' do
%strong Job events %strong Job events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when the job status changes This URL will be triggered when the job status changes
%li %li
= form.check_box :pipeline_events, class: 'form-check-input' = form.check_box :pipeline_events, class: 'form-check-input'
= form.label :pipeline_events, class: 'list-label form-check-label ml-1' do = form.label :pipeline_events, class: 'list-label form-check-label ml-1' do
%strong Pipeline events %strong Pipeline events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when the pipeline status changes This URL will be triggered when the pipeline status changes
%li %li
= form.check_box :wiki_page_events, class: 'form-check-input' = form.check_box :wiki_page_events, class: 'form-check-input'
= form.label :wiki_page_events, class: 'list-label form-check-label ml-1' do = form.label :wiki_page_events, class: 'list-label form-check-label ml-1' do
%strong Wiki Page events %strong Wiki Page events
%p.light.ml-1 %p.text-muted.ml-1
This URL will be triggered when a wiki page is created/updated This URL will be triggered when a wiki page is created/updated
.form-group .form-group
= form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox' = form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
......
---
title: Decouple Webhooks from Integrations within Project > Settings
merge_request: 23136
author:
type: changed
...@@ -45,7 +45,7 @@ They are available **per project** for GitLab Community Edition, ...@@ -45,7 +45,7 @@ They are available **per project** for GitLab Community Edition,
and **per project and per group** for **GitLab Enterprise Edition**. and **per project and per group** for **GitLab Enterprise Edition**.
Navigate to the webhooks page by going to your project's Navigate to the webhooks page by going to your project's
**Settings ➔ Integrations**. **Settings ➔ Webhooks**.
## Maximum number of webhooks (per tier) ## Maximum number of webhooks (per tier)
......
...@@ -6997,9 +6997,6 @@ msgstr "" ...@@ -6997,9 +6997,6 @@ msgstr ""
msgid "Edit Pipeline Schedule %{id}" msgid "Edit Pipeline Schedule %{id}"
msgstr "" msgstr ""
msgid "Edit Project Hook"
msgstr ""
msgid "Edit Release" msgid "Edit Release"
msgstr "" msgstr ""
...@@ -9451,6 +9448,9 @@ msgstr "" ...@@ -9451,6 +9448,9 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}." msgid "Go to %{link_to_google_takeout}."
msgstr "" msgstr ""
msgid "Go to Webhooks"
msgstr ""
msgid "Go to commits" msgid "Go to commits"
msgstr "" msgstr ""
...@@ -10607,10 +10607,13 @@ msgstr "" ...@@ -10607,10 +10607,13 @@ msgstr ""
msgid "Instance license" msgid "Instance license"
msgstr "" msgstr ""
msgid "Integration Settings"
msgstr ""
msgid "Integrations" msgid "Integrations"
msgstr "" msgstr ""
msgid "Integrations Settings" msgid "Integrations allow you to integrate GitLab with other applications"
msgstr "" msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to." msgid "Interested parties can even contribute by pushing commits if they want to."
...@@ -14780,9 +14783,6 @@ msgstr "" ...@@ -14780,9 +14783,6 @@ msgstr ""
msgid "Project Files" msgid "Project Files"
msgstr "" msgstr ""
msgid "Project Hooks"
msgstr ""
msgid "Project ID" msgid "Project ID"
msgstr "" msgstr ""
...@@ -14945,30 +14945,18 @@ msgstr "" ...@@ -14945,30 +14945,18 @@ msgstr ""
msgid "ProjectService|Comment will be posted on each event" msgid "ProjectService|Comment will be posted on each event"
msgstr "" msgstr ""
msgid "ProjectService|Integrations"
msgstr ""
msgid "ProjectService|Last edit" msgid "ProjectService|Last edit"
msgstr "" msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}" msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "" msgstr ""
msgid "ProjectService|Project services"
msgstr ""
msgid "ProjectService|Project services allow you to integrate GitLab with other applications"
msgstr ""
msgid "ProjectService|Service" msgid "ProjectService|Service"
msgstr "" msgstr ""
msgid "ProjectService|Services" msgid "ProjectService|Services"
msgstr "" msgstr ""
msgid "ProjectService|Settings"
msgstr ""
msgid "ProjectService|To set up this service:" msgid "ProjectService|To set up this service:"
msgstr "" msgstr ""
...@@ -21811,6 +21799,15 @@ msgstr "" ...@@ -21811,6 +21799,15 @@ msgstr ""
msgid "WebIDE|Merge request" msgid "WebIDE|Merge request"
msgstr "" msgstr ""
msgid "Webhook"
msgstr ""
msgid "Webhook Logs"
msgstr ""
msgid "Webhook Settings"
msgstr ""
msgid "Webhooks" msgid "Webhooks"
msgstr "" msgstr ""
...@@ -21820,6 +21817,9 @@ msgstr "" ...@@ -21820,6 +21817,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group." msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "" msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
msgid "Wednesday" msgid "Wednesday"
msgstr "" msgstr ""
......
...@@ -12,12 +12,11 @@ describe Projects::HooksController do ...@@ -12,12 +12,11 @@ describe Projects::HooksController do
end end
describe '#index' do describe '#index' do
it 'redirects to settings/integrations page' do it 'renders index with 200 status code' do
get(:index, params: { namespace_id: project.namespace, project_id: project }) get :index, params: { namespace_id: project.namespace, project_id: project }
expect(response).to redirect_to( expect(response).to have_gitlab_http_status(:ok)
project_settings_integrations_path(project) expect(response).to render_template(:index)
)
end end
end end
......
...@@ -88,6 +88,7 @@ describe 'Project navbar' do ...@@ -88,6 +88,7 @@ describe 'Project navbar' do
_('General'), _('General'),
_('Members'), _('Members'),
_('Integrations'), _('Integrations'),
_('Webhooks'),
_('Repository'), _('Repository'),
_('CI / CD'), _('CI / CD'),
_('Operations'), _('Operations'),
......
...@@ -14,7 +14,7 @@ describe 'User views services' do ...@@ -14,7 +14,7 @@ describe 'User views services' do
end end
it 'shows the list of available services' do it 'shows the list of available services' do
expect(page).to have_content('Project services') expect(page).to have_content('Integrations')
expect(page).to have_content('Campfire') expect(page).to have_content('Campfire')
expect(page).to have_content('HipChat') expect(page).to have_content('HipChat')
expect(page).to have_content('Assembla') expect(page).to have_content('Assembla')
......
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
require 'spec_helper' require 'spec_helper'
describe 'Projects > Settings > Integration settings' do describe 'Projects > Settings > Webhook Settings' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:role) { :developer } let(:webhooks_path) { project_hooks_path(project) }
let(:integrations_path) { project_settings_integrations_path(project) }
before do before do
sign_in(user) sign_in(user)
...@@ -17,7 +16,7 @@ describe 'Projects > Settings > Integration settings' do ...@@ -17,7 +16,7 @@ describe 'Projects > Settings > Integration settings' do
let(:role) { :developer } let(:role) { :developer }
it 'to be disallowed to view' do it 'to be disallowed to view' do
visit integrations_path visit webhooks_path
expect(page.status_code).to eq(404) expect(page.status_code).to eq(404)
end end
...@@ -33,7 +32,7 @@ describe 'Projects > Settings > Integration settings' do ...@@ -33,7 +32,7 @@ describe 'Projects > Settings > Integration settings' do
it 'show list of webhooks' do it 'show list of webhooks' do
hook hook
visit integrations_path visit webhooks_path
expect(page.status_code).to eq(200) expect(page.status_code).to eq(200)
expect(page).to have_content(hook.url) expect(page).to have_content(hook.url)
...@@ -49,7 +48,7 @@ describe 'Projects > Settings > Integration settings' do ...@@ -49,7 +48,7 @@ describe 'Projects > Settings > Integration settings' do
end end
it 'create webhook' do it 'create webhook' do
visit integrations_path visit webhooks_path
fill_in 'hook_url', with: url fill_in 'hook_url', with: url
check 'Tag push events' check 'Tag push events'
...@@ -68,7 +67,7 @@ describe 'Projects > Settings > Integration settings' do ...@@ -68,7 +67,7 @@ describe 'Projects > Settings > Integration settings' do
it 'edit existing webhook' do it 'edit existing webhook' do
hook hook
visit integrations_path visit webhooks_path
click_link 'Edit' click_link 'Edit'
fill_in 'hook_url', with: url fill_in 'hook_url', with: url
...@@ -81,25 +80,25 @@ describe 'Projects > Settings > Integration settings' do ...@@ -81,25 +80,25 @@ describe 'Projects > Settings > Integration settings' do
it 'test existing webhook', :js do it 'test existing webhook', :js do
WebMock.stub_request(:post, hook.url) WebMock.stub_request(:post, hook.url)
visit integrations_path visit webhooks_path
find('.hook-test-button.dropdown').click find('.hook-test-button.dropdown').click
click_link 'Push events' click_link 'Push events'
expect(current_path).to eq(integrations_path) expect(current_path).to eq(webhooks_path)
end end
context 'delete existing webhook' do context 'delete existing webhook' do
it 'from webhooks list page' do it 'from webhooks list page' do
hook hook
visit integrations_path visit webhooks_path
expect { click_link 'Delete' }.to change(ProjectHook, :count).by(-1) expect { click_link 'Delete' }.to change(ProjectHook, :count).by(-1)
end end
it 'from webhook edit page' do it 'from webhook edit page' do
hook hook
visit integrations_path visit webhooks_path
click_link 'Edit' click_link 'Edit'
expect { click_link 'Delete' }.to change(ProjectHook, :count).by(-1) expect { click_link 'Delete' }.to change(ProjectHook, :count).by(-1)
......
...@@ -56,7 +56,7 @@ describe 'profiles/preferences/show' do ...@@ -56,7 +56,7 @@ describe 'profiles/preferences/show' do
expect(rendered).not_to have_sourcegraph_field expect(rendered).not_to have_sourcegraph_field
end end
it 'does not display integrations settings' do it 'does not display Integration Settings' do
expect(rendered).not_to have_integrations_section expect(rendered).not_to have_integrations_section
end end
end end
......
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