mirror of
https://github.com/wger-project/wger.git
synced 2026-02-19 07:50:55 +01:00
Add JS library to show the images in a grid
This commit is contained in:
@@ -26,7 +26,8 @@
|
||||
"jquery": "^3.6.0",
|
||||
"metrics-graphics": "mozilla/metrics-graphics#2.15.x",
|
||||
"shariff": "^3.2.1",
|
||||
"tinymce": "^5.7.1"
|
||||
"tinymce": "^5.7.1",
|
||||
"masonry-layout": "^4.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build:css:sass": "sass wger/core/static/scss/main.scss:wger/core/static/yarn/bootstrap-compiled.css"
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap-custom.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'yarn/components-font-awesome/css/all.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'yarn/shariff/dist/shariff.min.css' %}">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'yarn/metrics-graphics/dist/metricsgraphics.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/metricsgraphics-custom.css' %}">
|
||||
{% endcompress %}
|
||||
@@ -65,8 +66,8 @@
|
||||
<script src="{% static 'yarn/d3/d3.js' %}"></script>
|
||||
<script src="{% static 'yarn/metrics-graphics/dist/metricsgraphics.min.js' %}"></script>
|
||||
<script src="{% static 'yarn/devbridge-autocomplete/dist/jquery.autocomplete.min.js' %}"></script>
|
||||
<script src="{% static 'yarn/masonry-layout/dist/masonry.pkgd.min.js' %}"></script>
|
||||
<script src="{% static 'js/wger-core.js' %}"></script>
|
||||
<script src="{% static 'js/exercises.js' %}"></script>
|
||||
<script src="{% static 'js/nutrition.js' %}"></script>
|
||||
{% endcompress %}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.1.8 on 2021-05-01 02:11
|
||||
# Generated by Django 3.1.8 on 2021-05-03 10:53
|
||||
|
||||
import datetime
|
||||
from django.conf import settings
|
||||
@@ -19,20 +19,13 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Image',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID')),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('date', models.DateField(default=datetime.datetime.now, verbose_name='Date')),
|
||||
('image', models.ImageField(help_text='Only PNG and JPEG formats are supported',
|
||||
upload_to=wger.gallery.models.image.gallery_upload_dir,
|
||||
verbose_name='Image')),
|
||||
('description', models.TextField(blank=True,
|
||||
max_length=1000,
|
||||
verbose_name='Description')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name='User')),
|
||||
('image', models.ImageField(height_field='height', help_text='Only PNG and JPEG formats are supported', upload_to=wger.gallery.models.image.gallery_upload_dir, verbose_name='Image', width_field='width')),
|
||||
('height', models.IntegerField(editable=False)),
|
||||
('width', models.IntegerField(editable=False)),
|
||||
('description', models.TextField(blank=True, max_length=1000, verbose_name='Description')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-date'],
|
||||
|
||||
@@ -22,6 +22,7 @@ import uuid
|
||||
# Django
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@@ -29,7 +30,7 @@ def gallery_upload_dir(instance, filename):
|
||||
"""
|
||||
Returns the upload target for exercise images
|
||||
"""
|
||||
return "gallery/{0}/{1}.{2}".format(instance.user.id,
|
||||
return "gallery/{0}/{1}{2}".format(instance.user.id,
|
||||
uuid.uuid4(),
|
||||
pathlib.Path(filename).suffix)
|
||||
|
||||
@@ -48,14 +49,62 @@ class Image(models.Model):
|
||||
|
||||
image = models.ImageField(verbose_name=_('Image'),
|
||||
help_text=_('Only PNG and JPEG formats are supported'),
|
||||
upload_to=gallery_upload_dir)
|
||||
upload_to=gallery_upload_dir,
|
||||
height_field='height',
|
||||
width_field='width')
|
||||
|
||||
height = models.IntegerField(editable=False)
|
||||
"""Height of the image"""
|
||||
|
||||
width = models.IntegerField(editable=False)
|
||||
"""Width of the image"""
|
||||
|
||||
description = models.TextField(verbose_name=_('Description'),
|
||||
max_length=1000,
|
||||
blank=True)
|
||||
|
||||
|
||||
def get_owner_object(self):
|
||||
"""
|
||||
Returns the object that has owner information
|
||||
"""
|
||||
return self
|
||||
|
||||
@property
|
||||
def is_landscape(self):
|
||||
return self.width > self.height
|
||||
|
||||
@receiver(models.signals.post_delete, sender=Image)
|
||||
def auto_delete_file_on_delete(sender, instance: Image, **kwargs):
|
||||
"""
|
||||
Deletes file from filesystem
|
||||
when corresponding `MediaFile` object is deleted.
|
||||
"""
|
||||
if instance.image:
|
||||
|
||||
path = pathlib.Path(instance.image.path)
|
||||
if path.exists():
|
||||
path.unlink()
|
||||
|
||||
|
||||
@receiver(models.signals.pre_save, sender=Image)
|
||||
def auto_delete_file_on_change(sender, instance: Image, **kwargs):
|
||||
"""
|
||||
Deletes old file from filesystem
|
||||
when corresponding `MediaFile` object is updated
|
||||
with new file.
|
||||
"""
|
||||
if not instance.pk:
|
||||
return False
|
||||
|
||||
try:
|
||||
old_file = sender.objects.get(pk=instance.pk).image
|
||||
except sender.DoesNotExist:
|
||||
return False
|
||||
|
||||
new_file = instance.image
|
||||
if not old_file == new_file:
|
||||
path = pathlib.Path(old_file.path)
|
||||
if path.is_file():
|
||||
path.unlink()
|
||||
|
||||
|
||||
@@ -7,34 +7,58 @@
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row card-columns" >
|
||||
|
||||
{% for image in images %}
|
||||
<div class="card w-25">
|
||||
<a href="{% url 'gallery:images:edit' image.pk %}">
|
||||
<img class="card-img-top" src="{{ image.image.url }}" class="img-thumbnail" alt="{{ image.description }}" >
|
||||
</a>
|
||||
<div class="card-body">
|
||||
<p class="card-title">{{ image.date }}</p>
|
||||
<a href="{% url 'gallery:images:delete' image.id %}">
|
||||
<span class="{% fa_class 'trash' %}"></span>
|
||||
</a>
|
||||
<!--
|
||||
<p>
|
||||
#{{ image.id }}
|
||||
{{ image.description }}
|
||||
</p>
|
||||
-->
|
||||
<div class="modal fade" id="modalImage{{ image.id }}" tabindex="-1" role="dialog"
|
||||
aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">{{ image.date }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<a href="{{ image.image.url }}">
|
||||
<img src="{{ image.image.url }}" class="img-fluid">
|
||||
</a>
|
||||
{% if image.description %}
|
||||
<p> {{ image.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="{% url 'gallery:images:delete' image.id %}"
|
||||
class="btn btn-primary">
|
||||
<span class="{% fa_class 'trash' %}"></span>
|
||||
</a>
|
||||
<a href="{% url 'gallery:images:edit' image.id %}" class="btn btn-primary">
|
||||
<span class="{% fa_class 'edit' %}"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="row" >
|
||||
{% for image in images %}
|
||||
<div class="col-sm-6 col-lg-4 mb-4">
|
||||
<div class="card">
|
||||
<a href="#" data-toggle="modal" data-target="#modalImage{{ image.id }}">
|
||||
<img class="card-img-top" src="{{ image.image.url }}" alt="{{ image.description }}">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block options %}
|
||||
<a href="{% url 'gallery:images:add' %}" class="btn btn-success btn-sm">
|
||||
{% translate "Add image" %}
|
||||
</a>
|
||||
<a href="{% url 'gallery:images:add' %}" class="btn btn-success btn-sm">
|
||||
{% translate "Add image" %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
42
yarn.lock
42
yarn.lock
@@ -14,7 +14,6 @@
|
||||
|
||||
Sortable@RubaXa/Sortable#1.13.0:
|
||||
version "1.13.0"
|
||||
uid "8a987c007cff0535edf65cd19a1a0a70cd880a07"
|
||||
resolved "https://codeload.github.com/RubaXa/Sortable/tar.gz/8a987c007cff0535edf65cd19a1a0a70cd880a07"
|
||||
|
||||
bootstrap@twbs/bootstrap#4.x:
|
||||
@@ -28,7 +27,6 @@ commander@2:
|
||||
|
||||
components-font-awesome@components/font-awesome#5.15.3:
|
||||
version "5.15.1"
|
||||
uid "09f1f2e02ea0cd319569b32f8639b37dfcd7a62d"
|
||||
resolved "https://codeload.github.com/components/font-awesome/tar.gz/09f1f2e02ea0cd319569b32f8639b37dfcd7a62d"
|
||||
|
||||
d3-array@1, d3-array@^1.2.0:
|
||||
@@ -372,7 +370,6 @@ d3@^4:
|
||||
|
||||
d3@mbostock-bower/d3-bower#>=5:
|
||||
version "0.0.0"
|
||||
uid c15b85ce115be200bd4ca473f97fcd0bb43bba07
|
||||
resolved "https://codeload.github.com/mbostock-bower/d3-bower/tar.gz/c15b85ce115be200bd4ca473f97fcd0bb43bba07"
|
||||
|
||||
datatables@DataTables/DataTables#1.10.x:
|
||||
@@ -381,6 +378,11 @@ datatables@DataTables/DataTables#1.10.x:
|
||||
dependencies:
|
||||
jquery ">=1.7"
|
||||
|
||||
desandro-matches-selector@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz#717beed4dc13e7d8f3762f707a6d58a6774218e1"
|
||||
integrity sha1-cXvu1NwT59jzdi9wem1YpndCGOE=
|
||||
|
||||
devbridge-autocomplete@^1.4.11:
|
||||
version "1.4.11"
|
||||
resolved "https://registry.yarnpkg.com/devbridge-autocomplete/-/devbridge-autocomplete-1.4.11.tgz#05424a675711a9c3ad118c98de0a22180944b00f"
|
||||
@@ -389,6 +391,23 @@ devbridge-autocomplete@^1.4.11:
|
||||
"@types/jquery" "^2.0.32"
|
||||
jquery ">=1.7"
|
||||
|
||||
ev-emitter@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ev-emitter/-/ev-emitter-1.1.1.tgz#8f18b0ce5c76a5d18017f71c0a795c65b9138f2a"
|
||||
integrity sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==
|
||||
|
||||
fizzy-ui-utils@^2.0.0:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz#7df45dcc4eb374a08b65d39bb9a4beedf7330505"
|
||||
integrity sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==
|
||||
dependencies:
|
||||
desandro-matches-selector "^2.0.0"
|
||||
|
||||
get-size@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/get-size/-/get-size-2.0.3.tgz#54a1d0256b20ea7ac646516756202769941ad2ef"
|
||||
integrity sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==
|
||||
|
||||
iconv-lite@0.4:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@@ -401,12 +420,29 @@ jquery@>=1.7, jquery@^3.4.1, jquery@^3.6.0:
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
|
||||
integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
|
||||
|
||||
masonry-layout@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/masonry-layout/-/masonry-layout-4.2.2.tgz#d57b44af13e601bfcdc423f1dd8348b5524de348"
|
||||
integrity sha512-iGtAlrpHNyxaR19CvKC3npnEcAwszXoyJiI8ARV2ePi7fmYhIud25MHK8Zx4P0LCC4d3TNO9+rFa1KoK1OEOaA==
|
||||
dependencies:
|
||||
get-size "^2.0.2"
|
||||
outlayer "^2.1.0"
|
||||
|
||||
metrics-graphics@mozilla/metrics-graphics#2.15.x:
|
||||
version "2.15.6"
|
||||
resolved "https://codeload.github.com/mozilla/metrics-graphics/tar.gz/9c213c7d80a19191bc3cf26e1ca17942447aa240"
|
||||
dependencies:
|
||||
d3 "^4"
|
||||
|
||||
outlayer@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/outlayer/-/outlayer-2.1.1.tgz#29863b6de10ea5dadfffcadfa0d728907387e9a2"
|
||||
integrity sha1-KYY7beEOpdrf/8rfoNcokHOH6aI=
|
||||
dependencies:
|
||||
ev-emitter "^1.0.0"
|
||||
fizzy-ui-utils "^2.0.0"
|
||||
get-size "^2.0.2"
|
||||
|
||||
rw@1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||
|
||||
Reference in New Issue
Block a user