photo-objects 0.9.5__tar.gz → 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. {photo_objects-0.9.5 → photo_objects-0.10.0}/PKG-INFO +1 -1
  2. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/photo.py +0 -48
  3. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/utils.py +2 -7
  4. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/forms.py +0 -26
  5. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_utils.py +3 -2
  6. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/urls.py +5 -1
  7. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/album.py +25 -9
  8. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/configuration.py +16 -6
  9. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/photo.py +19 -30
  10. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/photo_change_request.py +6 -5
  11. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/users.py +4 -6
  12. photo_objects-0.10.0/photo_objects/django/views/ui/utils.py +25 -0
  13. photo_objects-0.10.0/photo_objects/django/views/utils.py +86 -0
  14. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects.egg-info/PKG-INFO +1 -1
  15. {photo_objects-0.9.5 → photo_objects-0.10.0}/pyproject.toml +1 -1
  16. photo_objects-0.9.5/photo_objects/django/views/ui/utils.py +0 -10
  17. photo_objects-0.9.5/photo_objects/django/views/utils.py +0 -42
  18. {photo_objects-0.9.5 → photo_objects-0.10.0}/LICENSE +0 -0
  19. {photo_objects-0.9.5 → photo_objects-0.10.0}/README.md +0 -0
  20. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/__init__.py +0 -0
  21. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/config.py +0 -0
  22. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/__init__.py +0 -0
  23. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/admin.py +0 -0
  24. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/__init__.py +0 -0
  25. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/album.py +0 -0
  26. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/auth.py +0 -0
  27. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/backup.py +0 -0
  28. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/api/photo_change_request.py +0 -0
  29. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/apps.py +0 -0
  30. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/conf.py +0 -0
  31. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/context_processors.py +0 -0
  32. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/management/__init__.py +0 -0
  33. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/management/commands/__init__.py +0 -0
  34. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/management/commands/clean-scaled-photos.py +0 -0
  35. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/management/commands/create-initial-admin-account.py +0 -0
  36. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/management/commands/restore-backup.py +0 -0
  37. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0001_initial.py +0 -0
  38. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0002_created_at_updated_at.py +0 -0
  39. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0003_admin_visibility.py +0 -0
  40. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0004_camera_setup_and_settings.py +0 -0
  41. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0005_sitesettings.py +0 -0
  42. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0006_photo_alt_text.py +0 -0
  43. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/0007_backup.py +0 -0
  44. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/migrations/__init__.py +0 -0
  45. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/models.py +0 -0
  46. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/objsto.py +0 -0
  47. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/signals.py +0 -0
  48. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/templatetags/__init__.py +0 -0
  49. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/templatetags/photo_objects_extras.py +0 -0
  50. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/__init__.py +0 -0
  51. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_album.py +0 -0
  52. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_auth.py +0 -0
  53. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_commands.py +0 -0
  54. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_img.py +0 -0
  55. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_og_meta.py +0 -0
  56. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_photo.py +0 -0
  57. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/test_photo_change_requests.py +0 -0
  58. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/tests/utils.py +0 -0
  59. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/__init__.py +0 -0
  60. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/api/__init__.py +0 -0
  61. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/api/album.py +0 -0
  62. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/api/auth.py +0 -0
  63. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/api/photo.py +0 -0
  64. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/api/utils.py +0 -0
  65. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/django/views/ui/__init__.py +0 -0
  66. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/error.py +0 -0
  67. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/img.py +0 -0
  68. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects/utils.py +0 -0
  69. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects.egg-info/SOURCES.txt +0 -0
  70. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects.egg-info/dependency_links.txt +0 -0
  71. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects.egg-info/requires.txt +0 -0
  72. {photo_objects-0.9.5 → photo_objects-0.10.0}/photo_objects.egg-info/top_level.txt +0 -0
  73. {photo_objects-0.9.5 → photo_objects-0.10.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.9.5
3
+ Version: 0.10.0
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -9,7 +9,6 @@ from photo_objects.django import objsto
9
9
  from photo_objects.django.forms import (
10
10
  CreatePhotoForm,
11
11
  ModifyPhotoForm,
12
- UploadPhotosForm,
13
12
  slugify,
14
13
  )
15
14
  from photo_objects.img import photo_details
@@ -17,7 +16,6 @@ from photo_objects.img import photo_details
17
16
  from .auth import check_album_access, check_photo_access
18
17
  from .utils import (
19
18
  FormValidationFailed,
20
- UploadPhotosFailed,
21
19
  JsonProblem,
22
20
  check_permissions,
23
21
  parse_input_data,
@@ -74,52 +72,6 @@ def upload_photo(request: HttpRequest, album_key: str):
74
72
  return _upload_photo(album_key, photo_file)
75
73
 
76
74
 
77
- def _join_errors(errors: dict) -> str:
78
- messages = []
79
- for _, errs in errors.items():
80
- for err in errs:
81
- try:
82
- messages.append(err.get('message'))
83
- except AttributeError:
84
- messages.append(str(err))
85
- return " ".join(messages) if messages else "Unknown error."
86
-
87
-
88
- def upload_photos(request: HttpRequest, album_key: str):
89
- check_permissions(
90
- request,
91
- 'photo_objects.add_photo',
92
- 'photo_objects.change_album')
93
-
94
- f = UploadPhotosForm(request.POST, request.FILES)
95
- if not f.is_valid():
96
- raise FormValidationFailed(f)
97
-
98
- photo_files = f.cleaned_data["photos"]
99
- if len(photo_files) < 1:
100
- f.add_error("photos", "Expected at least one file, got 0.")
101
- raise FormValidationFailed(f)
102
-
103
- photos = []
104
- for photo_file in f.cleaned_data["photos"]:
105
- try:
106
- photos.append(_upload_photo(album_key, photo_file))
107
- except FormValidationFailed as e:
108
- message = _join_errors(e.form.errors.get_json_data())
109
- f.add_error(
110
- "photos",
111
- f"Failed to upload {photo_file.name}. {message}")
112
- except JsonProblem as e:
113
- f.add_error(
114
- "photos",
115
- f"Failed to upload {photo_file.name}. {e.title}")
116
-
117
- if not f.is_valid():
118
- raise UploadPhotosFailed(f, [i.filename for i in photos])
119
-
120
- return photos
121
-
122
-
123
75
  def modify_photo(request: HttpRequest, album_key: str, photo_key: str):
124
76
  check_permissions(request, 'photo_objects.change_photo')
125
77
  photo = check_photo_access(request, album_key, photo_key, 'xs')
@@ -53,7 +53,8 @@ class JsonProblem(PhotoObjectsError):
53
53
  'Albums',
54
54
  reverse_lazy('photo_objects:list_albums')),
55
55
  "problem_title": self.title,
56
- "status": self.status
56
+ "status": self.status,
57
+ "width": "narrow",
57
58
  }, status=self.status)
