Projet

Général

Profil

0001-review-backoffice-homepage-and-announce-management-1.patch

Serghei Mihai (congés, retour 15/05), 13 septembre 2016 22:20

Télécharger (18,1 ko)

Voir les différences:

Subject: [PATCH] review backoffice homepage and announce management (#12908)

 corbo/manage_urls.py                               |   7 +-
 corbo/models.py                                    |   6 +
 corbo/static/css/corbo.css                         | 142 ++-------------------
 corbo/templates/corbo/announce_confirm_delete.html |   2 +
 corbo/templates/corbo/announce_form.html           |  14 +-
 corbo/templates/corbo/category_confirm_delete.html |   2 +
 corbo/templates/corbo/category_detail.html         |  41 ++++++
 corbo/templates/corbo/manage.html                  | 122 +++++-------------
 corbo/views.py                                     |  71 +++++++----
 9 files changed, 157 insertions(+), 250 deletions(-)
 create mode 100644 corbo/templates/corbo/category_detail.html
corbo/manage_urls.py
1 1
from django.conf.urls import patterns, include, url
2 2

  
3 3
from .views import add_announce, edit_announce, delete_announce, \
4
    add_category, edit_category, delete_category, manage, menu_json
4
    add_category, edit_category, view_category, delete_category, manage, \
5
    add_announce_for_category, menu_json
5 6

  
6 7
urlpatterns = patterns('',
7 8
            url(r'^$', manage, name='manage'),
......
10 11
                name='edit_announce'),
11 12
            url(r'^announce/delete/(?P<pk>\d+)$', delete_announce,
12 13
                name='delete_announce'),
14
            url(r'^category/(?P<pk>\d+)/$', view_category,
15
                name='view_category'),
16
            url(r'^category/(?P<pk>\d+)/announce/$', add_announce_for_category,
17
                name='add_announce_for_category'),
13 18
            url(r'^category/add$', add_category,
14 19
                name='add_category'),
15 20
            url(r'^category/edit/(?P<pk>\d+)$', edit_category,
corbo/models.py
31 31
    def __unicode__(self):
32 32
        return self.name
33 33

  
34
    def get_announces_count(self):
35
        return self.announce_set.all().count()
36

  
37
    def get_subscriptions_count(self):
38
        return self.subscription_set.all().count()
39

  
34 40

  
35 41
class Announce(models.Model):
36 42
    category  = models.ForeignKey('Category', verbose_name=_('category'))
corbo/static/css/corbo.css
2 2
    font-family: FontAwesome;
3 3
}
4 4

  
5

  
6 5
body {
7 6
    margin: 0;
8 7
}
9 8

  
10 9
a:link, a:visited, a:hover {
11 10
    text-decoration: none;
12
    color: #000;
13 11
}
14 12

  
15 13
header h1 {
......
29 27
    padding: 0 10px;
30 28
}
31 29

  
32
ul.announces {
33
    margin: 0;
34
    padding: 0;
35
}
36

  
37
ul.announces li, ul.auth li, #management ul li {
30
ul.auth li {
38 31
    list-style-type: none;
39 32
    padding: .1em .5em;
40 33
}
41 34

  
42
li.bright {
43
    background: #fff;
44
}
45

  
46
li.bluesky {
47
    background: #d3d8e8 !important;
48
}
49

  
50
div.pub_time {
51
    float: right;
52
    font: bold Arial .8em;
53
}
54

  
55 35
div.clear {
56 36
    clear: both;
57 37
}
58 38

  
59
ul.pagination {
60
    font-size: .8em;
61
    margin: 0;
62
    padding: 0;
63
}
64

  
65
#management ul.pagination li {
66
    display: inline;
67
    margin: 0 2px;
68
}
69

  
70
ul.pagination li.current {
71
    border: 0;
72
}
73

  
74
ul.pagination a {
75
    color: #000;
76
}
77

  
78
ul.pagination li.next a:before {
79
    content: '\f105';
80
}
81

  
82
ul.pagination li.prev a:before {
83
    content: '\f104';
84
}
85

  
86 39
ul.auth {
87 40
    border-radius: .2em;
88 41
    -moz-border-radius: .2em;
......
142 95
    margin-left: .4em;
143 96
}
144 97

  
145
#management {
146
    margin: 1em 0 .5em 0;
