Add a one click import of demo project

This adds a view that performs a mocked form submission to create demo project.
It will create a new project with the name `<username>-demo` using our template
repository. If a project exists with the same repo, don't reimport. If a project
exists with the same name, throw an error and drop back to the dashboard.
auto-import
Anthony Johnson 2014-12-04 22:43:46 -08:00
parent a398d2127c
commit 7b0b677f25
5 changed files with 162 additions and 3 deletions

View File

@ -15,3 +15,10 @@ ImportWizardView = import_by_path(getattr(
'PROJECT_IMPORT_VIEW',
'projects.views.private.ImportWizardView'
))
# Project demo import
ImportDemoView = import_by_path(getattr(
settings,
'PROJECT_IMPORT_DEMO_VIEW',
'projects.views.private.ImportDemoView'
))

View File

@ -1,7 +1,7 @@
from django.conf.urls import patterns, url
from projects.views.private import AliasList, ProjectDashboard, ImportView
from projects.backends.views import ImportWizardView
from projects.backends.views import ImportWizardView, ImportDemoView
urlpatterns = patterns(
@ -20,6 +20,10 @@ urlpatterns = patterns(
ImportWizardView.as_view(),
name='projects_import_manual'),
url(r'^import/manual/demo/$',
ImportDemoView.as_view(),
name='projects_import_demo'),
url(r'^import/github/$',
'projects.views.private.project_import_github',
{'sync': False},

View File

@ -10,7 +10,7 @@ from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotAllow
from django.db.models import Q
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.views.generic import ListView, TemplateView
from django.views.generic import View, ListView, TemplateView
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext_lazy as _
from django.contrib.formtools.wizard.views import SessionWizardView
@ -304,6 +304,56 @@ class ImportView(TemplateView):
return self.wizard_class.as_view(initial_dict=initial_data)(request)
class ImportDemoView(View):
'''View to pass request on to import form to import demo project'''
form_class = ProjectBasicsForm
request = None
args = None
kwargs = None
def get(self, request, *args, **kwargs):
'''Process link request as a form post to the project import form'''
self.request = request
self.args = args
self.kwargs = kwargs
data = self.get_form_data()
project = Project.objects.filter(repo=data['repo']).first()
if project is not None:
messages.success(
request, _('The demo project is already imported!'))
else:
kwargs = self.get_form_kwargs()
form = self.form_class(data=data, **kwargs)
if form.is_valid():
project = form.save()
project.save()
trigger_build(project, basic=True)
messages.success(
request, _('Your demo project is currently being imported'))
else:
for (_f, msg) in form.errors.items():
log.error(msg)
messages.error(request,
_('There was a problem adding the demo project'))
return HttpResponseRedirect(reverse('projects_dashboard'))
return HttpResponseRedirect(reverse('projects_detail',
args=[project.slug]))
def get_form_data(self):
'''Get form data to post to import form'''
return {
'name': '{0}-demo'.format(self.request.user.username),
'repo_type': 'git',
'repo': 'https://github.com/readthedocs/template.git'
}
def get_form_kwargs(self):
'''Form kwargs passed in during instantiation'''
return {'user': self.request.user}
@login_required
def edit_alias(request, project_slug, id=None):
proj = get_object_or_404(Project.objects.for_admin_user(request.user), slug=project_slug)

View File

@ -1,3 +1,9 @@
import re
from mock import patch
from django.test import TestCase
from django.contrib.messages import constants as MSG
from rtd_tests.base import WizardTestCase
from projects.models import Project
@ -95,3 +101,91 @@ class TestAdvancedForm(TestBasicsForm):
self.assertWizardFailure(resp, 'default_version')
self.assertWizardFailure(resp, 'privacy_level')
self.assertWizardFailure(resp, 'python_interpreter')
@patch('projects.views.private.trigger_build', lambda x, basic: None)
@patch('readthedocs.projects.views.private.trigger_build', lambda x, basic: None)
class TestImportDemoView(TestCase):
'''Test project import demo view'''
fixtures = ["eric"]
def setUp(self):
self.client.login(username='eric', password='test')
def test_import_demo_pass(self):
resp = self.client.get('/dashboard/import/manual/demo/')
self.assertEqual(resp.status_code, 302)
self.assertEqual(resp['Location'],
'http://testserver/projects/eric-demo/')
resp_redir = self.client.get(resp['Location'])
self.assertEqual(resp_redir.status_code, 200)
messages = list(resp_redir.context['messages'])
self.assertEqual(messages[0].level, MSG.SUCCESS)
def test_import_demo_already_imported(self):
'''Import demo project multiple times, expect failure 2nd post'''
self.test_import_demo_pass()
project = Project.objects.get(slug='eric-demo')
resp = self.client.get('/dashboard/import/manual/demo/')
self.assertEqual(resp.status_code, 302)
self.assertEqual(resp['Location'],
'http://testserver/projects/eric-demo/')
resp_redir = self.client.get(resp['Location'])
self.assertEqual(resp_redir.status_code, 200)
messages = list(resp_redir.context['messages'])
self.assertEqual(messages[0].level, MSG.SUCCESS)
self.assertEqual(project,
Project.objects.get(slug='eric-demo'))
def test_import_demo_imported_renamed(self):
'''If the demo project is renamed, don't import another'''
self.test_import_demo_pass()
project = Project.objects.get(slug='eric-demo')
project.name = 'eric-demo-foobar'
project.save()
resp = self.client.get('/dashboard/import/manual/demo/')
self.assertEqual(resp.status_code, 302)
self.assertEqual(resp['Location'],
'http://testserver/projects/eric-demo/')
resp_redir = self.client.get(resp['Location'])
self.assertEqual(resp_redir.status_code, 200)
messages = list(resp_redir.context['messages'])
self.assertEqual(messages[0].level, MSG.SUCCESS)
self.assertRegexpMatches(messages[0].message,
r'already imported')
self.assertEqual(project,
Project.objects.get(slug='eric-demo'))
def test_import_demo_imported_duplicate(self):
'''If a project exists with same name, expect a failure importing demo
This should be edge case, user would have to import a project (not the
demo project), named user-demo, and then manually enter the demo import
URL, as the onboarding isn't shown when projects > 0
'''
self.test_import_demo_pass()
project = Project.objects.get(slug='eric-demo')
project.repo = 'file:///foobar'
project.save()
resp = self.client.get('/dashboard/import/manual/demo/')
self.assertEqual(resp.status_code, 302)
self.assertEqual(resp['Location'],
'http://testserver/dashboard/')
resp_redir = self.client.get(resp['Location'])
self.assertEqual(resp_redir.status_code, 200)
messages = list(resp_redir.context['messages'])
self.assertEqual(messages[0].level, MSG.ERROR)
self.assertRegexpMatches(messages[0].message,
r'There was a problem')
self.assertEqual(project,
Project.objects.get(slug='eric-demo'))

View File

@ -14,6 +14,10 @@
{% endblocktrans %}
</p>
<p>
Want to try a demo? <a href="{% url "projects_import_demo" %}">Import our own demo project</a>.
</p>
<input type="submit" value="Import a Project" />
</form>
{% endwith %}