58
59
 
59
60
 
@@ -137,12 +138,6 @@ class FormValidationFailed(JsonProblem):
137
138
  self.form = form
138
139
 
139
140
 
140
- class UploadPhotosFailed(FormValidationFailed):
141
- def __init__(self, form: ModelForm, uploaded_photos: list[str]):
142
- super().__init__(form)
143
- self.uploaded_photos = uploaded_photos
144
-
145
-
146
141
  def check_permissions(request: HttpRequest, *permissions: str):
147
142
  if not request.user.is_authenticated:
148
143
  raise Unauthorized()
@@ -3,9 +3,6 @@ import random
3
3
  from django import forms
4
4
  from django.forms import (
5
5
  CharField,
6
- ClearableFileInput,
7
- FileField,
8
- Form,
9
6
  HiddenInput,
10
7
  ModelForm,
11
8
  RadioSelect,
@@ -220,26 +217,3 @@ class ReviewPhotoChangeRequestForm(ModelForm):
220
217
  help_texts = {
221
218
  'alt_text': ALT_TEXT_HELP,
222
219
  }
223
-
224
-
225
- class MultipleFileInput(ClearableFileInput):
226
- allow_multiple_selected = True
227
-
228
-
229
- class MultipleFileField(FileField):
230
- def __init__(self, *args, **kwargs):
231
- kwargs.setdefault('widget', MultipleFileInput())
232
- super().__init__(*args, **kwargs)
233
-
234
- def clean(self, data, initial=None):
235
- single_file_clean = super().clean
236
- if isinstance(data, (list, tuple)):
237
- result = [single_file_clean(d, initial) for d in data]
238
- else:
239
- result = [single_file_clean(data, initial)]
240
- return result
241
-
242
-
243
- class UploadPhotosForm(Form):
244
- photos = MultipleFileField(label=_(
245
- 'Drag and drop photos here or click to open upload dialog.'))
@@ -56,8 +56,9 @@ class TestUtils(TestCase):
56
56
  "Plain text description"),