147
}
148

  
149
#management ul {
150
    margin: 1em 0 0 0;
151
    padding: 0;
152
}
153 98

  
154 99
#management ul li {
155 100
    padding: 5px;
156
    border: 1px solid #aaa;
157
    background: #eee;
158
    margin:2px 0;
159
    border-radius: .3em;
160
    position: relative;
161
}
162

  
163
#management h4 {
164
    margin: .4em 0;
165
}
166

  
167
.title {
168
    font-size: .9em;
169
    font-weight: bold;
170 101
}
171 102

  
172
.preview {
173
    padding-left: 10px;
174
    font-size: .8em;
175
    color: #777;
103
ul.objects-list.single-links li .actions a {
104
    color: #999;
105
    display: inline;
106
    padding: 0;
176 107
}
177 108

  
178
.actions {
179
    position: absolute;
180
    top: 2px;
181
    right: 5px;
109
.actions a:hover {
110
    color: #333;
182 111
}
183 112

  
184 113
.status {
......
190 119
    width: 20px;
191 120
}
192 121

  
193
.edit:before {
194
    content: '\f044';
195
}
196

  
197
.delete:before {
198
    content: '\f1f8';
199
}
200

  
201 122
.status .icon {
202 123
    color: #888;
124
    font-size: 0.9em;
203 125
}
204 126

  
205 127
.status .published:before {
......
220 142
}
221 143

  
222 144
#management .datetime {
223
    width: 15%;
224
    float: right;
225
    margin-right: 35px;
145
    position: absolute;
146
    top: 3px;
147
    right: 0;
148
    width: 25%;
226 149
}
227 150

  
228 151
.empty {
......
232 155
    margin: 0 auto;
233 156
}
234 157

  
235
.categories {
236
    float: right;
237
}
238

  
239
.categories select {
240
    border: 1px solid #aaa;
241
    display: inline;
242
}
243

  
244
.categories a, #management > span a {
245
    color: #000;
246
    padding: 1px 3px;
247
    margin: 0;
248
    font-weight: bold;
249
    font-size: .75em;
250
}
251

  
252
a.add:before {
253
    content: '\f067';
254
    padding-right:3px;
255
}
256

  
257 158
form ul li {
258 159
    list-style-type: none;
259 160
    margin: 5px 0;
260 161
}
261 162

  
262
li.datetime:after {
263
    margin-left: 5px;
264
    font-family: FontAwesome;
265
    content: '\f073';
266
    color: #555;
267
}
268

  
269 163
form ul li label {
270 164
    display: block;
271 165
}
272 166

  
273
#id_transport_channel li, #id_transport_channel label {
274
    display: inline;
275
}
276

  
277 167
.content {
278 168
    width: 50%;
279 169
    margin: auto;
......
283 173
    background: #e6db74;
284 174
    border: 1px solid #aaa;
285 175
    padding: 5px;
286
}
287

  
288
.info {
289
    background: #a6e22e;
290
    border: 1px solid #aaa;
291
    padding: 5px;
292
}
176
}
corbo/templates/corbo/announce_confirm_delete.html
1 1
{% extends "corbo/manage.html" %}
2 2
{% load i18n %}
3
{% block appbar %}
4
{% endblock %}
3 5
{% block content %}
4 6
<form method="post">
5 7
  <p>
corbo/templates/corbo/announce_form.html
1 1
{% extends "corbo/manage.html" %}
2 2
{% load i18n %}
3 3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
{% if category %}
7
<a href='{% url "view_category" pk=category.pk %}'>{{ category }}</a>
8
{% endif %}
9
{% endblock %}
10

  
4 11
{% block appbar %}
5 12
{% if object %}
6
  <h2>{% trans "Modify Announce" %}</h2>
13
<h2>{% trans "Edit Announce" %}</h2>
14
<a href='{% url "delete_announce" pk=object.pk %}' rel='popup'>{% trans 'Delete' %}</a>
7 15
{% else %}
8
  <h2>{% trans "New Announce" %}</h2>
