Projet

Général

Profil

0003-add-a-gallery-cell-type-7344.patch

Frédéric Péters, 25 mai 2015 13:06

Télécharger (19 ko)

Voir les différences:

Subject: [PATCH 3/3] add a gallery cell type (#7344)

 combo/apps/gallery/__init__.py                     | 26 +++++++++
 combo/apps/gallery/forms.py                        | 31 ++++++++++
 combo/apps/gallery/migrations/0001_initial.py      | 44 ++++++++++++++
 combo/apps/gallery/migrations/0002_image_title.py  | 20 +++++++
 combo/apps/gallery/migrations/__init__.py          |  0
 combo/apps/gallery/models.py                       | 44 ++++++++++++++
 combo/apps/gallery/static/js/combo.gallery.js      | 29 +++++++++
 combo/apps/gallery/templates/combo/gallery.html    | 29 +++++++++
 .../templates/combo/gallery_image_form.html        | 26 +++++++++
 .../gallery/templates/combo/gallery_manager.html   | 29 +++++++++
 .../combo/manager/gallery/gallerycell.html         |  1 +
 combo/apps/gallery/urls.py                         | 30 ++++++++++
 combo/apps/gallery/views.py                        | 68 ++++++++++++++++++++++
 combo/manager/static/css/combo.manager.css         | 32 +++++++++-
 14 files changed, 408 insertions(+), 1 deletion(-)
 create mode 100644 combo/apps/gallery/__init__.py
 create mode 100644 combo/apps/gallery/forms.py
 create mode 100644 combo/apps/gallery/migrations/0001_initial.py
 create mode 100644 combo/apps/gallery/migrations/0002_image_title.py
 create mode 100644 combo/apps/gallery/migrations/__init__.py
 create mode 100644 combo/apps/gallery/models.py
 create mode 100644 combo/apps/gallery/static/js/combo.gallery.js
 create mode 100644 combo/apps/gallery/templates/combo/gallery.html
 create mode 100644 combo/apps/gallery/templates/combo/gallery_image_form.html
 create mode 100644 combo/apps/gallery/templates/combo/gallery_manager.html
 create mode 100644 combo/apps/gallery/templates/combo/manager/gallery/gallerycell.html
 create mode 100644 combo/apps/gallery/urls.py
 create mode 100644 combo/apps/gallery/views.py
combo/apps/gallery/__init__.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import django.apps
18

  
19
class AppConfig(django.apps.AppConfig):
20
    name = 'combo.apps.gallery'
21

  
22
    def get_after_manager_urls(self):
23
        from . import urls
24
        return urls.manager_urlpatterns
25

  
26
default_app_config = 'combo.apps.gallery.AppConfig'
combo/apps/gallery/forms.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django import forms
18
from django.utils.translation import ugettext_lazy as _
19

  
20
from .models import Image
21

  
22
class ImageAddForm(forms.ModelForm):
23
    class Meta:
24
        model = Image
25
        fields = ('image', 'title',)
26

  
27

  
28
class ImageEditForm(forms.ModelForm):
29
    class Meta:
30
        model = Image
31
        fields = ('title',)
combo/apps/gallery/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import models, migrations
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('auth', '0001_initial'),
11
        ('data', '0005_auto_20150226_0903'),
12
    ]
13

  
14
    operations = [
15
        migrations.CreateModel(
16
            name='GalleryCell',
17
            fields=[
18
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
19
                ('placeholder', models.CharField(max_length=20)),
20
                ('order', models.PositiveIntegerField()),
21
                ('slug', models.SlugField(verbose_name='Slug', blank=True)),
22
                ('public', models.BooleanField(default=True, verbose_name='Public')),
23
                ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
24
                ('page', models.ForeignKey(to='data.Page')),
25
            ],
26
            options={
27
                'verbose_name': 'Gallery',
28
            },
29
            bases=(models.Model,),
30
        ),
31
        migrations.CreateModel(
32
            name='Image',
33
            fields=[
34
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
35
                ('image', models.ImageField(upload_to=b'uploads/gallery/%Y/%m/', verbose_name='Image')),
36
                ('order', models.PositiveIntegerField()),
37
                ('gallery', models.ForeignKey(verbose_name='Gallery', to='gallery.GalleryCell')),
38
            ],
39
            options={
40
                'ordering': ['order'],
41
            },
42
            bases=(models.Model,),
43
        ),
44
    ]
combo/apps/gallery/migrations/0002_image_title.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import models, migrations
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('gallery', '0001_initial'),
11
    ]
12

  
13
    operations = [
14
        migrations.AddField(
15
            model_name='image',
16
            name='title',
17
            field=models.CharField(max_length=50, verbose_name='Title', blank=True),
18
            preserve_default=True,
19
        ),
20
    ]