57
57
  (md_multi_p,
58
58
  "Description with bold and italics..."),
59
- (None,
60
- "A simple self-hosted photo server."),
59
+ # TODO: Test default description and description from site-settings
60
+ # (None,
61
+ # "A simple self-hosted photo server."),
61
62
  ]
62
63
 
63
64
  for description, expected in testdata:
@@ -9,7 +9,11 @@ urlpatterns = [
9
9
  path("_auth", api.has_permission),
10
10
  path("api/albums", api.albums),
11
11
  path("api/albums/<str:album_key>", api.album),
12
- path("api/albums/<str:album_key>/photos", api.photos),
12
+ path(
13
+ "api/albums/<str:album_key>/photos",
14
+ api.photos,
15
+ name="api_photos",
16
+ ),
13
17
  path("api/albums/<str:album_key>/photos/<str:photo_key>", api.photo),
14
18
  path(
15
19
  "api/albums/<str:album_key>/photos/<str:photo_key>/change-requests",
@@ -9,11 +9,12 @@ from photo_objects.django.forms import CreateAlbumForm, ModifyAlbumForm
9
9
  from photo_objects.django.models import Album
10
10
  from photo_objects.django.views.utils import (
11
11
  BackLink,
12
+ Preview,
12
13
  meta_description,
13
14
  )
14
15
  from photo_objects.utils import render_markdown
15
16
 
16
- from .utils import json_problem_as_html
17
+ from .utils import json_problem_as_html, preview_helptext
17
18
 
18
19
 
19
20
  @json_problem_as_html
@@ -46,6 +47,7 @@ def new_album(request: HttpRequest):
46
47
  "form": form,
47
48
  "title": "Create album",
48
49
  "back": back,
50
+ "width": "narrow",
49
51
  })
50
52
 
51
53
 
@@ -106,14 +108,24 @@ def edit_album(request: HttpRequest, album_key: str):
106
108
  reverse(
107
109
  'photo_objects:show_album',
108
110
  kwargs={"album_key": album_key}))
109
-
110
- return render(request, 'photo_objects/form.html', {
111
- "form": form,
112
- "title": "Edit album",
113
- "back": back,
114
- "photo": album.cover_photo,
115
- "info": get_info(request, album_key),
116
- })
111
+ empty = album.cover_photo is None
112
+
113
+ return render(
114
+ request,
115
+ 'photo_objects/form.html',
116
+ {
117
+ "form": form,
118
+ "title": "Edit album",
119
+ "back": back,
120
+ "info": get_info(
121
+ request,
122
+ album_key),
123
+ "width": "narrow",
124
+ "preview": Preview(
125
+ request,
126
+ album,
127
+ preview_helptext("album", empty)),
128
+ })
117
129
 
118
130
 
119
131
  @json_problem_as_html
@@ -140,10 +152,14 @@ def delete_album(request: HttpRequest, album_key: str):
140
152
  error = {'error': _(
141
153
  'This album is managed by the system and can not be deleted.')}
142
154
 
155
+ empty = album.cover_photo is None
156
+
143
157
  return render(request, 'photo_objects/delete.html', {
144
158
  "title": "Delete album",
145
159
  "back": back,
146
160
  "photo": album.cover_photo,
147
161
  "resource": target,
162
+ "width": "narrow",
163
+ "preview": Preview(request, album, preview_helptext("album", empty)),
148
164
  **error,
149
165
  })
@@ -6,7 +6,7 @@ from django.urls import reverse
6
6
  from django.utils.translation import gettext_lazy as _
7
7
 
8
8
  from photo_objects.django.api.utils import JsonProblem
9
- from photo_objects.django.views.utils import BackLink
9
+ from photo_objects.django.views.utils import BackLink, Preview
10
10
  from photo_objects.utils import render_markdown
