From d1c58c8a312d632c2628ee9c56590b3a592375d0 Mon Sep 17 00:00:00 2001
From: Ethan Nelson
Date: Mon, 2 May 2016 23:31:12 -0500
Subject: [PATCH] Implement project cloning
---
osmtm/__init__.py | 1 +
osmtm/static/js/project.new.js | 2 +-
osmtm/templates/project.new.mako | 40 ++++++++++++++++++++
osmtm/views/project.py | 65 ++++++++++++++++++++++++++++++++
4 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/osmtm/__init__.py b/osmtm/__init__.py
index 2b2edc8d..0fcbf03f 100644
--- a/osmtm/__init__.py
+++ b/osmtm/__init__.py
@@ -70,6 +70,7 @@ def main(global_config, **settings):
config.add_route('project_new_grid', '/project/new/grid')
config.add_route('project_new_arbitrary', '/project/new/arbitrary')
config.add_route('project_grid_simulate', '/project/grid_simulate')
+ config.add_route('project_clone', '/project_clone')
config.add_route('project_json', '/project/{project:\d+}.json')
config.add_route('project', '/project/{project:\d+}')
config.add_route('project_edit', '/project/{project:\d+}/edit')
diff --git a/osmtm/static/js/project.new.js b/osmtm/static/js/project.new.js
index 51433897..937d5f79 100644
--- a/osmtm/static/js/project.new.js
+++ b/osmtm/static/js/project.new.js
@@ -263,7 +263,7 @@ osmtm.project_new = (function() {
});
});
- $('#gridform, #arbitraryform').submit(function() {
+ $('#gridform, #arbitraryform, #cloneform').submit(function() {
window.setTimeout(function() {
$('input[type=submit]').attr('disabled', 'disabled');
$('.loading').removeClass('hidden');
diff --git a/osmtm/templates/project.new.mako b/osmtm/templates/project.new.mako
index ff1c50e4..cf3524d9 100644
--- a/osmtm/templates/project.new.mako
+++ b/osmtm/templates/project.new.mako
@@ -76,6 +76,46 @@
+
+ ${_('or')}
+
+
+<%
+ link = '%s' % (_('Clone'),)
+ text = _('${clone_link} an already existing project.', mapping={'clone_link': link})
+%>
+ ${text|n}
+
+
+
%block>
diff --git a/osmtm/views/project.py b/osmtm/views/project.py
index abb40dce..4dcfe0bc 100644
--- a/osmtm/views/project.py
+++ b/osmtm/views/project.py
@@ -45,6 +45,10 @@
Feature,
)
+from json import (
+ loads as _loads,
+)
+
import datetime
import itertools
@@ -226,6 +230,67 @@ def project_grid_simulate(request):
return FeatureCollection([Feature(geometry=shape.to_shape(geometry))])
+@view_config(route_name='project_clone', permission="project_edit")
+def project_clone(request):
+ _ = request.translate
+ user_id = authenticated_userid(request)
+ user = DBSession.query(User).get(user_id)
+
+ try:
+ id = request.params['project']
+ old_project = DBSession.query(Project).get(id)
+ new_project = Project(old_project.name, user=user)
+
+ for att in old_project.__dict__:
+ if (att[0] != '_' and att not in ['area_id', 'author_id',
+ 'created', 'done', 'id',
+ 'invalidated', 'last_update',
+ 'priority_areas', 'status',
+ 'tasks', 'validated']):
+ setattr(new_project, att, getattr(old_project, att))
+
+ if new_project.zoom is not None:
+ new_project.auto_fill(new_project.zoom)
+ else:
+ tasks = []
+ for task in old_project.tasks:
+ tasks.append(Task(None, None, None, 'SRID=4326;%S' %
+ task.geometry, _loads(task.extra_properties)))
+ new_project.tasks = tasks
+
+ if old_project.priority_areas:
+ new_project.priority_areas = []
+ for feature in old_project.priority_areas:
+ new_project.priority_areas.append(
+ PriorityArea(feature.geometry))
+
+ for locale, translation in old_project.translations.iteritems():
+ with old_project.force_locale(locale) and \
+ new_project.force_locale(locale):
+ for field in ['name', 'short_description', 'description',
+ 'instructions', 'per_task_instructions']:
+ if hasattr(old_project, field):
+ setattr(new_project, field,
+ getattr(translation, field))
+
+ DBSession.add(new_project)
+ DBSession.flush()
+
+ msg = _("""Project #${new_project_id} cloned successfully from Project
+ #${old_project_id}""", mapping={'new_project_id':
+ new_project.id,
+ 'old_project_id': id})
+ request.session.flash(msg, 'alert')
+
+ return HTTPFound(location=route_path('project_edit', request,
+ project=new_project.id))
+
+ except Exception, e:
+ msg = _("Sorry, could not create the project.
%s") % e.message
+ request.session.flash(msg, 'alert')
+ return HTTPFound(location=route_path('project_new', request))
+
+
@view_config(route_name='project_edit', renderer='project.edit.mako',
permission="project_edit")
def project_edit(request):