combo/apps/gallery/models.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django import template
18
from django.db import models
19
from django.forms import models as model_forms
20
from django.utils.translation import ugettext_lazy as _
21

  
22
from combo.data.models import CellBase
23
from combo.data.library import register_cell_class
24

  
25
@register_cell_class
26
class GalleryCell(CellBase):
27
    manager_form_template = 'combo/gallery_manager.html'
28

  
29
    class Meta:
30
        verbose_name = _('Gallery')
31

  
32
    def render(self, context):
33
        gallery_template = template.loader.get_template('combo/gallery.html')
34
        return gallery_template.render(context)
35

  
36
class Image(models.Model):
37
    gallery = models.ForeignKey(GalleryCell, verbose_name=_('Gallery'))
38
    image = models.ImageField(_('Image'),
39
            upload_to='uploads/gallery/%Y/%m/')
40
    order = models.PositiveIntegerField()
41
    title = models.CharField(_('Title'), max_length=50, blank=True)
42

  
43
    class Meta:
44
        ordering = ['order']
combo/apps/gallery/static/js/combo.gallery.js
1
function gallery(element) {
2
  var element_id = '#' + $(element).attr('id');
3
  $(element).sortable({
4
    items: '> li',
5
    containment: 'parent',
6
    placeholder: 'empty-image',
7
    update: function(event, ui) {
8
      var new_order = $(element).find('> li').map(function() { return $(this).data('object-id'); }).get().join();
9
      $.ajax({
10
        url: $(element).data('order-url'),
11
        data: {'new-order': new_order},
12
        success: function(data, status) {
13
          $(element).replaceWith($(data).find(element_id));
14
          gallery($(element_id));
15
        }
16
      });
17
    }
18
  });
19
  $('.image-delete').on('click', function() {
20
    $.ajax({
21
      url: $(this).attr('href'),
22
      success: function(data, status) {
23
        $(element).replaceWith($(data).find(element_id));
24
        gallery($(element_id));
25
      }
26
    });
27
    return false;
28
  });
29
};
combo/apps/gallery/templates/combo/gallery.html
1
{% load thumbnail %}
2
<div class="gallery" id="gallery-{{cell.id}}">
3
{% for image in cell.image_set.all %}
4
  {% if forloop.first %}
5
{% thumbnail image.image "640x480" crop="50% 25%" as im %}
6
<div class="first">
7
<img src="{{ im.url }}"/>
8
<span>{% if image.title %}{{ image.title }}{% endif %}</span>
9
</div>
10
<div>
11
{% endthumbnail %}
12
  {% endif %}
13
{% thumbnail image.image "60x60" crop="50% 25%" as im %}
14
{% thumbnail image.image "640x480" crop="50% 25%" as im_large %}
15
<span data-image-large="{{ im_large.url }}"><img src="{{ im.url }}"
16
        {% if image.title %} title="{{image.title}}" {% endif %}/></span>