11
11
 
12
12
  from .utils import json_problem_as_html
@@ -169,8 +169,18 @@ def configuration(request: HttpRequest):
169
169
 
170
170
  back = BackLink("Albums", reverse('photo_objects:list_albums'))
171
171
 
172
- return render(request, "photo_objects/configuration.html", {
173
- "title": "Configuration",
174
- "validations": validations,
175
- "back": back,
176
- })
172
+ return render(
173
+ request,
174
+ "photo_objects/configuration.html",
175
+ {
176
+ "title": "Configuration",
177
+ "validations": validations,
178
+ "back": back,
179
+ "width": "narrow",
180
+ "preview": Preview(
181
+ request,
182
+ None,
183
+ "This is an example on how the site will appear by default "
184
+ "when sharing in social media. Note that individual albums "
185
+ "and photos override this default preview."),
186
+ })
@@ -6,53 +6,36 @@ from photo_objects.django import api
6
6
  from photo_objects.django.api.utils import (
7
7
  AlbumNotFound,
8
8
  FormValidationFailed,
9
- UploadPhotosFailed,
10
9
  )
11
- from photo_objects.django.forms import ModifyPhotoForm, UploadPhotosForm
10
+ from photo_objects.django.forms import ModifyPhotoForm
12
11
  from photo_objects.django.models import Photo
13
12
  from photo_objects.django.views.utils import (
14
13
  BackLink,
14
+ Preview,
15
15
  meta_description,
16
16
  )
17
17
  from photo_objects.utils import render_markdown
18
18
 
19
- from .utils import json_problem_as_html
19
+ from .utils import json_problem_as_html, preview_helptext
20
20
 
21
21
 
22
22
  @json_problem_as_html
23
23
  def upload_photos(request: HttpRequest, album_key: str):
24
- if request.method == "POST":
25
- try:
26
- api.upload_photos(request, album_key)
27
- return HttpResponseRedirect(
28
- reverse(
29
- 'photo_objects:show_album',
30
- kwargs={"album_key": album_key}))
31
- except UploadPhotosFailed as e:
32
- form = e.form
33
- uploaded_count = len(e.uploaded_photos)
34
- if uploaded_count > 0:
35
- plural = 's' if uploaded_count != 1 else ''
36
- info = f"Successfully uploaded {uploaded_count} photo{plural}."
37
- else:
38
- info = None
39
- else:
40
- form = UploadPhotosForm()
41
- info = None
42
-
43
24
  album = api.check_album_access(request, album_key)
44
25
  target = album.title or album.key
45
26
  back = BackLink(
46
27
  target, reverse(
47
28
  'photo_objects:show_album', kwargs={
48
29
  "album_key": album_key}))
30
+ empty = album.cover_photo is None
49
31
 
50
32
  return render(request, 'photo_objects/photo/upload.html', {
51
- "form": form,
52
- "info": info,
53
33
  "title": "Upload photos",
54
34
  "back": back,
35
+ "album": album,
55
36
  "photo": album.cover_photo,
37
+ "width": "narrow",
38
+ "preview": Preview(request, album, preview_helptext("album", empty)),
56
39
  })
57
40
 
58
41
 
@@ -177,12 +160,16 @@ def edit_photo(request: HttpRequest, album_key: str, photo_key: str):
177
160
  "album_key": album_key,
178
161
  "photo_key": photo_key}))
179
162
 
180
- return render(request, 'photo_objects/form.html', {
181
- "form": form,
182
- "title": "Edit photo",
183
- "back": back,
184
- "photo": photo,
185
- })
163
+ return render(
164
+ request,
165
+ 'photo_objects/form.html',
166
+ {
167
+ "form": form,
168
+ "title": "Edit photo",
169
+ "back": back,
170
+ "width": "narrow",
171
+ "preview": Preview(request, photo, preview_helptext("photo")),
172
+ })
186
173
 
187
174
 
188
175
  @json_problem_as_html
@@ -208,4 +195,6 @@ def delete_photo(request: HttpRequest, album_key: str, photo_key: str):
208
195
  "back": back,
209
196
  "photo": photo,
210
197
  "resource": target,
