Repository: readthedocs/readthedocs.org

Issue:
Notify the user when deleting a superproject
Now, when the user deletes a superproject (a `Project` that has subproject(s)) that Project is deleted but all the subprojects are "disconnected" from its parent and now become just regular Project (change the hierarchy from sub to project).

This means that the URL for those subproject changes also and probably other things are changed also.

We need to find a good pattern to handle this in a better way, but our first step will be to alert the user that this will happen when they try to delete the superproject.

The flow should be:

1. user tries to remove the superproject
1. user is informed in a very well detailed way what will happen and how the subprojects will be affected
1. user accepts it
1. project is deleted

For this issue we need:

- [ ] know exactly what is happening now when a superproject is deleted
- [ ] write a good message to communicate this to the user
- [ ] implement the flow proposed in this issue
- [ ] write some tests for this flow

Ref: #3649 


Discussion:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/readthedocs/projects/views/private.py b/readthedocs/projects/views/private.py
--- a/readthedocs/projects/views/private.py
+++ b/readthedocs/projects/views/private.py
@@ -243,6 +243,11 @@ def project_delete(request, project_slug):
         slug=project_slug,
     )
 
+    context = {
+        'project': project,
+        'is_superproject': project.subprojects.all().exists()
+    }
+
     if request.method == 'POST':
         broadcast(
             type='app',
@@ -254,7 +259,7 @@ def project_delete(request, project_slug):
         project_dashboard = reverse('projects_dashboard')
         return HttpResponseRedirect(project_dashboard)
 
-    return render(request, 'projects/project_delete.html', {'project': project})
+    return render(request, 'projects/project_delete.html', context)
 
 
 class ImportWizardView(ProjectSpamMixin, PrivateViewMixin, SessionWizardView):


Test patch:
diff --git a/readthedocs/rtd_tests/tests/test_project_views.py b/readthedocs/rtd_tests/tests/test_project_views.py
--- a/readthedocs/rtd_tests/tests/test_project_views.py
+++ b/readthedocs/rtd_tests/tests/test_project_views.py
@@ -414,6 +414,24 @@ def test_delete_project(self):
                 args=[(project.doc_path,)],
             )
 
+    def test_delete_superproject(self):
+        super_proj = get(Project, slug='pip', users=[self.user])
+        sub_proj = get(Project, slug='test-sub-project', users=[self.user])
+
+        self.assertFalse(super_proj.subprojects.all().exists())
+        super_proj.add_subproject(sub_proj)
+
+        response = self.client.get('/dashboard/pip/delete/')
+        self.assertEqual(response.status_code, 200)
+        self.assertContains(
+            response,
+            'This project <a href="/dashboard/pip/subprojects/">has subprojects</a> under it. '
+            'Deleting this project will make them to become regular projects. '
+            'This will break the URLs of all its subprojects and they will be served normally as other projects.',
+            count=1,
+            html=True,
+        )
+
     def test_subproject_create(self):
         project = get(Project, slug='pip', users=[self.user])
         subproject = get(Project, users=[self.user])