]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7918 Rewrite "Deletion" project page (#1116)
authorStas Vilchik <vilchiks@gmail.com>
Tue, 26 Jul 2016 14:11:54 +0000 (16:11 +0200)
committerGitHub <noreply@github.com>
Tue, 26 Jul 2016 14:11:54 +0000 (16:11 +0200)
21 files changed:
it/it-tests/src/test/resources/projectAdministration/ProjectAdministrationTest/project-deletion/project-deletion.html
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentNavigationAction.java
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/on_module.json
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/quality_profile_admin.json
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/with_admin_rights.json
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/with_all_properties.json
server/sonar-web/src/main/js/api/components.js
server/sonar-web/src/main/js/apps/project-admin/app.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModal.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModalTemplate.hbs [new file with mode: 0644]
server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js [new file with mode: 0644]
server/sonar-web/src/main/js/main/nav/app.js
server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
server/sonar-web/src/main/webapp/WEB-INF/app/views/project/_delete_form.html.erb [deleted file]
server/sonar-web/src/main/webapp/WEB-INF/app/views/project/deletion.html.erb
server/sonar-web/src/main/webapp/WEB-INF/app/views/project/pending_deletion.html.erb [deleted file]
server/sonar-web/webpack.config.js
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 16a057b896ad8ca23258ccdd2c353a14d24930ff..c77796182ba9316d37bcde647d2ab743e9b91900 100644 (file)
 </tr>
 <tr>
        <td>open</td>
-       <td>/dashboard/index/sample</td>
+       <td>/project/deletion?id=sample</td>
        <td></td>
 </tr>
-<tr>
-    <td>click</td>
-    <td>css=#context-navigation .navbar-admin-link</td>
-    <td></td>
-</tr>
 <tr>
        <td>waitForElementPresent</td>
-       <td>link=Deletion</td>
+       <td>css=#delete-project</td>
        <td></td>
 </tr>
 <tr>
-       <td>clickAndWait</td>
-       <td>link=Deletion</td>
+       <td>click</td>
+       <td>css=#delete-project</td>
        <td></td>
 </tr>
 <tr>
-  <td>click</td>
-  <td>delete_resource</td>
-  <td></td>
-</tr>
-<tr>
-       <td>waitForText</td>
-       <td>delete-project-form</td>
-       <td>*Delete Project*</td>
+       <td>waitForElementPresent</td>
+       <td>css=#delete-project-confirm</td>
+       <td></td>
 </tr>
 <tr>
        <td>click</td>
-       <td>delete-project-submit</td>
+       <td>css=#delete-project-confirm</td>
        <td></td>
 </tr>
 <tr>
-       <td>pause</td>
-       <td>3000</td>
-       <td>NOTE: necessary as the deletion is asynchronous</td>
+       <td>waitForElementNotPresent</td>
+       <td>css=#delete-project-confirm</td>
+       <td></td>
 </tr>
 <tr>
        <td>open</td>
index f7aca74f29e3bf1956db408460598594f5a6d4bc..4d824d7806edffa33f98c80f658063713a59ab2f 100644 (file)
@@ -66,7 +66,6 @@ public class ComponentNavigationAction implements NavigationWsAction {
   private static final String PROPERTY_HAS_ROLE_POLICY = "hasRolePolicy";
   private static final String PROPERTY_MODIFIABLE_HISTORY = "modifiable_history";
   private static final String PROPERTY_UPDATABLE_KEY = "updatable_key";
-  private static final String PROPERTY_DELETABLE = "deletable";
 
   private final DbClient dbClient;
   private final Views views;
@@ -221,7 +220,6 @@ public class ComponentNavigationAction implements NavigationWsAction {
     json.prop("showPermissions", isAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY));
     json.prop("showHistory", isAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY));
     json.prop("showUpdateKey", isAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY));
-    json.prop("showDeletion", isAdmin && componentTypeHasProperty(component, PROPERTY_DELETABLE));
     json.prop("showBackgroundTasks", ActivityAction.isAllowedOnComponentUuid(userSession, component.uuid()));
   }
 
index 19646c8fa0041cfe51f2c4d51da508198789464b..51e9d4130035e6f19f6cdddd74e85acb83b477d0 100644 (file)
@@ -15,7 +15,6 @@
     "showPermissions": false,
     "showHistory": false,
     "showUpdateKey": false,
