Commit 21e9ed2e authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'improve-danger-zone' into 'master'

Improve danger zone

* show transfer/remove boxes by default
* ask person to type project name before transfer/remove

Fixes #1347

See merge request !1161
parents 80f9b758 ab68fd22
...@@ -177,6 +177,13 @@ $ -> ...@@ -177,6 +177,13 @@ $ ->
$(@).closest(".diff-file").find(".notes_holder").toggle() $(@).closest(".diff-file").find(".notes_holder").toggle()
e.preventDefault() e.preventDefault()
$(document).on "click", '.js-confirm-danger', (e) ->
e.preventDefault()
btn = $(e.target)
text = btn.data("confirm-danger-message")
form = btn.closest("form")
new ConfirmDangerModal(form, text)
(($) -> (($) ->
# Disable an element and add the 'disabled' Bootstrap class # Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: -> $.fn.extend disable: ->
......
class ConfirmDangerModal
constructor: (form, text) ->
@form = form
$('.js-confirm-text').text(text || '')
$('.js-confirm-danger-input').val('')
$('#modal-confirm-danger').modal('show')
project_path = $('.js-confirm-danger-match').text()
submit = $('.js-confirm-danger-submit')
submit.disable()
$('.js-confirm-danger-input').on 'input', ->
if rstrip($(@).val()) is project_path
submit.enable()
else
submit.disable()
$('.js-confirm-danger-submit').on 'click', =>
@form.submit()
@ConfirmDangerModal = ConfirmDangerModal
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.issue-box { .issue-box {
color: #555; color: #555;
margin:20px 0; margin:20px 0;
background: #f9f9f9; background: $box_bg;
border-top-left-radius: 5px; border-top-left-radius: 5px;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
......
...@@ -233,8 +233,8 @@ $list-group-active-bg: $bg_primary; ...@@ -233,8 +233,8 @@ $list-group-active-bg: $bg_primary;
} }
.form-actions { .form-actions {
margin-bottom: 0; margin: -15px;
background: #FFF; margin-top: 18px;
} }
} }
...@@ -262,53 +262,33 @@ $list-group-active-bg: $bg_primary; ...@@ -262,53 +262,33 @@ $list-group-active-bg: $bg_primary;
} }
.panel-danger { .panel-danger {
border-color: $border_danger; @include panel-colored;
.panel-heading { .panel-heading {
color: #ffffff; color: $border_danger;
background-color: $bg_danger;
border-color: $border_danger; border-color: $border_danger;
a {
color: #FFF;
text-decoration: underline;
}
} }
} }
.panel-success { .panel-success {
border-color: $border_success; @include panel-colored;
.panel-heading { .panel-heading {
color: #ffffff; color: $border_success;
background-color: $bg_success;
border-color: $border_success; border-color: $border_success;
a {
color: #FFF;
text-decoration: underline;
}
} }
} }
.panel-primary { .panel-primary {
border-color: $border_primary; @include panel-colored;
.panel-heading { .panel-heading {
color: #ffffff; color: $border_primary;
background-color: $bg_primary;
border-color: $border_primary; border-color: $border_primary;
a {
color: #FFF;
text-decoration: underline;
}
} }
} }
.panel-warning { .panel-warning {
border-color: $border_warning; @include panel-colored;
.panel-heading { .panel-heading {
color: #ffffff; color: $border_warning;
background-color: $bg_warning;
border-color: $border_warning; border-color: $border_warning;
a {
color: #FFF;
text-decoration: underline;
}
} }
} }
...@@ -132,3 +132,14 @@ ...@@ -132,3 +132,14 @@
white-space: nowrap; white-space: nowrap;
max-width: $max_width; max-width: $max_width;
} }
@mixin panel-colored {
border: none;
background: $box_bg;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
.panel-heading {
font-weight: bold;
background-color: $box_bg;
}
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
*/ */
$style_color: #474D57; $style_color: #474D57;
$hover: #FFECDB; $hover: #FFECDB;
$box_bg: #F9F9F9;
/* /*
* Link colors * Link colors
......
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
} }
.mr-state-widget { .mr-state-widget {
background: #f9f9f9; background: $box_bg;
margin-bottom: 20px; margin-bottom: 20px;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
......
...@@ -56,6 +56,10 @@ module ProjectsHelper ...@@ -56,6 +56,10 @@ module ProjectsHelper
"You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?" "You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?"
end end
def transfer_project_message(project)
"You are going to transfer #{project.name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
end
def project_nav_tabs def project_nav_tabs
@nav_tabs ||= get_project_nav_tabs(@project, current_user) @nav_tabs ||= get_project_nav_tabs(@project, current_user)
end end
......
...@@ -86,101 +86,92 @@ ...@@ -86,101 +86,92 @@
.danger-settings.js-toggle-container .danger-settings
.centered-light-block - if can? current_user, :archive_project, @project
%h3 - if @project.archived?
%i.fa.fa-exclamation-triangle .panel.panel-success
Dangerous settings
%p Project settings below may result in data loss!
= link_to '#', class: 'btn js-toggle-button' do
Show them to me
%i.fa.fa-chevron-down
.js-toggle-content.hide
- if can? current_user, :archive_project, @project
.panel.panel-default.panel.panel-warning
.panel-heading .panel-heading
- if @project.archived? Unarchive project
Unarchive project
- else
Archive project
.panel-body .panel-body
- if @project.archived? %p
%p Unarchiving the project will mark its repository as active.
Unarchiving the project will mark its repository as active. %br
%br The project can be committed to.
The project can be committed to. %br
%br %strong Once active this project shows up in the search and on the dashboard.
%strong Once active this project shows up in the search and on the dashboard. = link_to 'Unarchive', unarchive_project_path(@project),
= link_to 'Unarchive', unarchive_project_path(@project), data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, method: :post, class: "btn btn-success"
method: :post, class: "btn btn-remove"
- else
%p
Archiving the project will mark its repository as read-only.
%br
It is hidden from the dashboard and doesn't show up in searches.
%br
%strong Archived projects cannot be committed to!
= link_to 'Archive', archive_project_path(@project),
data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
method: :post, class: "btn btn-warning"
- else - else
.nothing-here-block Only the project owner can archive a project .panel.panel-warning
.panel-heading
.panel.panel-default.panel.panel-warning Archive project
.panel-heading Rename repository .panel-body
%p
Archiving the project will mark its repository as read-only.
%br
It is hidden from the dashboard and doesn't show up in searches.
%br
%strong Archived projects cannot be committed to!
= link_to 'Archive', archive_project_path(@project),
data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
method: :post, class: "btn btn-warning"
- else
.nothing-here-block Only the project owner can archive a project
.panel.panel-default.panel.panel-warning
.panel-heading Rename repository
.errors-holder
.panel-body
= form_for(@project, html: { class: 'form-horizontal' }) do |f|
.form-group
= f.label :path, class: 'control-label' do
%span Path
.col-sm-9
.form-group
.input-group
= f.text_field :path, class: 'form-control'
%span.input-group-addon .git
%ul
%li Be careful. Renaming a project's repository can have unintended side effects.
%li You will need to update your local repositories to point to the new location.
.form-actions
= f.submit 'Rename', class: "btn btn-warning"
- if can?(current_user, :change_namespace, @project)
.panel.panel-default.panel.panel-danger
.panel-heading Transfer project
.errors-holder .errors-holder
.panel-body .panel-body
= form_for(@project, html: { class: 'form-horizontal' }) do |f| = form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
.form-group .form-group
= f.label :path, class: 'control-label' do = f.label :namespace_id, class: 'control-label' do
%span Path %span Namespace
.col-sm-9 .col-sm-10
.form-group .form-group
.input-group = f.select :namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace' }, { class: 'select2' }
= f.text_field :path, class: 'form-control'
%span.input-group-addon .git
%ul %ul
%li Be careful. Renaming a project's repository can have unintended side effects. %li Be careful. Changing the project's namespace can have unintended side effects.
%li You can only transfer the project to namespaces you manage.
%li You will need to update your local repositories to point to the new location. %li You will need to update your local repositories to point to the new location.
.form-actions .form-actions
= f.submit 'Rename', class: "btn btn-warning" = f.submit 'Transfer', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
- else
- if can?(current_user, :change_namespace, @project) .nothing-here-block Only the project owner can transfer a project
.panel.panel-default.panel.panel-danger
.panel-heading Transfer project
.errors-holder
.panel-body
= form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
.form-group
= f.label :namespace_id, class: 'control-label' do
%span Namespace
.col-sm-10
.form-group
= f.select :namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace' }, { class: 'select2' }
%ul
%li Be careful. Changing the project's namespace can have unintended side effects.
%li You can only transfer the project to namespaces you manage.
%li You will need to update your local repositories to point to the new location.
.form-actions
= f.submit 'Transfer', class: "btn btn-remove"
- else
.nothing-here-block Only the project owner can transfer a project
- if can?(current_user, :remove_project, @project) - if can?(current_user, :remove_project, @project)
.panel.panel-default.panel.panel-danger .panel.panel-default.panel.panel-danger
.panel-heading Remove project .panel-heading Remove project
.panel-body .panel-body
= form_tag(project_path(@project), method: :delete, html: { class: 'form-horizontal'}) do
%p %p
Removing the project will delete its repository and all related resources including issues, merge requests etc. Removing the project will delete its repository and all related resources including issues, merge requests etc.
%br %br
%strong Removed projects cannot be restored! %strong Removed projects cannot be restored!
= link_to 'Remove project', @project, data: { confirm: remove_project_message(@project) }, method: :delete, class: "btn btn-remove" = link_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
- else - else
.nothing-here-block Only project owner can remove a project .nothing-here-block Only project owner can remove a project
.save-project-loader.hide .save-project-loader.hide
.center .center
...@@ -188,3 +179,6 @@ ...@@ -188,3 +179,6 @@
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
Saving project. Saving project.
%p Please wait a moment, this page will automatically refresh when ready. %p Please wait a moment, this page will automatically refresh when ready.
= render 'shared/confirm_modal', phrase: @project.path
#modal-confirm-danger.modal.hide{tabindex: -1}
.modal-dialog
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h4 Confirmation required
.modal-body
%p.cred.lead.js-confirm-text
%p
This action can lead to data loss.
To prevent accidental actions we ask you to confirm your intention.
%br
Please type
%code.js-confirm-danger-match #{phrase}
to proceed or close this modal to cancel
.form-group
= text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input'
.form-group
= submit_tag 'Confirm', class: "btn btn-danger js-confirm-danger-submit"
...@@ -10,8 +10,12 @@ describe "Projects", feature: true do ...@@ -10,8 +10,12 @@ describe "Projects", feature: true do
visit edit_project_path(@project) visit edit_project_path(@project)
end end
it "should be correct path" do it "should be correct path", js: true do
expect { click_link "Remove project" }.to change {Project.count}.by(-1) expect {
click_link "Remove project"
fill_in 'confirm_name_input', with: @project.path
click_button 'Confirm'
}.to change {Project.count}.by(-1)
end end
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