16
<h2>{% trans "New Announce" %}</h2>
9 17
{% endif %}
18
</h2>
19

  
10 20
{% endblock %}
11 21

  
12 22
{% block content %}
corbo/templates/corbo/category_confirm_delete.html
1 1
{% extends "corbo/manage.html" %}
2 2
{% load i18n %}
3
{% block appbar %}
4
{% endblock %}
3 5
{% block content %}
4 6
<form method="post">
5 7
  {% csrf_token %}
corbo/templates/corbo/category_detail.html
1
{% extends 'corbo/manage.html' %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
<h2>{{ object.name }}</h2>
6
<a href="{% url 'delete_category' object.id %}" rel="popup">{% trans 'Delete' %}</a>
7
<a href="{% url 'edit_category' object.id %}" rel="popup">{% trans 'Rename' %}</a>
8
<a href="{% url 'add_announce_for_category' pk=object.pk %}">{% trans 'New announce' %}</a>
9
{% endblock %}
10

  
11
{% block content %}
12
<div id="management">
13
<ul class='objects-list single-links'>
14
{% for announce in announces %}
15
<li>
16
  <div class="status">
17
    {% if announce.is_published %}
18
    <span class="icon published" title="{% trans "published" %}"></span>
19
    {% endif %}
20
    {% if not announce.is_published %}
21
    {% if announce.is_expired %}
22
    <span class="icon expired" title="{% trans "expired" %}"></span>
23
    {% else %}
24
    <span class="icon unpublished" title="{% trans "not published yet" %}"></span>
25
    {% endif %}
26
    {% endif %}
27
  </div>
28
  <a href="{% url 'edit_announce' announce.id %}">{{ announce.title }}</a>
29
  <div class="datetime">
30
    {% blocktrans with mtime=announce.mtime|date:'DATETIME_FORMAT' %}
31
    Modified on {{ mtime }}
32
    {% endblocktrans %}
33
  </div>
34
</li>
35
{% empty %}
36
<div class="empty">
37
  {% trans "No announces yet." %}
38
</div>
39
{% endfor %}
40
</ul>
41
{% endblock %}
corbo/templates/corbo/manage.html
1 1
{% extends 'corbo/base.html' %}
2
{% load i18n static %}
3
{% block page-title %}
4
{{ block.super }} :: {% trans "Management" %}
5
{% endblock %}
6

  
2
{% load i18n %}
7 3

  
4
{% block appbar %}
5
<h2>{% trans "Categories" %}</h2>
6
<a href="{% url 'add_category' %}" rel='popup'>{% trans 'New category' %}</a>
7
<a href="{% url 'add_announce' %}">{% trans 'New announce' %}</a>
8
{% endblock %}
8 9

  
9 10
{% block content %}
10
<div class="categories">
11
  <span class="title">{% trans "Category:" %}</span>
12
  <select>
13
    <option value=''>{% trans "All" %}</option>
14
    {% for category in categories %}
15
    <option value='{{ category.id }}'{% if category_id == category.id %} selected{% endif %}>{{ category }}</option>
16
    {% endfor %}
17
  </select>
18
  <span>
19
    {% if category_id %}
20
    <a class="icon edit" href="{% url "edit_category" category_id %}" rel="popup" title="{% trans "edit category" %}"></a>
21
    <a class="icon delete" href="{% url "delete_category" category_id %}" rel="popup" title="{% trans "delete category" %}"></a>
22
    {% endif %}
23
    <a class="icon add" href="{% url "add_category" %}" rel="popup" title="{% trans "add category" %}"></a></span>
24
</div>
25 11
<div id="management">
26
  <h4>{% trans "Announces" %}</h4>
27
  <span><a class="icon add" href="{% url "add_announce" %}">{% trans "add announce" %}</a></span>
28
<ul>
29
{% for obj in object_list %}
30
<li class='{% cycle 'bluesky' '' %}'>
31
  <div class="status">
32
    {% if obj.is_published %}
33
    <span class="icon published" title="{% trans "published" %}"></span>
34
    {% endif %}
35
    {% if not obj.is_published %}
36
    {% if obj.is_expired %}
37
    <span class="icon expired" title="{% trans "expired" %}"></span>
38
    {% else %}
39
    <span class="icon unpublished" title="{% trans "not published yet" %}"></span>
40
    {% endif %}
41
    {% endif %}
42
  </div>
43
  <div class="preview datetime">
44
    {% blocktrans with mtime=obj.mtime|date:'DATETIME_FORMAT' %}
45
    Modified on {{ mtime }}
46
    {% endblocktrans %}
47
  </div>
48
  <div class="actions">
49
    <span><a class="icon edit" href="{% url 'edit_announce' obj.id %}"></a></span>
50
    <span><a class="icon delete" href="{% url 'delete_announce' obj.id %}" rel="popup"></a></span>
51
  </div>
52
  <div class="announce">
53
    <div class="title">{{ obj.title }}</div>
54
    <div class="preview">{{ obj.text|safe|truncatechars_html:128 }}</div>
55
  </div>
56
</li>
57
{% empty %}
58
<div class="empty">
59
  {% trans "No announces matching this category" %}
60
</div>
61
{% endfor %}
62
</ul>
63

  
64
{% if is_paginated %}
65
<ul class="pagination">
66
  {% if page_obj.has_previous %}
67
  <li class="prev">
68
    <a href="?{% if category_id %}category={{ category_id}}&{% endif %}page={{ page_obj.previous_page_number }}" class="icon"></a>
69
  </li>
70
  {% endif %}
71
  <li class="current">
72
    page {{ page_obj.number }} of {{ paginator.num_pages }}
73
  </li>
74
  {% if page_obj.has_next %}
75
  <li class="next">
76
    <a href="?{% if category_id %}category={{ category_id}}&{% endif %}page={{ page_obj.next_page_number }}" class="icon"></a>
77
  </li>
78
  {% endif %}
79
</ul>
80
{% endif %}
12
  <ul class='objects-list single-links'>
13
    {% for obj in object_list %}
14
    <li class='category'>
15
        <a href="{% url 'view_category' pk=obj.id %}">{{ obj.name }} /
16
        {% blocktrans with creation_date=obj.ctime|date:"SHORT_DATETIME_FORMAT" %}
17
        created on {{ creation_date }}
18
          {% endblocktrans %} /
19
          {% blocktrans count announces_number=obj.get_announces_count %}
20
          {{ announces_number }} announce
21
          {% plural %}
22
          {{ announces_number }} announces
23
          {% endblocktrans %} /
24
          {% blocktrans count subscriptions_number=obj.get_subscriptions_count %}
25
          {{ subscriptions_number }} subscription
26
          {% plural %}
27
          {{ subscriptions_number }} subscriptions
28
          {% endblocktrans %}
29
        </a>
30
    </li>
31
    {% empty %}
32
    <div class="empty">
33
      {% trans "No categories yet." %}
34
    </div>
35
    {% endfor %}
36
  </ul>
81 37
</div>
82
{% endblock %}
83

  
84
{% block page-end %}
85
<script type="text/javascript">
86
  $(function() {
87
    $('div.categories select').on('change', function() {
88
        var category = $(this).val();
89
        if (category)
90
            window.location.replace('{% url "manage" %}?category=' + category);
91
        else
92
            window.location.replace({% url "manage" %});
93
    })
94
})
95
</script>
96
{% endblock %}
38
  {% endblock %}
corbo/views.py
6 6
from django.core import signing
7 7
from django.core.urlresolvers import reverse
8 8
from django.views.generic import CreateView, UpdateView, DeleteView, \
9
                                 ListView, TemplateView, RedirectView
9
                                 ListView, TemplateView, RedirectView, \
10
                                 DetailView
10 11
from django.contrib.syndication.views import Feed
11 12
from django.shortcuts import resolve_url
12 13
from django.utils.encoding import force_text
......
54 55
    template_name = 'corbo/announce_form.html'
55 56

  
56 57
    def get_success_url(self):
57
        """
58
        redirect to the category page of the new created announce
59
        """
60
        return reverse('manage') + '?' + urlencode({'category': self.object.category.id})
58
        return reverse('view_category', kwargs={'pk': self.object.category.pk})
61 59

  
62 60
add_announce = AnnounceCreateView.as_view()
63 61

  
62

  
63
class AnnounceForCategoryCreateView(AnnounceCreateView):
64

  
65
    def get_initial(self):
66
        initial = super(AnnounceForCategoryCreateView, self).get_initial()
67
        initial['category'] = models.Category.objects.get(pk=self.kwargs['pk'])
68
        return initial
69

  
70
    def get_context_data(self, **kwargs):
71
        context = super(AnnounceForCategoryCreateView, self).get_context_data(**kwargs)
72
        context['category'] = kwargs['form'].initial['category']
73
        return context
74

  
75
add_announce_for_category = AnnounceForCategoryCreateView.as_view()
76

  
77

  
64 78
class AnnounceEditView(UpdateView):
65 79
    model = models.Announce
66 80
    form_class = AnnounceForm
67 81

  
82
    def get_context_data(self, **kwargs):
83
        context = super(AnnounceEditView, self).get_context_data(**kwargs)
84
        category_id = kwargs['form'].initial['category']
85
        context['category'] = models.Category.objects.get(pk=category_id)
86
        return context
87

  
68 88
    def get_success_url(self):
69
        return reverse('manage') + '?' + urlencode({'category': self.object.category.id})
89
        return reverse('view_category', kwargs={'pk': self.object.category.pk})
70 90

  
71 91
edit_announce = AnnounceEditView.as_view()
72 92

  
......
74 94
    model = models.Announce
75 95

  
76 96
    def get_success_url(self):
77
        return self.request.META['HTTP_REFERER'] or \
78
            reverse('manage') + '?' + urlencode({'category': self.object.category.id})
97
        return reverse('view_category', kwargs={'pk': self.object.category.pk})
79 98

  
80 99
delete_announce = AnnounceDeleteView.as_view()
81 100

  
......
92 111

  
93 112
add_category = CategoryCreateView.as_view()
94 113

  
114

  
95 115
class CategoryEditView(UpdateView):
96 116
    form_class = CategoryForm
97 117
    model = models.Category
98 118

  
99 119
    def get_success_url(self):
100
        return self.request.META['HTTP_REFERER'] or \
101
            reverse('manage') + '?' + urlencode({'category': self.object.id})
120
        return reverse('view_category', kwargs={'pk': self.object.pk})
102 121

  
103 122
edit_category = CategoryEditView.as_view()
104 123

  
124

  
125
class CategoryView(DetailView):
126
    model = models.Category
127

  
128
    def get_context_data(self, **kwargs):
129
        context = super(CategoryView, self).get_context_data(**kwargs)
130
        context['announces'] = self.object.announce_set.all()
131
        return context
132

  
133
view_category = CategoryView.as_view()
134

  
135

  
105 136
class CategoryDeleteView(DeleteView):
106 137
    model = models.Category
107 138

  
......
135 166

  
136 167

  
137 168
class ManageView(ListView):
138
    paginate_by = settings.ANNOUNCES_PER_PAGE
139 169
    template_name = 'corbo/manage.html'
140
    model = models.Announce
141

  
142
    def get_queryset(self):
143
        queryset = super(ManageView, self).get_queryset()
144
        if self.request.GET.get('category'):
145
            queryset = queryset.filter(category__id=self.request.GET['category'])
146
        return queryset
147

  
148
    def get_context_data(self, **kwargs):
149
        context = super(ManageView, self).get_context_data(**kwargs)
150
        context['categories'] = models.Category.objects.all().order_by('-ctime')
151
        if self.request.GET.get('category'):
152
            try:
153
                context['category_id'] = int(self.request.GET['category'])
154
            except:
155
                pass
156
        return context
170
    model = models.Category
157 171

  
158 172
manage = ManageView.as_view()
159 173

  
174

  
160 175
class Atom1Feed(DjangoAtom1Feed):
161 176
    def root_attributes(self):
162 177
        attrs = super(Atom1Feed, self).root_attributes()
163
-