17
{% endthumbnail %}
18
{% endthumbnail %}
19
{% endfor %}
20
</div>
21
</div>
22
<script type="text/javascript">
23
$(function() {
24
  var $gallery = $('#gallery-{{cell.id}}');
25
  $gallery.find('span').on('click', function() {
26
    $gallery.find('div.first img').attr('src', $(this).data('image-large'));
27
  });
28
});
29
</script>
combo/apps/gallery/templates/combo/gallery_image_form.html
1
{% extends "combo/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
{% if object.id %}
6
<h2>{% trans "Edit Image" %}</h2>
7
{% else %}
8
<h2>{% trans "New Image" %}</h2>
9
{% endif %}
10
{% endblock %}
11

  
12
{% block content %}
13

  
14
<form method="post" enctype="multipart/form-data">
15
  {% csrf_token %}
16
  {{ form.as_p }}
17
  <div class="buttons">
18
    <button>{% trans "Save" %}</button>
19
    {% if object.id %}
20
    <a class="cancel" href="{{ object.get_absolute_url }}">{% trans 'Cancel' %}</a>
21
    {% else %}
22
    <a class="cancel" href="{% url 'combo-manager-homepage' %}">{% trans 'Cancel' %}</a>
23
    {% endif %}
24
  </div>
25
</form>
26
{% endblock %}
combo/apps/gallery/templates/combo/gallery_manager.html
1
{% extends 'combo/cell_form.html' %}
2
{% load static thumbnail i18n %}
3

  
4
{% block cell-form %}
5
<ul class="gallery" id="gallery-{{cell.id}}" data-order-url="{% url 'combo-gallery-image-order' gallery_pk=cell.id %}">
6
{% for image in cell.image_set.all %}
7
<li data-object-id="{{image.id}}">
8
{% thumbnail image.image "120x120" crop="50% 25%" as im %}
9
  <img height="120" src="{{ im.url }}"/>
10
{% endthumbnail %}
11
  <span class="image-actions">
12
  <a rel="popup" class="image-edit icon-edit" href="{% url 'combo-gallery-image-edit' gallery_pk=cell.id pk=image.id %}"></a>
13
  <a class="image-delete icon-remove-sign" href="{% url 'combo-gallery-image-delete' gallery_pk=cell.id pk=image.id %}"></a>
14
  </span>
15
</li>
16
{% endfor %}
17
</ul>
18

  
19
<script src="{% static "js/combo.gallery.js" %}"></script>
20
<script>gallery($('#gallery-{{cell.id}}'));</script>
21

  
22
{% endblock %}
23

  
24

  
25
{% block cell-buttons %}
26
<a class="image-add" rel="popup" href="{% url 'combo-gallery-image-add' gallery_pk=cell.id %}">{% trans 'New Image' %}</a>
27
|
28
{{ block.super }}
29
{% endblock %}
combo/apps/gallery/templates/combo/manager/gallery/gallerycell.html
1
HLLOW
combo/apps/gallery/urls.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.conf.urls import patterns, url
18

  
19
from . import views
20

  
21
manager_urlpatterns = patterns('',
22
        url('^gallery/(?P<gallery_pk>\w+)/images/add/$', views.image_add,
23
            name='combo-gallery-image-add'),
24
        url('^gallery/(?P<gallery_pk>\w+)/order$', views.image_order,
25
            name='combo-gallery-image-order'),
26
        url('^gallery/(?P<gallery_pk>\w+)/images/(?P<pk>\w+)/edit$', views.image_edit,
27
            name='combo-gallery-image-edit'),
28
        url('^gallery/(?P<gallery_pk>\w+)/images/(?P<pk>\w+)/delete$', views.image_delete,
29
            name='combo-gallery-image-delete'),
30
)
combo/apps/gallery/views.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.core.urlresolvers import reverse, reverse_lazy
18
from django.shortcuts import redirect
19
from django.views.generic import (TemplateView, RedirectView, DetailView,
20
        CreateView, UpdateView, ListView, DeleteView, FormView)
21

  
22
from .models import Image, GalleryCell
23
from .forms import ImageAddForm, ImageEditForm
24

  
25
class ImageAddView(CreateView):
26
    model = Image
27
    template_name = 'combo/gallery_image_form.html'
28
    form_class = ImageAddForm
29

  
30
    def form_valid(self, form):
31
        form.instance.gallery_id = self.kwargs.get('gallery_pk')
32
        other_images = form.instance.gallery.image_set.all()
33
        if other_images:
34
            form.instance.order = max([x.order for x in other_images]) + 1
35
        else:
36
            form.instance.order = 0
37
        return super(ImageAddView, self).form_valid(form)
38

  
39
    def get_success_url(self):
40
        return reverse('combo-manager-page-view', kwargs={'pk': self.object.gallery.page.id})
41

  
42
image_add = ImageAddView.as_view()
43

  
44

  
45
class ImageEditView(UpdateView):
46
    model = Image
47
    template_name = 'combo/gallery_image_form.html'
48
    form_class = ImageEditForm
49

  
50
    def get_success_url(self):
51
        return reverse('combo-manager-page-view', kwargs={'pk': self.object.gallery.page.id})
52

  
53
image_edit = ImageEditView.as_view()
54

  
55

  
56
def image_delete(request, gallery_pk, pk):
57
    gallery = GalleryCell.objects.get(id=gallery_pk)
58
    Image.objects.get(id=pk).delete()
59
    return redirect(reverse('combo-manager-page-view', kwargs={'pk': gallery.page.id}))
60

  
61

  
62
def image_order(request, gallery_pk):
63
    gallery = GalleryCell.objects.get(id=gallery_pk)
64
    new_order = [int(x) for x in request.GET['new-order'].split(',')]
65
    for image in gallery.image_set.all():
66
        image.order = new_order.index(image.id)+1
67
        image.save()
68
    return redirect(reverse('combo-manager-page-view', kwargs={'pk': gallery.page.id}))
combo/manager/static/css/combo.manager.css
139 139
	margin-left: 2em;
140 140
}
141 141

  
142
.icon-eye-open:before             { content: "\f06e "; }
142
.icon-eye-open:before { content: "\f06e "; }
143
.icon-edit:before { content: "\f044"; }
143 144

  
144 145
div.objects-list > div {
145 146
	border: 1px solid #eee;
......
253 254
div#asset-cmds {
254 255
	text-align: right;
255 256
}
257

  
258
ul.gallery {
259
	list-style: none;
260
	margin: 0;
261
	padding: 0;
262
}
263

  
264
ul.gallery li {
265
	display: inline-block;
266
	margin: 0.5ex;
267
	position: relative;
268
}
269

  
270
ul.gallery li img {
271
	border: 1px solid #aaa;
272
	background: white;
273
	padding: 2px;
274
}
275

  
276
ul.gallery li.empty-image {
277
	width: 122px;
278
}
279

  
280
ul.gallery li span.image-actions {
281
	position: absolute;
282
	bottom: 5px;
283
	right: 5px;
284
	font-size: 150%;
285
}
256
-