Projet

Général

Profil

0001-admin-display-configuration-and-preview-on-data-sour.patch

Frédéric Péters, 19 avril 2016 11:03

Télécharger (9,93 ko)

Voir les différences:

Subject: [PATCH] admin: display configuration and preview on data source page
 (#10705)

 tests/test_admin_pages.py           | 55 +++++++++++++++++++++++++++++++++----
 wcs/admin/data_sources.py           | 50 +++++++++++++++++++++++++++++++--
 wcs/data_sources.py                 |  2 +-
 wcs/qommon/static/css/dc2/admin.css | 14 ++++++++++
 4 files changed, 111 insertions(+), 10 deletions(-)
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
-