198
+ "width": "narrow",
199
+ "preview": Preview(request, photo, preview_helptext("photo")),
211
200
  })
@@ -7,7 +7,7 @@ from photo_objects.django.api.utils import (
7
7
  FormValidationFailed,
8
8
  )
9
9
  from photo_objects.django.forms import ReviewPhotoChangeRequestForm
10
- from photo_objects.django.views.utils import BackLink
10
+ from photo_objects.django.views.utils import BackLink, Preview
11
11
  from photo_objects.utils import render_markdown
12
12
 
13
13
  from .utils import json_problem_as_html
@@ -49,13 +49,14 @@ def review_photo_change_request(request: HttpRequest, cr_id: str):
49
49
 
50
50
  back = BackLink("Albums", reverse('photo_objects:list_albums'))
51
51
 
52
+ helptext = render_markdown(
53
+ f'The current alt text for `{photo.key}` is: _"{photo.alt_text}"_.')
54
+
52
55
  return render(request, 'photo_objects/form.html', {
53
56
  "form": form,
54
57
  "title": "Review photo change request",
55
58
  "back": back,
56
- "photo": photo,
57
59
  "info": info,
58
- "instructions": render_markdown(
59
- f'The current alt text for `{photo.key}` is: '
60
- f'_"{photo.alt_text}"_.'),
60
+ "width": "narrow",
61
+ "preview": Preview(request, photo, helptext),
61
62
  })
@@ -2,22 +2,20 @@ from django.contrib.auth import views as auth_views
2
2
  from django.http import HttpRequest
3
3
  from django.urls import reverse_lazy
4
4
 
5
- from photo_objects.django.models import SiteSettings
6
- from photo_objects.django.views.utils import BackLink
5
+ from photo_objects.django.views.utils import BackLink, Preview
7
6
 
8
7
 
9
8
  def login(request: HttpRequest):
10
- settings = SiteSettings.objects.get(request.site)
11
-
12
9
  return auth_views.LoginView.as_view(
13
10
  template_name="photo_objects/form.html",
14
11
  extra_context={
15
12
  "title": "Login",
16
- "photo": settings.preview_image,
17
13
  "action": "Login",
18
14
  "back": BackLink(
19
15
  'Albums',
20
16
  reverse_lazy('photo_objects:list_albums')),
21
- "class": "login"
17
+ "class": "login",
18
+ "width": "narrow",
19
+ "preview": Preview(request, None),
22
20
  },
23
21
  )(request)