-    "showDeletion": false,
     "extensions": []
   },
   "breadcrumbs": [
index 3e6474a44204506a19f66bce2c5db753356f996c..594a12562e67d71f9e390423598f870bd97bffa8 100644 (file)
@@ -14,8 +14,7 @@
     "showLinks": false,
     "showPermissions": false,
     "showHistory": false,
-    "showUpdateKey": false,
-    "showDeletion": false
+    "showUpdateKey": false
   },
   "breadcrumbs": [
     {
index e60ff54767d98493ee3c364a83ee185b9f7810e0..c213ac063687b8159aec6dbba4dfd607af696364 100644 (file)
@@ -15,7 +15,6 @@
     "showPermissions": false,
     "showHistory": false,
     "showUpdateKey": false,
-    "showDeletion": false,
     "extensions": [
       {
         "name": "First Page",
index 2352e48e4849e17ad0fbeb0750b330a2309956d1..930df6729eff624adc4f640704a5ba0f8a50caa0 100644 (file)
@@ -15,7 +15,6 @@
     "showPermissions": true,
     "showHistory": true,
     "showUpdateKey": true,
-    "showDeletion": true,
     "extensions": []
   },
   "breadcrumbs": [
index 3c7581dba9b76b7050e375a42ae99e828ffc9eb4..f0f49a636b4d7b713e48bc9ebaba6fa870a94e31 100644 (file)
@@ -39,6 +39,12 @@ export function deleteComponents (data) {
   return post(url, data);
 }
 
+export function deleteProject (key) {
+  const url = '/api/projects/delete';
+  const data = { key };
+  return post(url, data);
+}
+
 export function createProject (data) {
   const url = '/api/projects/create';
   return postJSON(url, data);
diff --git a/server/sonar-web/src/main/js/apps/project-admin/app.js b/server/sonar-web/src/main/js/apps/project-admin/app.js
new file mode 100644 (file)
index 0000000..ee34935
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import React from 'react';
+import { render } from 'react-dom';
+import { Router, Route, useRouterHistory } from 'react-router';
+import { createHistory } from 'history';
+import Deletion from './deletion/Deletion';
+
+window.sonarqube.appStarted.then(options => {
+  const el = document.querySelector(options.el);
+
+  const history = useRouterHistory(createHistory)({
+    basename: window.baseUrl + '/project'
+  });
+
+  const withComponent = ComposedComponent => props =>
+      <ComposedComponent {...props} component={options.component}/>;
+
+  render((
+      <Router history={history}>
+        <Route path="/deletion" component={withComponent(Deletion)}/>
+      </Router>
+  ), el);
+});
diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModal.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModal.js
new file mode 100644 (file)
index 0000000..e5e6f71
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import ModalForm from '../../../components/common/modal-form';
+import Template from './ConfirmationModalTemplate.hbs';
+import { deleteProject } from '../../../api/components';
+
+export default ModalForm.extend({
+  template: Template,
+
+  onFormSubmit () {
+    ModalForm.prototype.onFormSubmit.apply(this, arguments);
+    this.disableForm();
+
+    deleteProject(this.options.project.key)
+        .then(() => {
+          this.trigger('done');
+        })
+        .catch(function (e) {
+          e.response.json().then(r => {
+            this.showErrors(r.errors, r.warnings);
+            this.enableForm();
+          });
+        });
+  },
+
+  serializeData () {
+    return { project: this.options.project };
+  }
+});
+
diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModalTemplate.hbs b/server/sonar-web/src/main/js/apps/project-admin/deletion/ConfirmationModalTemplate.hbs
new file mode 100644 (file)
index 0000000..5da393e
--- /dev/null
@@ -0,0 +1,13 @@
+<form id="deactivate-user-form" autocomplete="off">
+  <div class="modal-head">
+    <h2>{{t 'qualifiers.delete.TRK'}}</h2>
+  </div>
+  <div class="modal-body">
+    <div class="js-modal-messages"></div>
+    {{tp 'project_deletion.delete_resource_confirmation' project.name}}
+  </div>
+  <div class="modal-foot">
+    <button id="delete-project-confirm" class="button-red">{{t 'delete'}}</button>
+    <a href="#" class="js-modal-close">{{t 'cancel'}}</a>
+  </div>
+</form>
diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js
new file mode 100644 (file)
index 0000000..6756389
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import React from 'react';
+import Header from './Header';
+import Form from './Form';
+
+export default class Deletion extends React.Component {
+  static propTypes = {
+    component: React.PropTypes.object.isRequired
+  };
+
+  render () {
+    return (
+        <div className="page page-limited">
+          <Header/>
+          <Form component={this.props.component}/>
+        </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js
new file mode 100644 (file)
index 0000000..81d52fb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import React from 'react';
+import ConfirmationModal from './ConfirmationModal';
+import { translate } from '../../../helpers/l10n';
+
+export default class Form extends React.Component {
+  static propTypes = {
+    component: React.PropTypes.object.isRequired
+  };
+
+  handleDelete (e) {
+    e.preventDefault();
+    new ConfirmationModal({ project: this.props.component })
+        .on('done', () => {
+          window.location = window.baseUrl + '/';
+        })
+        .render();
+  }
+
+  render () {
+    return (
+        <form onSubmit={this.handleDelete.bind(this)}>
+          <button id="delete-project" className="button-red">
+            {translate('delete')}
+          </button>
+        </form>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js
new file mode 100644 (file)
index 0000000..39bd303
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import React from 'react';
+import { translate } from '../../../helpers/l10n';
+
+export default class Header extends React.Component {
+  render () {
+    return (
+        <header className="page-header">
+          <h1 className="page-title">
+            {translate('deletion.page')}
+          </h1>
+          <div className="page-description">
+            {translate('project_deletion.page.description')}
+          </div>
+        </header>
+    );
+  }
+}
index 9c0526f57a0175ea00abecfae79a10c90f8f7996..902e6ea07ef4cdd24f0e690f7119754e38251a8c 100644 (file)
@@ -67,8 +67,12 @@ export default class App {
   static renderComponentNav (options) {
     return getComponentNavigation(options.componentKey).then(component => {
       const el = document.getElementById('context-navigation');
+      const nextComponent = {
+        ...component,
+        qualifier: _.last(component.breadcrumbs).qualifier
+      };
       if (el) {
-        ReactDOM.render(<ComponentNav component={component} conf={component.configuration || {}}/>, el);
+        ReactDOM.render(<ComponentNav component={nextComponent} conf={component.configuration || {}}/>, el);
       }
       return component;
     });
index 4aaf6ff239ee46d4f70c2f02c9a90e11887435e0..ad6ad6c6e76b1b444d426aa88d19b4a1242535ae 100644 (file)
@@ -42,12 +42,11 @@ export default React.createClass({
   mixins: [LinksMixin],
 
   isDeveloper() {
-    const qualifier = _.last(this.props.component.breadcrumbs).qualifier;
-    return qualifier === 'DEV';
+    return this.props.component.qualifier === 'DEV';
   },
 
   isView() {
-    const qualifier = _.last(this.props.component.breadcrumbs).qualifier;
+    const { qualifier } = this.props.component;
     return qualifier === 'VW' || qualifier === 'SVW';
   },
 
@@ -100,7 +99,6 @@ export default React.createClass({
   renderAdministration() {
     const shouldShowAdministration =
         this.props.conf.showBackgroundTasks ||
-        this.props.conf.showDeletion ||
         this.props.conf.showHistory ||
         this.props.conf.showLinks ||
         this.props.conf.showManualMeasures ||
@@ -132,8 +130,8 @@ export default React.createClass({
             {this.renderHistoryLink()}
             {this.renderBackgroundTasksLink()}
             {this.renderUpdateKeyLink()}
-            {this.renderDeletionLink()}
             {this.renderExtensions()}
+            {this.renderDeletionLink()}
           </ul>
         </li>
     );
@@ -212,9 +210,12 @@ export default React.createClass({
   },
 
   renderDeletionLink() {
-    if (!this.props.conf.showDeletion) {
+    const { qualifier } = this.props.component;
+
+    if (qualifier !== 'TRK' && qualifier !== 'VW') {
       return null;
     }
+
     const url = `/project/deletion?id=${encodeURIComponent(this.props.component.key)}`;
     return this.renderLink(url, translate('deletion.page'), '/project/deletion');
   },
index a85983ebeded6b8aa73d96de7f79c31a0c967f9e..ab0d54009634180b0dae66848f841ae56c914b2c 100644 (file)
@@ -20,7 +20,6 @@
 class ProjectController < ApplicationController
   verify :method => :post, :only => [:set_links, :set_exclusions, :delete_exclusions, :update_key, :perform_key_bulk_update],
          :redirect_to => {:action => :index}
-  verify :method => :delete, :only => [:delete], :redirect_to => {:action => :index}
 
   SECTION=Navigation::SECTION_RESOURCE
 
@@ -29,56 +28,8 @@ class ProjectController < ApplicationController
     redirect_to :overwrite_params => {:controller => :dashboard, :action => 'index'}
   end
 
-  def delete_form
-    @project = get_current_project(params[:id])
-    render :partial => 'delete_form'
-  end
-
-  def delete
-    @project = get_current_project(params[:id])
-
-    # Ask the resource deletion manager to start the migration
-    # => this is an asynchronous AJAX call
-    ResourceDeletionManager.instance.delete_resources([@project.id])
-
-    # and return some text that will actually never be displayed
-    render :text => ResourceDeletionManager.instance.message
-  end
-
   def deletion
     @project = get_current_project(params[:id])
-
-    if java_facade.getResourceTypeBooleanProperty(@project.qualifier, 'deletable')
-      deletion_manager = ResourceDeletionManager.instance
-      if deletion_manager.currently_deleting_resources? ||
-          (!deletion_manager.currently_deleting_resources? && deletion_manager.deletion_failures_occured?)
-        # a deletion is happening or it has just finished with errors => display the message from the Resource Deletion Manager
-        render :template => 'project/pending_deletion'
-      else
-        @snapshot=@project.last_snapshot
-      end
-    else
-      redirect_to :action => 'index', :id => params[:id]
-    end
-  end
-
-  def pending_deletion
-    deletion_manager = ResourceDeletionManager.instance
-
-    if deletion_manager.currently_deleting_resources? ||
-        (!deletion_manager.currently_deleting_resources? && deletion_manager.deletion_failures_occured?)
-      # display the same page again and again
-      # => implicit render "pending_deletion.html.erb"
-    else
-      redirect_to_default
-    end
-  end
-
-  def dismiss_deletion_message
-    # It is important to reinit the ResourceDeletionManager so that the deletion screens can be available again
-    ResourceDeletionManager.instance.reinit
-
-    redirect_to :action => 'deletion', :id => params[:id]
   end
 
   # GET /project/profile?id=<project id>
@@ -227,18 +178,6 @@ class ProjectController < ApplicationController
     @project = get_current_project(params[:id])
   end
 
-  def delete_snapshot_history
-    @project = get_current_project(params[:id])
-
-    sid = params[:snapshot_id]
-    if sid
-      Snapshot.update_all("status='U'", ["id=?", sid.to_i])
-      flash[:notice] = message('project_history.snapshot_deleted')
-    end
-
-    redirect_to :action => 'history', :id => @project.id
-  end
-
   def links
     @project = get_current_project(params[:id])
 
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/project/_delete_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/project/_delete_form.html.erb
deleted file mode 100644 (file)
index 79c73cd..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<% resource_qualifier = message('qualifier.' + @project.qualifier) %>
-<form id="delete-project-form" method="post" action="<%= ApplicationController.root_context -%>/project/delete">
-  <fieldset>
-    <div class="modal-head">
-      <h2><%= message('project_deletion.page', :params => resource_qualifier) -%></h2>
-    </div>
-    <div class="modal-body">
-      <%= message('project_deletion.delete_resource_confirmation', :params => resource_qualifier) %>
-    </div>
-    <div class="modal-foot">
-      <span id="delete-project-loading-image" class="loading-image hidden"><%= image_tag 'loading.gif' %></span>
-      <input type="submit" value="<%= message('delete') -%>" id="delete-project-submit" onclick="return displayLoadingImage()"/>
-      <a href="#" onclick="return closeModalWindow()" id="delete-project-cancel"><%= message('cancel') -%></a>
-    </div>
-  </fieldset>
-</form>
-<script>
-  $j("#delete-project-form").modalForm({
-    success: function () {
-      $j.ajax({
-        url: "<%= ApplicationController.root_context-%>/project/delete/<%= h(@project.id) -%>",
-        success: function (request) {
-          window.location = '<%= url_for(:action => 'pending_deletion',:id => @project.id)-%>';
-        },
-        data: $j(this).serialize(),
-        type: 'delete'
-      });
-    }
-  });
-
-  function displayLoadingImage() {
-    $j('#delete-project-loading-image').removeClass("hidden");
-  }
-</script>
index da66ac28b95fce24e0c9a3835f115d507a2e5659..e9dd9ae341023b9b8daca7528d9cb6c8edd3ea46 100644 (file)
@@ -1,18 +1,3 @@
-<div class="page">
-  <%
-     if !@snapshot || @project.root?
-       resource_qualifier = message('qualifier.' + @project.qualifier)
-       delete_resource_message = message('project_deletion.page', :params => resource_qualifier)
-  %>
-    <header class="page-header">
-      <h1 class="page-title"><%= delete_resource_message -%></h1>
-      <p class="page-description"><%= message('project_deletion.page.description') -%></p>
-    </header>
-
-    <div class="yui-g widget" id="widget_delete_project">
-      <div class="alert alert-warning spacer-bottom"><%= message('project_deletion.operation_cannot_be_undone') -%></div>
-      <a id="delete_resource" class="open-modal button button-red"
-         href="<%= ApplicationController.root_context -%>/project/delete_form/<%= h(@project.id) -%>"><%= delete_resource_message -%></a>
-    </div>
-  <% end %>
-</div>
+<% content_for :extra_script do %>
+  <script src="<%= ApplicationController.root_context -%>/js/bundles/project-admin.js?v=<%= sonar_version -%>"></script>
+<% end %>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/project/pending_deletion.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/project/pending_deletion.html.erb
deleted file mode 100644 (file)
index 7d96f93..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-<%= render :partial => 'bulk_deletion/pending_deletions_screen', 
-           :locals => {:url_after_dismiss => url_for(:action => 'dismiss_deletion_message', :id => params[:id])} -%>
\ No newline at end of file
index d64f64ab975abd89695b2c235f14315b35549bcb..cea911812e7d6240b36cc9ab07d87993c320322a 100644 (file)
@@ -45,6 +45,7 @@ module.exports = {
     'metrics': './src/main/js/apps/metrics/app.js',
     'overview': './src/main/js/apps/overview/app.js',
     'permission-templates': './src/main/js/apps/permission-templates/app.js',
+    'project-admin': './src/main/js/apps/project-admin/app.js',
     'project-permissions': './src/main/js/apps/permissions/project/app.js',
     'projects': './src/main/js/apps/projects/app.js',
     'quality-gates': './src/main/js/apps/quality-gates/app.js',
index c2ed6ed763cd77104654e5ecf3b2d81d06615ecc..94cab9055d4cf93bfe02d0945137ce5a5ef96131 100644 (file)
@@ -508,8 +508,7 @@ bulk_deletion.page.description=Use this page to delete multiple projects at once
 update_key.page=Update Key
 update_key.page.description=Edit the keys of a project and/or its modules. Key changes must be made here BEFORE analyzing the project with the new keys, otherwise the analysis will simply create another project with the new key, rather than updating the existing project.
 deletion.page=Deletion
-project_deletion.page=Delete {0}
-project_deletion.page.description=Delete this project from the SonarQube database.
+project_deletion.page.description=Delete this project from SonarQube. The operation cannot be undone.
 provisioning.page=Provisioning
 provisioning.page.description=Use this page to initialize projects if you would like to configure them before the first analysis. Once a project is provisioned, you have access to perform all project configurations on it.
 
@@ -1640,8 +1639,7 @@ project_quality_gate.default_qgate=Default
 #
 #------------------------------------------------------------------------------
 
-project_deletion.operation_cannot_be_undone=This operation can not be undone.
-project_deletion.delete_resource_confirmation=Are you sure you want to delete this {0}?
+project_deletion.delete_resource_confirmation=Are you sure you want to delete "{0}"?
 
 
 #------------------------------------------------------------------------------