0001-admin-display-configuration-and-preview-on-data-sour.patch
tests/test_admin_pages.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 | ||
1 | 3 |
import datetime |
4 |
import json |
|
2 | 5 |
import os |
3 | 6 |
import re |
4 | 7 |
import shutil |
... | ... | |
2655 | 2658 |
resp = resp.click('New Data Source') |
2656 | 2659 |
resp.forms[0]['name'] = 'a new data source' |
2657 | 2660 |
resp.forms[0]['description'] = 'description of the data source' |
2658 |
resp.forms[0]['data_source$type'] = 'Formula (Python)'
|
|
2661 |
resp.forms[0]['data_source$type'] = 'Python Expression'
|
|
2659 | 2662 |
resp = resp.forms[0].submit('data_source$apply') |
2660 | 2663 |
resp.forms[0]['data_source$value'] = repr( |
2661 | 2664 |
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) |
... | ... | |
2676 | 2679 |
resp = resp.click('New Data Source') |
2677 | 2680 |
resp.forms[0]['name'] = 'an other data source' |
2678 | 2681 |
resp.forms[0]['description'] = 'description of the data source' |
2679 |
resp.forms[0]['data_source$type'] = 'Formula (Python)'
|
|
2682 |
resp.forms[0]['data_source$type'] = 'Python Expression'
|
|
2680 | 2683 |
resp = resp.forms[0].submit('data_source$apply') |
2681 | 2684 |
resp.forms[0]['data_source$value'] = repr( |
2682 | 2685 |
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]) |
... | ... | |
2684 | 2687 | |
2685 | 2688 |
assert NamedDataSource.count() == 2 |
2686 | 2689 | |
2690 |
def test_data_sources_view(pub): |
|
2691 |
create_superuser(pub) |
|
2692 |
NamedDataSource.wipe() |
|
2693 | ||
2694 |
data_source = NamedDataSource(name='foobar') |
|
2695 |
app = login(get_app(pub)) |
|
2696 | ||
2697 |
data_source.data_source = {'type': 'formula', 'value': '[]'} |
|
2698 |
data_source.store() |
|
2699 |
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id) |
|
2700 |
assert 'Type of source: Python Expression' in resp.body |
|
2701 |
assert 'Python Expression' in resp.body |
|
2702 |
assert not 'Preview' in resp.body |
|
2703 | ||
2704 |
data_source.data_source = {'type': 'formula', 'value': '["aaa", "bbb"]'} |
|
2705 |
data_source.store() |
|
2706 |
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id) |
|
2707 |
assert 'Preview' in resp.body |
|
2708 |
assert resp.body.count('aaa') == 3 # expression + id + text |
|
2709 | ||
2710 |
# check unicode |
|
2711 |
data_source.data_source = {'type': 'formula', |
|
2712 |
'value': repr([('Y', 'Domicilié'), ('N', u'Pas domicilié')])} |
|
2713 |
data_source.store() |
|
2714 |
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id) |
|
2715 |
assert 'Preview' in resp.body |
|
2716 |
assert 'error: not a string' in resp.body |
|
2717 | ||
2718 |
# check json |
|
2719 |
json_file_path = os.path.join(pub.app_dir, 'test.json') |
|
2720 |
json_file = open(json_file_path, 'w') |
|
2721 |
json.dump({'data': [{'id': '1', 'text': 'foo'}, {'id': '2', 'text': 'bar'}]}, json_file) |
|
2722 |
json_file.close() |
|
2723 | ||
2724 |
data_source.data_source = {'type': 'json', 'value': 'file://%s' % json_file_path} |
|
2725 |
data_source.store() |
|
2726 |
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id) |
|
2727 |
assert 'Preview' in resp.body |
|
2728 |
assert 'foo' in resp.body |
|
2729 | ||
2687 | 2730 |
def test_data_sources_edit(pub): |
2688 | 2731 |
create_superuser(pub) |
2689 | 2732 |
NamedDataSource.wipe() |
... | ... | |
2698 | 2741 |
assert resp.forms[0]['name'].value == 'foobar' |
2699 | 2742 |
resp.forms[0]['description'] = 'data source description' |
2700 | 2743 |
resp = resp.forms[0].submit('submit') |
2701 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/' |
|
2744 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
2702 | 2745 |
resp = resp.follow() |
2703 | 2746 |
resp = resp.click('foobar') |
2704 | 2747 | |
... | ... | |
2723 | 2766 |
assert 'This name is already used' in resp.body |
2724 | 2767 | |
2725 | 2768 |
resp = resp.forms[0].submit('cancel') |
2726 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/' |
|
2769 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
2727 | 2770 | |
2728 | 2771 |
def test_data_sources_delete(pub): |
2729 | 2772 |
create_superuser(pub) |
... | ... | |
2763 | 2806 |
assert resp.forms[0]['name'].value == 'foobar' |
2764 | 2807 |
resp.forms[0]['slug'] = 'foo_bar' |
2765 | 2808 |
resp = resp.forms[0].submit('submit') |
2766 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/' |
|
2809 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
2767 | 2810 |
assert NamedDataSource.get(1).slug == 'foo_bar' |
2768 | 2811 | |
2769 | 2812 |
data_source = NamedDataSource(name='barfoo') |
... | ... | |
2779 | 2822 | |
2780 | 2823 |
resp.forms[0]['slug'] = 'foobar' |
2781 | 2824 |
resp = resp.forms[0].submit('submit') |
2782 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/' |
|
2825 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
2783 | 2826 | |
2784 | 2827 |
def test_settings_permissions(pub): |
2785 | 2828 |
create_superuser(pub) |
wcs/admin/data_sources.py | ||
---|---|---|
18 | 18 |
from quixote.directory import Directory |
19 | 19 |
from quixote.html import TemplateIO, htmltext |
20 | 20 | |
21 |
from wcs.data_sources import NamedDataSource, DataSourceSelectionWidget |
|
22 | 21 |
from qommon.form import * |
23 | 22 |
from qommon.backoffice.menu import html_top |
23 |
from wcs.data_sources import (NamedDataSource, DataSourceSelectionWidget, |
|
24 |
get_structured_items) |
|
24 | 25 | |
25 | 26 |
class NamedDataSourceUI(object): |
26 | 27 |
def __init__(self, datasource): |
... | ... | |
99 | 100 |
r += self.datasource.description |
100 | 101 |
r += htmltext('</div>') |
101 | 102 | |
103 |
data_source_labels = { |
|
104 |
'json': _('JSON'), |
|
105 |
'jsonp': _('JSONP'), |
|
106 |
'formula': _('Python Expression'), |
|
107 |
} |
|
108 | ||
109 |
if self.datasource.data_source and self.datasource.data_source.get('type') in data_source_labels: |
|
110 |
data_source_type = self.datasource.data_source.get('type') |
|
111 |
r += htmltext('<h3>%s</h3>') % _('Configuration') |
|
112 |
r += htmltext('<ul>') |
|
113 |
r += htmltext('<li>%s</li>') % _( |
|
114 |
'Type of source: %s') % data_source_labels.get(data_source_type) |
|
115 |
if data_source_type in ('json', 'jsonp'): |
|
116 |
r += htmltext('<li>%s<a href="%s">%s</a></li>') % ( |
|
117 |
_('URL: '), |
|
118 |
self.datasource.data_source.get('value'), |
|
119 |
self.datasource.data_source.get('value')) |
|
120 |
elif data_source_type == 'formula': |
|
121 |
r += htmltext('<li>%s<tt>%s</tt></li>') % ( |
|
122 |
_('Python Expression: '), |
|
123 |
self.datasource.data_source.get('value')) |
|
124 |
r += htmltext('</ul>') |
|
125 | ||
126 |
if data_source_type in ('json', 'formula'): |
|
127 |
items = get_structured_items(self.datasource.data_source) |
|
128 |
if items: |
|
129 |
r += htmltext('<h3>%s</h3>') % _('Preview') |
|
130 |
r += htmltext('<div class="bo-block data-source-preview"><ul>') |
|
131 |
r += htmltext('<ul>') |
|
132 |
for item in items[:10]: |
|
133 |
if not isinstance(item.get('text'), str): |
|
134 |
r += htmltext('<li><tt>%s</tt>: <i>%s (%r)</i></li>') % ( |
|
135 |
item.get('id'), |
|
136 |
_('error: not a string'), |
|
137 |
item.get('text')) |
|
138 |
else: |
|
139 |
r += htmltext('<li><tt>%s</tt>: %s</li>') % ( |
|
140 |
item.get('id'), item.get('text')) |
|
141 |
r += htmltext('</ul></div>') |
|
142 |
else: |
|
143 |
# the data source field is required so this should never happen |
|
144 |
r += htmltext('<p class="infonotice">%s</p>') % _('Not configured') |
|
145 | ||
102 | 146 |
return r.getvalue() |
103 | 147 | |
104 | 148 |
def get_sidebar(self): |
... | ... | |
112 | 156 |
def edit(self): |
113 | 157 |
form = self.datasource_ui.get_form() |
114 | 158 |
if form.get_submit() == 'cancel': |
115 |
return redirect('..')
|
|
159 |
return redirect('.') |
|
116 | 160 | |
117 | 161 |
if form.get_submit() == 'submit' and not form.has_errors(): |
118 | 162 |
try: |
... | ... | |
120 | 164 |
except ValueError: |
121 | 165 |
pass |
122 | 166 |
else: |
123 |
return redirect('..')
|
|
167 |
return redirect('.') |
|
124 | 168 | |
125 | 169 |
get_response().breadcrumb.append( ('edit', _('Edit')) ) |
126 | 170 |
html_top('datasources', title = _('Edit Data Source')) |
wcs/data_sources.py | ||
---|---|---|
46 | 46 |
value = {} |
47 | 47 | |
48 | 48 |
options = [('none', _('None')), |
49 |
('formula', _('Formula (Python)')),
|
|
49 |
('formula', _('Python Expression')),
|
|
50 | 50 |
('json', _('JSON URL'))] |
51 | 51 |
if allow_jsonp: |
52 | 52 |
options.append(('jsonp', _('JSONP URL'))) |
wcs/qommon/static/css/dc2/admin.css | ||
---|---|---|
1318 | 1318 |
ul#evolutions li div.msg li::after { |
1319 | 1319 |
content: none; |
1320 | 1320 |
} |
1321 | ||
1322 |
div.bo-block.data-source-preview ul { |
|
1323 |
margin: 0; |
|
1324 |
padding: 0; |
|
1325 |
padding-left: 1em; |
|
1326 |
} |
|
1327 | ||
1328 |
div.bo-block.data-source-preview ul li { |
|
1329 |
margin: 1ex 0; |
|
1330 |
} |
|
1331 | ||
1332 |
div.bo-block.data-source-preview tt { |
|
1333 |
padding-right: 1ex; |
|
1334 |
} |
|
1321 |
- |