@@ -0,0 +1,25 @@
1
+ from photo_objects.django.api.utils import JsonProblem
2
+
3
+
4
+ def json_problem_as_html(func):
5
+ def wrapper(*args, **kwargs):
6
+ try:
7
+ return func(*args, **kwargs)
8
+ except JsonProblem as e:
9
+ return e.html_response(args[0])
10
+ return wrapper
11
+
12
+
13
+ def preview_helptext(resource_type: str, empty: bool = False) -> str:
14
+ if resource_type == "album" and empty:
15
+ return (
16
+ f"This is an example on how the {resource_type} would appear "
17
+ "when sharing on social media. Upload photos and select a cover "
18
+ "photo to use this album specific preview instead of the server "
19
+ "level default preview."
20
+ )
21
+
22
+ return (
23
+ f"This is an example on how the {resource_type} will currently appear "
24
+ "when sharing on social media."
25
+ )
@@ -0,0 +1,86 @@
1
+ from django.http import HttpRequest
2
+ from django.utils.dateformat import format as format_date
3
+
4
+ from photo_objects.django.models import Album, Photo, SiteSettings
5
+ from photo_objects.utils import first_paragraph_textcontent
6
+
7
+
8
+ class BackLink:
9
+ def __init__(self, text: str, url: str):
10
+ self.text = text
11
+ self.url = url
12
+
13
+
14
+ # TODO: Use this also for meta-og tags
15
+ class Preview:
16
+ def __init__(
17
+ self,
18
+ request: HttpRequest,
19
+ resource: Album | Photo = None,
20
+ helptext: str = None):
21
+ self.description = meta_description(request, resource)
22
+ self.photo = meta_photo(request, resource)
23
+ self.title = meta_title(request, resource)
24
+ self.helptext = helptext
25
+
26
+
27
+ def _default_album_description(request: HttpRequest, album: Album) -> str:
28
+ count = album.photo_set.count()
29
+ plural = 's' if count != 1 else ''
30
+ return f"Album with {count} photo{plural} in {request.site.name}."
31
+
32
+
33
+ def _default_photo_description(photo: Photo) -> str:
34
+ date_str = format_date(photo.timestamp, "F Y")
35
+ return f"Photo from {date_str} in {photo.album.title} album."
36
+
37
+
38
+ def meta_description(
39
+ request: HttpRequest,
40
+ resource: Album | Photo | str = None) -> str:
41
+ text = None
42
+ if isinstance(resource, Album):
43
+ return (
44
+ first_paragraph_textcontent(resource.description) or
45
+ _default_album_description(request, resource))
46
+
47
+ if isinstance(resource, Photo):
48
+ return (
49
+ first_paragraph_textcontent(resource.description) or
50
+ _default_photo_description(resource))
51
+
52
+ if isinstance(resource, str):
53
+ return first_paragraph_textcontent(resource)
54
+
55
+ settings = SiteSettings.objects.get(request.site)
56
+ text = first_paragraph_textcontent(settings.description)
57
+ return text or "A simple self-hosted photo server."
58
+
59
+
60
+ def meta_photo(
61
+ request: HttpRequest,
62
+ resource: Album | Photo = None) -> Photo:
63
+ if isinstance(resource, Photo):
64
+ return resource
65
+
66
+ if isinstance(resource, Album):
67
+ return resource.cover_photo
68
+
69
+ settings = SiteSettings.objects.get(request.site)
70
+ return settings.preview_image
71
+
72
+
73
+ def meta_title(
74
+ request: HttpRequest,
75
+ resource: Album | Photo | str = None) -> str:
76
+ text = None
77
+ if isinstance(resource, Album):
78
+ text = resource.title
79
+
80
+ if isinstance(resource, Photo):
81
+ text = resource.title or resource.filename
82
+
83
+ if isinstance(resource, str):
84
+ text = resource
85
+
86
+ return text or request.site.name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.9.5
3
+ Version: 0.10.0
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "photo-objects"
7
- version = "0.9.5"
7
+ version = "0.10.0"
8
8
  dependencies = [
9
9
  "markdown~=3.7",
10
10
  "minio>=7.2.0,<7.2.19",
@@ -1,10 +0,0 @@
1
- from photo_objects.django.api.utils import JsonProblem
2
-
3
-
4
- def json_problem_as_html(func):
5
- def wrapper(*args, **kwargs):
6
- try:
7
- return func(*args, **kwargs)
8
- except JsonProblem as e:
9
- return e.html_response(args[0])
10
- return wrapper
@@ -1,42 +0,0 @@
1
- from django.http import HttpRequest
2
- from django.utils.dateformat import format as format_date
3
-
4
- from photo_objects.django.models import Album, Photo
5
- from photo_objects.utils import first_paragraph_textcontent
6
-
7
-
8
- class BackLink:
9
- def __init__(self, text: str, url: str):
10
- self.text = text
11
- self.url = url
12
-
13
-
14
- def _default_album_description(request: HttpRequest, album: Album) -> str:
15
- count = album.photo_set.count()
16
- plural = 's' if count != 1 else ''
17
- return f"Album with {count} photo{plural} in {request.site.name}."
18
-
19
-
20
- def _default_photo_description(photo: Photo) -> str:
21
- date_str = format_date(photo.timestamp, "F Y")
22
- return f"Photo from {date_str} in {photo.album.title} album."
23
-
24
-
25
- def meta_description(
26
- request: HttpRequest,
27
- resource: Album | Photo | str | None) -> str:
28
- text = None
29
- if isinstance(resource, Album):
30
- text = (
31
- first_paragraph_textcontent(resource.description) or
32
- _default_album_description(request, resource))
33
-
34
- if isinstance(resource, Photo):
35
- text = (
36
- first_paragraph_textcontent(resource.description) or
37
- _default_photo_description(resource))
38
-
39
- if isinstance(resource, str):
40
- text = first_paragraph_textcontent(resource)
41
-
42
- return text or "A simple self-hosted photo server."
File without changes
File without changes
File without changes