Commit cfbb6f4e authored by Skia's avatar Skia
Browse files

Lot of small improvement in SAS

parent 0b23d39e
Pipeline #429 passed with stage
in 2 minutes and 14 seconds
from django.contrib import admin from django.contrib import admin
from ajax_select import make_ajax_form
from core.models import User, Page, RealGroup, SithFile from core.models import User, Page, RealGroup, SithFile
from django.contrib.auth.models import Group as AuthGroup from django.contrib.auth.models import Group as AuthGroup
...@@ -7,5 +8,9 @@ admin.site.register(User) ...@@ -7,5 +8,9 @@ admin.site.register(User)
admin.site.unregister(AuthGroup) admin.site.unregister(AuthGroup)
admin.site.register(RealGroup) admin.site.register(RealGroup)
admin.site.register(Page) admin.site.register(Page)
admin.site.register(SithFile)
@admin.register(SithFile)
class SithFileAdmin(admin.ModelAdmin):
form = make_ajax_form(SithFile, {
'parent': 'files', # ManyToManyField
})
...@@ -2,7 +2,7 @@ from django.core.exceptions import PermissionDenied ...@@ -2,7 +2,7 @@ from django.core.exceptions import PermissionDenied
from ajax_select import register, LookupChannel from ajax_select import register, LookupChannel
from core.views.site import search_user from core.views.site import search_user
from core.models import User, Group from core.models import User, Group, SithFile
from club.models import Club from club.models import Club
from counter.models import Product, Counter from counter.models import Product, Counter
from accounting.models import ClubAccount, Company from accounting.models import ClubAccount, Company
...@@ -77,6 +77,13 @@ class ProductsLookup(RightManagedLookupChannel): ...@@ -77,6 +77,13 @@ class ProductsLookup(RightManagedLookupChannel):
def format_item_display(self, item): def format_item_display(self, item):
return "%s (%s)" % (item.name, item.code) return "%s (%s)" % (item.name, item.code)
@register('files')
class SithFileLookup(RightManagedLookupChannel):
model = SithFile
def get_query(self, q, request):
return self.model.objects.filter(name__icontains=q)[:50]
@register('club_accounts') @register('club_accounts')
class ClubAccountLookup(RightManagedLookupChannel): class ClubAccountLookup(RightManagedLookupChannel):
model = ClubAccount model = ClubAccount
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
import core.models
class Migration(migrations.Migration):
dependencies = [
('core', '0010_sithfile_is_in_sas'),
]
operations = [
migrations.AlterField(
model_name='sithfile',
name='compressed',
field=models.FileField(verbose_name='compressed file', upload_to=core.models.get_compressed_directory, null=True, blank=True, max_length=256),
),
migrations.AlterField(
model_name='sithfile',
name='date',
field=models.DateTimeField(verbose_name='date', default=django.utils.timezone.now),
),
migrations.AlterField(
model_name='sithfile',
name='file',
field=models.FileField(verbose_name='file', upload_to=core.models.get_directory, null=True, blank=True, max_length=256),
),
migrations.AlterField(
model_name='sithfile',
name='thumbnail',
field=models.FileField(verbose_name='thumbnail', upload_to=core.models.get_thumbnail_directory, null=True, blank=True, max_length=256),
),
]
...@@ -317,7 +317,9 @@ class User(AbstractBaseUser): ...@@ -317,7 +317,9 @@ class User(AbstractBaseUser):
def get_short_name(self): def get_short_name(self):
"Returns the short name for the user." "Returns the short name for the user."
return self.first_name if self.nick_name:
return self.nick_name
return self.first_name + " " + self.last_name
def get_display_name(self): def get_display_name(self):
""" """
...@@ -501,16 +503,16 @@ def get_thumbnail_directory(instance, filename): ...@@ -501,16 +503,16 @@ def get_thumbnail_directory(instance, filename):
class SithFile(models.Model): class SithFile(models.Model):
name = models.CharField(_('file name'), max_length=256, blank=False) name = models.CharField(_('file name'), max_length=256, blank=False)
parent = models.ForeignKey('self', related_name="children", verbose_name=_("parent"), null=True, blank=True) parent = models.ForeignKey('self', related_name="children", verbose_name=_("parent"), null=True, blank=True)
file = models.FileField(upload_to=get_directory, verbose_name=_("file"), null=True, blank=True) file = models.FileField(upload_to=get_directory, verbose_name=_("file"), max_length=256, null=True, blank=True)
compressed = models.FileField(upload_to=get_compressed_directory, verbose_name=_("compressed file"), null=True, blank=True) compressed = models.FileField(upload_to=get_compressed_directory, verbose_name=_("compressed file"), max_length=256, null=True, blank=True)
thumbnail = models.FileField(upload_to=get_thumbnail_directory, verbose_name=_("thumbnail"), null=True, blank=True) thumbnail = models.FileField(upload_to=get_thumbnail_directory, verbose_name=_("thumbnail"), max_length=256, null=True, blank=True)
owner = models.ForeignKey(User, related_name="owned_files", verbose_name=_("owner")) owner = models.ForeignKey(User, related_name="owned_files", verbose_name=_("owner"))
edit_groups = models.ManyToManyField(Group, related_name="editable_files", verbose_name=_("edit group"), blank=True) edit_groups = models.ManyToManyField(Group, related_name="editable_files", verbose_name=_("edit group"), blank=True)
view_groups = models.ManyToManyField(Group, related_name="viewable_files", verbose_name=_("view group"), blank=True) view_groups = models.ManyToManyField(Group, related_name="viewable_files", verbose_name=_("view group"), blank=True)
is_folder = models.BooleanField(_("is folder"), default=True) is_folder = models.BooleanField(_("is folder"), default=True)
mime_type = models.CharField(_('mime type'), max_length=30) mime_type = models.CharField(_('mime type'), max_length=30)
size = models.IntegerField(_("size"), default=0) size = models.IntegerField(_("size"), default=0)
date = models.DateTimeField(_('date'), auto_now=True) date = models.DateTimeField(_('date'), default=timezone.now)
is_moderated = models.BooleanField(_("is moderated"), default=False) is_moderated = models.BooleanField(_("is moderated"), default=False)
asked_for_removal = models.BooleanField(_("asked for removal"), default=False) asked_for_removal = models.BooleanField(_("asked for removal"), default=False)
is_in_sas = models.BooleanField(_("is in the SAS"), default=False) is_in_sas = models.BooleanField(_("is in the SAS"), default=False)
...@@ -629,6 +631,9 @@ class SithFile(models.Model): ...@@ -629,6 +631,9 @@ class SithFile(models.Model):
def get_download_url(self): def get_download_url(self):
return reverse('core:download', kwargs={'file_id': self.id}) return reverse('core:download', kwargs={'file_id': self.id})
def __str__(self):
return self.get_parent_path() + "/" + self.name
class LockError(Exception): class LockError(Exception):
"""There was a lock error on the object""" """There was a lock error on the object"""
pass pass
......
...@@ -314,10 +314,11 @@ textarea { ...@@ -314,10 +314,11 @@ textarea {
text-align: center; text-align: center;
padding: 5px; padding: 5px;
width: 200px; width: 200px;
height: 133px; height: 140px;
background: #eee; background: #eee;
box-shadow: black 2px 2px 10px; box-shadow: black 2px 2px 10px;
margin: 10px; margin: 10px;
vertical-align: top;
} }
.album img { .album img {
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% for r in user.pictures.exclude(picture=None).values('user__pictures__picture__parent').distinct() %} {% for r in profile.pictures.exclude(picture=None).values('user__pictures__picture__parent').distinct() %}
<div style="padding: 10px"> <div style="padding: 10px">
{% set album = user.pictures.filter(picture__parent=r['user__pictures__picture__parent']).first().picture.parent %} {% set album = profile.pictures.filter(picture__parent=r['user__pictures__picture__parent']).first().picture.parent %}
<h4>{{ album.name }}</h4> <h4>{{ album.name }}</h4>
<hr> <hr>
{% for r in user.pictures.exclude(picture=None).filter(picture__parent=album) %} {% for r in profile.pictures.exclude(picture=None).filter(picture__parent=album).order_by('id') %}
<div class="picture"> <div class="picture">
<a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict"> <a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict">
<img src="{{ r.picture.as_picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/> <img src="{{ r.picture.as_picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/>
......
...@@ -25,7 +25,7 @@ from counter.models import Customer, Counter, Selling, Refilling, Product, Produ ...@@ -25,7 +25,7 @@ from counter.models import Customer, Counter, Selling, Refilling, Product, Produ
from subscription.models import Subscription, Subscriber from subscription.models import Subscription, Subscriber
from eboutic.models import Invoice, InvoiceItem from eboutic.models import Invoice, InvoiceItem
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label
from sas.models import Album, Picture from sas.models import Album, Picture, PeoplePictureRelation
db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS) db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
start = datetime.datetime.now() start = datetime.datetime.now()
...@@ -1029,7 +1029,7 @@ def migrate_sas(): ...@@ -1029,7 +1029,7 @@ def migrate_sas():
album_link = {} album_link = {}
picture_link = {} picture_link = {}
FILE_ROOT = "/data/sas/" FILE_ROOT = "/data/sas/"
Album.objects.filter(is_in_sas=True).delete() SithFile.objects.filter(id__gt=18886).delete()
print("Album/Pictures deleted") print("Album/Pictures deleted")
cur = db.cursor(MySQLdb.cursors.SSDictCursor) cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute(""" cur.execute("""
...@@ -1044,44 +1044,74 @@ def migrate_sas(): ...@@ -1044,44 +1044,74 @@ def migrate_sas():
album_link[str(r['id_catph'])] = a.id album_link[str(r['id_catph'])] = a.id
except Exception as e: except Exception as e:
print("FAIL to migrate Album: %s" % (repr(e))) print("FAIL to migrate Album: %s" % (repr(e)))
print("Album moved, need to make the tree")
cur.execute(""" cur.execute("""
SELECT * SELECT *
FROM sas_cat_photos FROM sas_cat_photos
""") """)
for r in cur: for r in cur:
try: try:
p = Album.objects.filter(id=album_link[r['id_catph_parent']]).first() p = Album.objects.filter(id=album_link[str(r['id_catph_parent'])]).first()
a = Album.objects.filter(id=album_link[r['id_catph']]).first() a = Album.objects.filter(id=album_link[str(r['id_catph'])]).first()
a.parent = p a.parent = p
a.save() a.save()
except: pass except: pass
print("Album migrated at %s" % datetime.datetime.now()) print("Album migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start)) print("Running time: %s" % (datetime.datetime.now()-start))
# cur.execute(""" cur.execute("""
# SELECT * SELECT *
# FROM sas_photos FROM sas_photos
# """) """)
# for r in cur: for r in cur:
# try: try:
# user = User.objects.filter(id=r['id_utilisateur']).first() or root user = User.objects.filter(id=r['id_utilisateur']).first() or root
# parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first() parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first()
file_name = FILE_ROOT
if r['date_prise_vue']:
file_name += r['date_prise_vue'].strftime("%Y/%m/%d")
else:
file_name += '/'.join(["1970", "01", "01"])
file_name += "/" + str(r['id_photo']) + ".jpg"
file = File(open(file_name, "rb"))
file.name = str(r['id_photo']) + ".jpg"
# p = Picture( p = Picture(
# name=to_unicode(str(r['id_photo'])), name=to_unicode(str(r['id_photo'])) + ".jpg",
# owner=user, owner=user,
# is_moderated=True, is_moderated=True,
# is_folder=False, is_folder=False,
# mime_type="image/jpeg", mime_type="image/jpeg",
# parent=parent parent=parent,
# ) file=file,
# for f in p._meta.local_fields: )
# if f.name == "date": if r['date_prise_vue']:
# f.auto_now = False p.date = r['date_prise_vue'].replace(tzinfo=timezone('Europe/Paris'))
# p.date = r['date_ajout_ph'].replace(tzinfo=timezone('Europe/Paris')) else:
# p.save() p.date = r['date_ajout_ph'].replace(tzinfo=timezone('Europe/Paris'))
# picture_link[str(r['id_photo'])] = p.id for f in p._meta.local_fields:
# except Exception as e: if f.name == "date":
# print("FAIL to migrate Picture: %s" % (repr(e))) f.auto_now = False
p.generate_thumbnails()
db2 = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
cur2 = db2.cursor(MySQLdb.cursors.SSDictCursor)
cur2.execute("""
SELECT *
FROM sas_personnes_photos
WHERE id_photo = %s
""", (r['id_photo'], ))
for r2 in cur2:
try:
u = User.objects.filter(id=r2['id_utilisateur']).first()
if u:
PeoplePictureRelation(user=u, picture=p).save()
except:
print("Fail to associate user %d to picture %d" % (r2['id_utilisateur'], p.id))
picture_link[str(r['id_photo'])] = p.id
except Exception as e:
pass
print("FAIL to migrate Picture: %s" % (repr(e)))
cur.close() cur.close()
print("SAS migrated at %s" % datetime.datetime.now()) print("SAS migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start)) print("Running time: %s" % (datetime.datetime.now()-start))
......
...@@ -4,5 +4,7 @@ from sas.models import * ...@@ -4,5 +4,7 @@ from sas.models import *
admin.site.register(Album) admin.site.register(Album)
admin.site.register(Picture) # admin.site.register(Picture)
admin.site.register(PeoplePictureRelation)
from django.db import models from django.db import models
from django.core.urlresolvers import reverse_lazy, reverse
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -36,6 +37,9 @@ class Picture(SithFile): ...@@ -36,6 +37,9 @@ class Picture(SithFile):
def get_download_thumb_url(self): def get_download_thumb_url(self):
return reverse('sas:download_thumb', kwargs={'picture_id': self.id}) return reverse('sas:download_thumb', kwargs={'picture_id': self.id})
def get_absolute_url(self):
return reverse('sas:picture', kwargs={'picture_id': self.id})
def generate_thumbnails(self): def generate_thumbnails(self):
im = Image.open(BytesIO(self.file.read())) im = Image.open(BytesIO(self.file.read()))
try: try:
...@@ -94,3 +98,6 @@ class PeoplePictureRelation(models.Model): ...@@ -94,3 +98,6 @@ class PeoplePictureRelation(models.Model):
class Meta: class Meta:
unique_together = ['user', 'picture'] unique_together = ['user', 'picture']
def __str__(self):
return self.user.get_display_name() + " - " + str(self.picture)
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
{% block content %} {% block content %}
<a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(album.parent) }} {{ album.get_display_name() }} <a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(album.parent) }} {{ album.get_display_name() }}
<h3>{{ album.get_display_name() }}</h3> <h3>{{ album.get_display_name() }}</h3>
<a href="{{ url('sas:album_edit', album_id=album.id) }}">{% trans %}Edit{% endtrans %}</a><br>
<hr> <hr>
<div> <div>
{% for a in album.children.filter(is_folder=True, is_moderated=True).all() %} {% for a in album.children.filter(is_folder=True, is_moderated=True).all() %}
...@@ -33,7 +34,7 @@ ...@@ -33,7 +34,7 @@
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
{% for p in album.children.filter(is_folder=False, is_moderated=True).all() %} {% for p in album.children.filter(is_folder=False, is_moderated=True).order_by('id') %}
{% if p.as_picture.can_be_viewed_by(user) %} {% if p.as_picture.can_be_viewed_by(user) %}
<div class="picture"> <div class="picture">
<a href="{{ url("sas:picture", picture_id=p.id) }}#pict"> <a href="{{ url("sas:picture", picture_id=p.id) }}#pict">
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
{% block content %} {% block content %}
<a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(picture.parent) }} {{ picture.get_display_name() }} <a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(picture.parent) }} {{ picture.get_display_name() }}
<h3>{{ picture.get_display_name() }}</h3> ({{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }})
<h3> {{ picture.get_display_name() }}</h3>
<div style="display: inline-block; width: 19%; vertical-align: top; overflow: hidden; float: right"> <div style="display: inline-block; width: 19%; vertical-align: top; overflow: hidden; float: right">
<div> <div>
<div id="prev"> <div id="prev">
...@@ -60,7 +61,7 @@ ...@@ -60,7 +61,7 @@
<ul> <ul>
{% for r in picture.people.all() %} {% for r in picture.people.all() %}
<li> <li>
<a href="{{ r.user.get_absolute_url() }}">{{ r.user.get_display_name() }}</a> <a href="{{ r.user.get_absolute_url() }}">{{ r.user.get_short_name() }}</a>
{% if user == r.user or user.is_in_group(settings.SITH_SAS_ADMIN_GROUP_ID) %} {% if user == r.user or user.is_in_group(settings.SITH_SAS_ADMIN_GROUP_ID) %}
<a href="?remove_user={{ r.user.id }}">{% trans %}Delete{% endtrans %}</a> <a href="?remove_user={{ r.user.id }}">{% trans %}Delete{% endtrans %}</a>
{% endif %} {% endif %}
...@@ -73,12 +74,18 @@ ...@@ -73,12 +74,18 @@
<p><input type="submit" value="{% trans %}Go{% endtrans %}" /></p> <p><input type="submit" value="{% trans %}Go{% endtrans %}" /></p>
</form> </form>
</div> </div>
<div>
<h5>{% trans %}Infos{% endtrans %}</h5>
<p>{% trans %}Date: {% endtrans %}{{ picture.date|date(DATETIME_FORMAT) }}</p>
<p>{{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }}</p>
</div>
<div> <div>
<h5>{% trans %}Tools{% endtrans %}</h5> <h5>{% trans %}Tools{% endtrans %}</h5>
<p> <p>
<a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a> <a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a>
</p> </p>
<p style="font-size: smaller;"> <p style="font-size: smaller;">
<a href="{{ url('sas:picture_edit', picture_id=picture.id) }}">{% trans %}Edit{% endtrans %}</a><br>
<a href="?rotate_left">{% trans %}Rotate left{% endtrans %}</a><br> <a href="?rotate_left">{% trans %}Rotate left{% endtrans %}</a><br>
<a href="?rotate_right">{% trans %}Rotate right{% endtrans %}</a><br> <a href="?rotate_right">{% trans %}Rotate right{% endtrans %}</a><br>
<a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a><br> <a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a><br>
......
...@@ -6,7 +6,9 @@ urlpatterns = [ ...@@ -6,7 +6,9 @@ urlpatterns = [
url(r'^$', SASMainView.as_view(), name='main'), url(r'^$', SASMainView.as_view(), name='main'),
url(r'^moderation$', ModerationView.as_view(), name='moderation'), url(r'^moderation$', ModerationView.as_view(), name='moderation'),
url(r'^album/(?P<album_id>[0-9]+)$', AlbumView.as_view(), name='album'), url(r'^album/(?P<album_id>[0-9]+)$', AlbumView.as_view(), name='album'),
url(r'^album/(?P<album_id>[0-9]+)/edit$', AlbumEditView.as_view(), name='album_edit'),
url(r'^picture/(?P<picture_id>[0-9]+)$', PictureView.as_view(), name='picture'), url(r'^picture/(?P<picture_id>[0-9]+)$', PictureView.as_view(), name='picture'),
url(r'^picture/(?P<picture_id>[0-9]+)/edit$', PictureEditView.as_view(), name='picture_edit'),
url(r'^picture/(?P<picture_id>[0-9]+)/download$', send_pict, name='download'), url(r'^picture/(?P<picture_id>[0-9]+)/download$', send_pict, name='download'),
url(r'^picture/(?P<picture_id>[0-9]+)/download/compressed$', send_compressed, name='download_compressed'), url(r'^picture/(?P<picture_id>[0-9]+)/download/compressed$', send_compressed, name='download_compressed'),
url(r'^picture/(?P<picture_id>[0-9]+)/download/thumb$', send_thumb, name='download_thumb'), url(r'^picture/(?P<picture_id>[0-9]+)/download/thumb$', send_thumb, name='download_thumb'),
......
...@@ -5,6 +5,7 @@ from django.views.generic.edit import UpdateView, CreateView, DeleteView, Proces ...@@ -5,6 +5,7 @@ from django.views.generic.edit import UpdateView, CreateView, DeleteView, Proces
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
from django.forms.models import modelform_factory
from django import forms from django import forms
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
...@@ -192,4 +193,27 @@ class ModerationView(TemplateView): ...@@ -192,4 +193,27 @@ class ModerationView(TemplateView):
kwargs['pictures'] = Picture.objects.filter(is_moderated=False, is_in_sas=True).order_by('id') kwargs['pictures'] = Picture.objects.filter(is_moderated=False, is_in_sas=True).order_by('id')
return kwargs return kwargs
class PictureEditForm(forms.ModelForm):
class Meta:
model = Picture
fields=['name', 'parent']
parent = make_ajax_field(Picture, 'parent', 'files', help_text="")
class AlbumEditForm(forms.ModelForm):
class Meta:
model = Album
fields=['name', 'parent']
parent = make_ajax_field(Album, 'parent', 'files', help_text="")
class PictureEditView(UpdateView):
model=Picture
form_class=PictureEditForm
template_name='core/edit.jinja'
pk_url_kwarg = "picture_id"
class AlbumEditView(UpdateView):
model=Album
form_class=AlbumEditForm
template_name='core/edit.jinja'
pk_url_kwarg = "album_id"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment