settings: make site export async (#34915)
This commit is contained in:
parent
bef5381961
commit
c26cfd1734
|
@ -9,6 +9,7 @@ import re
|
|||
import shutil
|
||||
import StringIO
|
||||
import tarfile
|
||||
import urlparse
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
import zipfile
|
||||
|
@ -3942,11 +3943,20 @@ def test_settings_export_import(pub):
|
|||
resp = resp.form.submit('cancel')
|
||||
resp = app.get('/backoffice/settings/export')
|
||||
resp = resp.form.submit('submit')
|
||||
assert resp.location.startswith('http://example.net/backoffice/settings/export?job=')
|
||||
job_id = urlparse.parse_qs(urlparse.urlparse(resp.location).query)['job'][0]
|
||||
resp = resp.follow()
|
||||
assert 'completed' in resp.body
|
||||
resp = resp.click('Download Export')
|
||||
zip_content = StringIO.StringIO(resp.body)
|
||||
zipf = zipfile.ZipFile(zip_content, 'a')
|
||||
filelist = zipf.namelist()
|
||||
assert len(filelist) == 0
|
||||
|
||||
# check afterjob ajax call
|
||||
status_resp = app.get('/afterjobs/' + job_id)
|
||||
assert status_resp.body == 'completed|completed'
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'foo'
|
||||
formdef.store()
|
||||
|
@ -3971,6 +3981,10 @@ def test_settings_export_import(pub):
|
|||
|
||||
resp = app.get('/backoffice/settings/export')
|
||||
resp = resp.form.submit('submit')
|
||||
assert resp.location.startswith('http://example.net/backoffice/settings/export?job=')
|
||||
job_id = urlparse.parse_qs(urlparse.urlparse(resp.location).query)['job'][0]
|
||||
resp = resp.follow()
|
||||
resp = resp.click('Download Export')
|
||||
zip_content = StringIO.StringIO(resp.body)
|
||||
zipf = zipfile.ZipFile(zip_content, 'a')
|
||||
filelist = zipf.namelist()
|
||||
|
@ -4006,6 +4020,10 @@ def test_settings_export_import(pub):
|
|||
pub.write_cfg()
|
||||
resp = app.get('/backoffice/settings/export')
|
||||
resp = resp.form.submit('submit')
|
||||
assert resp.location.startswith('http://example.net/backoffice/settings/export?job=')
|
||||
job_id = urlparse.parse_qs(urlparse.urlparse(resp.location).query)['job'][0]
|
||||
resp = resp.follow()
|
||||
resp = resp.click('Download Export')
|
||||
zip_content = StringIO.StringIO(resp.body)
|
||||
zipf = zipfile.ZipFile(zip_content, 'a')
|
||||
filelist = zipf.namelist()
|
||||
|
|
|
@ -41,6 +41,7 @@ from qommon import template
|
|||
from qommon.form import *
|
||||
from qommon.sms import SMS
|
||||
|
||||
from qommon.afterjobs import AfterJob
|
||||
from qommon.backoffice.menu import html_top
|
||||
from qommon.admin.menu import error_page
|
||||
from qommon.admin.cfg import cfg_submit
|
||||
|
@ -840,6 +841,9 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
return redirect('.')
|
||||
|
||||
def export(self):
|
||||
if get_request().form.get('job') or get_request().form.get('download'):
|
||||
return self.export_pending()
|
||||
|
||||
form = Form(enctype="multipart/form-data")
|
||||
form.add(CheckboxWidget, 'formdefs', title = _('Forms'), value = True)
|
||||
form.add(CheckboxWidget, 'workflows', title = _('Workflows'), value = True)
|
||||
|
@ -861,10 +865,37 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
r += htmltext('<h2>%s</h2>') % _('Export')
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
else:
|
||||
return self.export_submit(form)
|
||||
|
||||
def export_submit(self, form):
|
||||
class Exporter(object):
|
||||
def __init__(self, dirs, settings):
|
||||
self.app_dir = get_publisher().app_dir
|
||||
self.dirs = dirs
|
||||
self.settings = settings
|
||||
|
||||
def export(self, job):
|
||||
c = StringIO()
|
||||
z = zipfile.ZipFile(c, 'w')
|
||||
for d in self.dirs:
|
||||
path = os.path.join(self.app_dir, d)
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
for f in os.listdir(path):
|
||||
if f == '.indexes':
|
||||
continue
|
||||
z.write(os.path.join(path, f), os.path.join(d, f))
|
||||
if self.settings:
|
||||
z.write(os.path.join(self.app_dir, 'config.pck'), 'config.pck')
|
||||
for f in os.listdir(self.app_dir):
|
||||
if f.startswith('idp-') and os.path.splitext(f)[-1] in ('.pem', '.xml'):
|
||||
z.write(os.path.join(self.app_dir, f), f)
|
||||
if os.path.exists(os.path.join(self.app_dir, 'config')):
|
||||
for f in os.listdir(os.path.join(self.app_dir, 'config')):
|
||||
z.write(os.path.join(self.app_dir, 'config', f), os.path.join('config', f))
|
||||
z.close()
|
||||
|
||||
job.file_content = c.getvalue()
|
||||
job.store()
|
||||
|
||||
dirs = []
|
||||
for w in ('formdefs', 'workflows', 'roles', 'categories',
|
||||
'datasources', 'wscalls'):
|
||||
|
@ -875,32 +906,48 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
if not dirs and not form.get_widget('settings').parse():
|
||||
return redirect('.')
|
||||
|
||||
c = StringIO()
|
||||
z = zipfile.ZipFile(c, 'w')
|
||||
app_dir = get_publisher().app_dir
|
||||
for d in dirs:
|
||||
path = os.path.join(app_dir, d)
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
for f in os.listdir(path):
|
||||
if f == '.indexes':
|
||||
continue
|
||||
z.write(os.path.join(path, f), os.path.join(d, f))
|
||||
if form.get_widget('settings').parse():
|
||||
z.write(os.path.join(app_dir, 'config.pck'), 'config.pck')
|
||||
for f in os.listdir(app_dir):
|
||||
if f.startswith('idp-') and os.path.splitext(f)[-1] in ('.pem', '.xml'):
|
||||
z.write(os.path.join(app_dir, f), f)
|
||||
if os.path.exists(os.path.join(app_dir, 'config')):
|
||||
for f in os.listdir(os.path.join(app_dir, 'config')):
|
||||
z.write(os.path.join(app_dir, 'config', f), os.path.join('config', f))
|
||||
exporter = Exporter(dirs, settings=form.get_widget('settings').parse())
|
||||
|
||||
z.close()
|
||||
job = get_response().add_after_job(
|
||||
N_('Exporting site settings'),
|
||||
exporter.export)
|
||||
job.store()
|
||||
return redirect('export?job=%s' % job.id)
|
||||
|
||||
response = get_response()
|
||||
response.set_content_type('application/x-wcs')
|
||||
response.set_header('content-disposition', 'attachment; filename=export.wcs')
|
||||
return c.getvalue()
|
||||
def export_pending(self):
|
||||
job_id = get_request().form.get('job') or get_request().form.get('download')
|
||||
try:
|
||||
job = AfterJob.get(job_id)
|
||||
except KeyError:
|
||||
return redirect('.')
|
||||
|
||||
if get_request().form.get('download'):
|
||||
response = get_response()
|
||||
response.set_content_type('application/x-wcs')
|
||||
response.set_header('content-disposition', 'attachment; filename=export.wcs')
|
||||
return job.file_content
|
||||
|
||||
html_top('settings', title=_('Exporting'))
|
||||
r = TemplateIO(html=True)
|
||||
get_response().add_javascript(['jquery.js', 'afterjob.js'])
|
||||
r += htmltext('<h2>%s</h2>') % _('Export')
|
||||
r += htmltext('<div class="section"><dl class="job-status">')
|
||||
r += htmltext('<dt>')
|
||||
r += _(job.label)
|
||||
r += htmltext('</dt>')
|
||||
r += htmltext('<dd>')
|
||||
r += htmltext('<span class="afterjob" id="%s">') % job.id
|
||||
r += _(job.status)
|
||||
r += htmltext('</span>')
|
||||
r += htmltext('</dd>')
|
||||
r += htmltext('</dl>')
|
||||
|
||||
r += htmltext('<div class="done">')
|
||||
r += htmltext('<a download="export.wcs" href="export?download=%s">%s</a>') % (
|
||||
job.id, _('Download Export'))
|
||||
r += htmltext('</div>')
|
||||
r += htmltext('</div>')
|
||||
return r.getvalue()
|
||||
|
||||
def p_import(self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
|
|
Loading…
Reference in New Issue