From c732ce1d489f567f624526245cddd35140b2b52c Mon Sep 17 00:00:00 2001 From: MaertHaekkinen Date: Sun, 24 Nov 2024 01:02:21 +0200 Subject: [PATCH] Add year filter to gallery --- ajapaik/ajapaik/api.py | 40 +- ajapaik/ajapaik/forms.py | 2 + ajapaik/ajapaik/static/js/ajp-core.js | 86 +++ ajapaik/ajapaik/static/js/ajp-frontpage.js | 4 +- ajapaik/ajapaik/static/js/constants.js | 282 +++++----- .../static/js/photoview/annotations.js | 171 +++--- .../ajapaik/templates/common/frontpage.html | 3 - .../filtering/_filtering_dropdown.html | 492 ++++++++++-------- ajapaik/ajapaik/views.py | 25 +- 9 files changed, 629 insertions(+), 476 deletions(-) diff --git a/ajapaik/ajapaik/api.py b/ajapaik/ajapaik/api.py index 3131d9877..5a0e5c856 100644 --- a/ajapaik/ajapaik/api.py +++ b/ajapaik/ajapaik/api.py @@ -201,7 +201,7 @@ def _authenticate_with_wikimedia_commons(self, request, access_token): adapter = WikimediaCommonsOAuth2Adapter(request) return self._authenticate_with_oauth2_access_token(adapter, request, access_token) - def post(self, request, format=None): + def post(self, request): form = forms.APILoginForm(request.data) user = None @@ -276,7 +276,7 @@ class Register(APIView): permission_classes = (AllowAny,) authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication) - def post(self, request, format=None): + def post(self, request): form = forms.APIRegisterForm(request.data) if form.is_valid(): registration_type = form.cleaned_data['type'] @@ -368,13 +368,13 @@ def _reset_session_cookie(self, request): del request.session['sessionid'] return request - def post(self, request, format=None): + def post(self, request): body = request.body post = self._fix_latin1_query_param(request, body) request = self._reset_session_cookie(request) return self._handle_request(post, request.user, request) - def get(self, request, format=None): + def get(self, request): request = self._reset_session_cookie(request) return self._handle_request(request.GET, request.user, request) @@ -679,7 +679,7 @@ def _handle_request(self, data, user, request): photos = Photo.objects.filter(rephoto_of__isnull=True, ).annotate( distance=GeometryDistance("geography", ref_location)).order_by("distance")[start:end] photo_ids = photos.values_list('id', flat=True) - photos = Photo.objects.filter(id__in=photo_ids).order_by(GeometryDistance("geography", ref_location)); + photos = Photo.objects.filter(id__in=photo_ids).order_by(GeometryDistance("geography", ref_location)) photos = PhotoSerializer.annotate_photos( photos, @@ -852,7 +852,7 @@ class RephotoUpload(APIView): permission_classes = (AllowAny,) authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication) - def post(self, request, format=None): + def post(self, request): print('rephotoupload', file=sys.stderr) form = forms.ApiPhotoUploadForm(request.POST, request.FILES) @@ -1022,7 +1022,7 @@ class RephotoUploadSettings(AjapaikAPIView): API endpoint for saving rephoto upload settings ''' - def post(self, request, format=None): + def post(self, request): try: profile = request.user.profile profile.wikimedia_commons_rephoto_upload_consent = request.POST['wikimedia_commons_rephoto_upload_consent'] @@ -1388,14 +1388,14 @@ def _handle_request(self, data, user, request): 'albums': [] }) - def post(self, request, format=None): + def post(self, request): user = request.user or None body = request.body post = self._fix_latin1_query_param(request, body) return self._handle_request(post, user, request) - def get(self, request, format=None): + def get(self, request): user = request.user or None return self._handle_request(request.GET, user, request) @@ -1580,7 +1580,7 @@ class SubmitSimilarPhotos(AjapaikAPIView): API endpoint for posting similar photos. ''' - def post(self, request, format=None): + def post(self, request): points = 0 profile = request.user.profile data = json.loads(request.body.decode('utf-8')) @@ -1616,7 +1616,7 @@ class Transcriptions(AjapaikAPIView): API endpoint for getting transcriptions for an image. ''' - def get(self, request, photo_id, format=None): + def get(self, request, photo_id): transcriptions = Transcription.objects.filter(photo_id=photo_id).order_by('-created').values() ids = transcriptions.values_list('id', flat=True) feedback = TranscriptionFeedback.objects.filter(transcription_id__in=ids) @@ -1634,7 +1634,7 @@ def feedback_count(elem): data = {'transcriptions': sorted(list(transcriptions), key=feedback_count, reverse=True)} return JsonResponse(data, safe=False) - def post(self, request, format=None): + def post(self, request): try: photo = get_object_or_404(Photo, id=request.POST['photo']) user = get_object_or_404(Profile, pk=request.user.profile.id) @@ -1687,7 +1687,7 @@ class SubmitTranscriptionFeedback(AjapaikAPIView): API endpoint for confirming transcription for an image. ''' - def post(self, request, format=None): + def post(self, request): try: if TranscriptionFeedback.objects.filter(transcription_id=request.POST['id'], user_id=request.user.profile.id).exists(): @@ -1707,7 +1707,7 @@ class UserSettings(AjapaikAPIView): API endpoint for saving user settings ''' - def post(self, request, format=None): + def post(self, request): try: profile = request.user.profile profile.preferred_language = request.POST['preferredLanguage'] @@ -1723,7 +1723,7 @@ class ChangeProfileDisplayName(AjapaikAPIView): API endpoint for changing user display name ''' - def post(self, request, format=None): + def post(self, request): try: profile = request.user.profile profile.display_name = request.POST['display_name'] @@ -1741,7 +1741,7 @@ class PhotoSuggestion(AjapaikAPIView): API endpoints for getting photo scene category and updating it ''' - def get(self, request, photo_id, format=None): + def get(self, request, photo_id): try: if request.user.is_anonymous: return JsonResponse({'error': PLEASE_LOGIN}, status=401) @@ -1788,7 +1788,7 @@ def get(self, request, photo_id, format=None): except: # noqa return JsonResponse({'error': _('Something went wrong')}, status=500) - def post(self, request, format=None): + def post(self, request): profile = request.user.profile data = json.loads(request.body.decode('utf-8')) scene = data['scene'] @@ -1848,7 +1848,7 @@ class PhotoAppliedOperations(AjapaikAPIView): API endpoints for getting photo scene category and updating it ''' - def get(self, request, photo_id, format=None): + def get(self, request, photo_id): try: if request.user.is_anonymous: return JsonResponse({'error': PLEASE_LOGIN}, status=401) @@ -1899,7 +1899,7 @@ def get(self, request, photo_id, format=None): except: # noqa return JsonResponse({'error': _('Something went wrong')}, status=500) - def post(self, request, format=None): + def post(self, request): profile = request.user.profile data = json.loads(request.body.decode('utf-8')) flip = data['flip'] @@ -1927,6 +1927,7 @@ def post(self, request, format=None): photo_flip_suggestions = [] photo_rotated_suggestions = [] photo_invert_suggestions = [] + original_rotation = 0 for photo_id in photo_ids: if not photo_id.isdigit(): @@ -1975,5 +1976,6 @@ def post(self, request, format=None): PhotoFlipSuggestion.objects.bulk_create(photo_flip_suggestions) PhotoInvertSuggestion.objects.bulk_create(photo_invert_suggestions) PhotoRotationSuggestion.objects.bulk_create(photo_rotated_suggestions) + return JsonResponse({'message': response, 'rotated_by_90': (was_rotate_successful and abs(rotated - original_rotation) % 180 == 90)}) diff --git a/ajapaik/ajapaik/forms.py b/ajapaik/ajapaik/forms.py index 2328e2f53..f95b2c4db 100644 --- a/ajapaik/ajapaik/forms.py +++ b/ajapaik/ajapaik/forms.py @@ -154,6 +154,8 @@ class GalleryFilteringForm(forms.Form): square = forms.BooleanField(initial=False, required=False) landscape = forms.BooleanField(initial=False, required=False) panoramic = forms.BooleanField(initial=False, required=False) + date_from = forms.DateField(initial=None, required=False) + date_to = forms.DateField(initial=None, required=False) def clean_page(self): page = self.cleaned_data['page'] diff --git a/ajapaik/ajapaik/static/js/ajp-core.js b/ajapaik/ajapaik/static/js/ajp-core.js index f813cca3f..f21609171 100644 --- a/ajapaik/ajapaik/static/js/ajp-core.js +++ b/ajapaik/ajapaik/static/js/ajp-core.js @@ -66,6 +66,8 @@ window.galleryFilters = [ 'square', 'landscape', 'panoramic', + 'date_from', + 'date_to', ]; window.albumFilters = ['film', 'collections', 'people']; @@ -457,6 +459,58 @@ $('.ajp-navbar').autoHidingNavbar(); }, ); + $(document).on( + 'click', + '#removeDateFilters', + function(e) { + e.preventDefault(); + let uri = URI(window.location); + + if (uri.query().indexOf('date_from') > -1) { + uri.removeQuery('date_from'); + } + + if (uri.query().indexOf('date_to') > -1) { + uri.removeQuery('date_to'); + } + + window.location.href = uri; + }, + ); + + $(document).on( + 'click', + '#applyDateFilters', + function(e) { + e.preventDefault(); + let uri = URI(window.location); + let dateFromValue = document.getElementById('startingFrom').innerText; + let dateFrom = dateFromValue ? new Date(dateFromValue).toISOString().substring(0, 10) : null; + + if (uri.query().indexOf('date_to') > -1) { + uri.removeQuery('date_to'); + } + if (uri.query().indexOf('date_from') > -1) { + uri.removeQuery('date_from'); + } + + if (dateFrom !== null) { + uri.addQuery('date_from', dateFrom); + } + + let dateToValue = document.getElementById('endingAt').innerText; + let dateTo = dateToValue ? new Date(dateToValue, 11, 31, 23, 59, 59).toISOString().substring(0, 10) : null; + + + if (dateTo !== null) { + uri.addQuery('date_to', dateTo); + } + + window.location.href = uri; + }, + ); + + handleGeolocation = function(position) { $('#ajp-geolocation-error').hide(); window.location.href = @@ -2347,5 +2401,37 @@ $('.ajp-navbar').autoHidingNavbar(); } window.positionMinimapCTAButton(); }); + + function getVals() { + // Get slider values + var parent = this.parentNode; + var slides = parent.getElementsByTagName('input'); + var slide1 = parseFloat(slides[0].value); + var slide2 = parseFloat(slides[1].value); + // Neither slider will clip the other, so make sure we determine which is larger + if (slide1 > slide2) { + var tmp = slide2; + slide2 = slide1; + slide1 = tmp; + } + + var displayElement = parent.getElementsByClassName('rangeValues')[0]; + displayElement.innerHTML = slide1 + ' - ' + slide2; + } + + window.onload = function() { + // Initialize Sliders + var sliderSections = document.getElementsByClassName('range-slider'); + for (var x = 0; x < sliderSections.length; x++) { + var sliders = sliderSections[x].getElementsByTagName('input'); + for (var y = 0; y < sliders.length; y++) { + if (sliders[y].type === 'range') { + sliders[y].oninput = getVals; + // Manually trigger event first time to display values + sliders[y].oninput(); + } + } + } + }; } })(jQuery); diff --git a/ajapaik/ajapaik/static/js/ajp-frontpage.js b/ajapaik/ajapaik/static/js/ajp-frontpage.js index d272a6a7d..1efe8d813 100644 --- a/ajapaik/ajapaik/static/js/ajp-frontpage.js +++ b/ajapaik/ajapaik/static/js/ajp-frontpage.js @@ -63,7 +63,7 @@ }); }, syncStateToUrl = function() { - const currentUrl = window.URI(window.location.href); + let currentUrl = window.URI(window.location.href); currentUrl .removeSearch('photo') .removeSearch('page') @@ -535,6 +535,8 @@ categoryMessage = 'No rephotos were found'; } else if (window.location.search.indexOf('myLikes=1') > 0) { categoryMessage = 'No liked pictures were found'; + } else if (window.location.search.indexOf('dateFrom=') > 0 || window.location.search.indexOf('date=') > 0) { + categoryMessage = 'No pictures were found in date range'; } else { categoryMessage = 'No pictures were found'; } diff --git a/ajapaik/ajapaik/static/js/constants.js b/ajapaik/ajapaik/static/js/constants.js index 800ca5130..a3c9d95ff 100644 --- a/ajapaik/ajapaik/static/js/constants.js +++ b/ajapaik/ajapaik/static/js/constants.js @@ -1,149 +1,149 @@ 'use strict'; var constants = { - keyCodes: { - ESCAPE: 27, - D: 68, - ARROW_RIGHT: 39, - ARROW_LEFT: 37, - }, - fieldValues: { - common: { - UNSURE: 'UNSURE', + keyCodes: { + ESCAPE: 27, + D: 68, + ARROW_RIGHT: 39, + ARROW_LEFT: 37, }, - genders: { - MALE: 'MALE', - FEMALE: 'FEMALE', + fieldValues: { + common: { + UNSURE: 'UNSURE', + }, + genders: { + MALE: 'MALE', + FEMALE: 'FEMALE', + }, + ageGroups: { + CHILD: 'CHILD', + ADULT: 'ADULT', + ELDERLY: 'ELDERLY', + }, }, - ageGroups: { - CHILD: 'CHILD', - ADULT: 'ADULT', - ELDERLY: 'ELDERLY', + elements: { + NEW_OBJECT_SELECT_FIELDS_GROUP_WRAPPER_ID: + 'new-object-select-fields-wrapper-id', + ANNOTATION_MORE_SPECIFIC_FIELDS_WRAPPER_ID: + 'more-specific-annotation-fields-wrapper', + AUTOCOMPLETE_WRAPPER_ID: 'autocomplete-wrapper', + SUBJECT_AUTOCOMPLETE_ID: 'autocomplete-subject', + SUBJECT_GENDER_SUGGESTION_COMPONENT_ID: 'person-popover-gender-suggestion', + SUBJECT_AGE_GROUP_SUGGESTION_COMPONENT_ID: + 'person-popover-age-group-suggestion', + ADD_NEW_FACE_FIELDS_WRAPPER_ID: 'add-new-subject-fields-wrapper', + ADD_NEW_SUBJECT_LINK_ID: 'add-new-subject', + POPOVER_CONTROL_BUTTONS_ID: 'control-buttons', + OBJECT_CLASS_SELECT_ID: 'select-object-class', + SELECT_OBJECT_CLASS_WRAPPER_ID: 'select-object-class-wrapper', + NEW_ANNOTATION_FORM_ID: 'add-object-class', + IMAGE_SELECTION_AREA_ID: 'image-selection', + IMAGE_SELECTION_OVERLAY_ID: 'image-selection-overlay', + FACE_ANNOTATIONS_ID: 'person-annotations', + OBJECT_ANNOTATIONS_ID: 'object-annotations', + ANNOTATION_CONTAINER_ID_ON_IMAGE: 'annotation-container', }, - }, - elements: { - NEW_OBJECT_SELECT_FIELDS_GROUP_WRAPPER_ID: - 'new-object-select-fields-wrapper-id', - ANNOTATION_MORE_SPECIFIC_FIELDS_WRAPPER_ID: - 'more-specific-annotation-fields-wrapper', - AUTOCOMPLETE_WRAPPER_ID: 'autocomplete-wrapper', - SUBJECT_AUTOCOMPLETE_ID: 'autocomplete-subject', - SUBJECT_GENDER_SUGGESTION_COMPONENT_ID: 'person-popover-gender-suggestion', - SUBJECT_AGE_GROUP_SUGGESTION_COMPONENT_ID: - 'person-popover-age-group-suggestion', - ADD_NEW_FACE_FIELDS_WRAPPER_ID: 'add-new-subject-fields-wrapper', - ADD_NEW_SUBJECT_LINK_ID: 'add-new-subject', - POPOVER_CONTROL_BUTTONS_ID: 'control-buttons', - OBJECT_CLASS_SELECT_ID: 'select-object-class', - SELECT_OBJECT_CLASS_WRAPPER_ID: 'select-object-class-wrapper', - NEW_ANNOTATION_FORM_ID: 'add-object-class', - IMAGE_SELECTION_AREA_ID: 'image-selection', - IMAGE_SELECTION_OVERLAY_ID: 'image-selection-overlay', - FACE_ANNOTATIONS_ID: 'person-annotations', - OBJECT_ANNOTATIONS_ID: 'object-annotations', - ANNOTATION_CONTAINER_ID_ON_IMAGE: 'annotation-container', - }, - translations: { - annotations: { - INFORM_HOW_TO_ANNOTATE: gettext( - "Click (don't drag) to start drawing the annotation. Click again to finish drawing." - ), + translations: { + annotations: { + INFORM_HOW_TO_ANNOTATE: gettext( + 'Click (don\'t drag) to start drawing the annotation. Click again to finish drawing.', + ), + }, + errors: { + OBJECT_REQUIRED: gettext('Object is required'), + }, + common: { + OPTIONAL: gettext('optional'), + UNIDENTIFIED: gettext('Unidentified'), + MALE: gettext('Male'), + FEMALE: gettext('Female'), + CHILD: gettext('Child'), + ELDERLY: gettext('Elderly'), + ADULT: gettext('Adult'), + }, + button: { + CANCEL: gettext('Cancel'), + DELETE: gettext('Delete'), + SUBMIT: gettext('Submit'), + }, + popover: { + titles: { + NEW_ANNOTATION: gettext('What is displayedsss'), + EDIT_FACE_ANNOTATION: gettext('Edit face annotation'), + EDIT_OBJECT_ANNOTATION: gettext('Edit object annotation'), + ADD_FEEDBACK: gettext('Add feedback'), + }, + labels: { + CHANGE_PERSON_NAME: gettext('Change person name'), + CHANGE_OBJECT_CLASS: gettext('Change object class'), + FACE_ANNOTATION: gettext('Face'), + OBJECT_ANNOTATION: gettext('Object'), + }, + }, + queries: { + GET_ANNOTATION_CLASSES_FAILED: gettext( + 'Failed to load object annotation classes', + ), + GET_ANNOTATIONS_FAILED: gettext('Failed to load annotations'), + ADD_OBJECT_ANNOTATION_SUCCESS: gettext( + 'Successfully added object annotation', + ), + ADD_OBJECT_ANNOTATION_FAILED: gettext('Unable to save object annotation'), + UPDATE_OBJECT_ANNOTATION_SUCCESS: gettext( + 'Successfully updated object annotation', + ), + UPDATE_OBJECT_ANNOTATION_FAILED: gettext( + 'Unable to update object annotation', + ), + ADD_OBJECT_ANNOTATION_FEEDBACK_SUCCESS: gettext( + 'Successfully added object annotation feedback', + ), + ADD_OBJECT_ANNOTATION_FEEDBACK_FAILED: gettext( + 'Failed to add object annotation feedback', + ), + REMOVE_OBJECT_ANNOTATION_SUCCESS: gettext( + 'Successfully removed object annotation', + ), + REMOVE_OBJECT_ANNOTATION_FAILED: gettext( + 'Unable to remove object annotation', + ), + ADD_FACE_ANNOTATION_SUCCESS: gettext( + 'Successfully added face annotation', + ), + ADD_FACE_ANNOTATION_FAILED: gettext('Unable to save face annotation'), + UPDATE_FACE_ANNOTATION_SUCCESS: gettext( + 'Successfully edited face annotation', + ), + UPDATE_FACE_ANNOTATION_FAILED: gettext( + 'Failed to save face annotation edit', + ), + REMOVE_FACE_ANNOTATION_SUCCESS: gettext( + 'Successfully removed face annotation', + ), + REMOVE_FACE_ANNOTATION_FAILED: gettext( + 'Failed to remove face annotation', + ), + }, + autocomplete: { + objectSearch: { + PLACEHOLDER: gettext('Find object'), + SEARCHING_TEXT: gettext('Searching'), + SEARCH_PLACEHOLDER: gettext('Search for object'), + MIN_CHARACTERS_NEEDED: gettext('Need 2 characters'), + NO_RESULTS_FOUND: gettext('No results found'), + }, + subjectSearch: { + PLACEHOLDER: gettext('Find existing person'), + SEARCHING_TEXT: gettext('Searching'), + SEARCH_PLACEHOLDER: gettext('Enter person name'), + MIN_CHARACTERS_NEEDED: gettext('Need 2 characters'), + NO_RESULTS_TEXT: gettext('No results found'), + ADD_NEW_PERSON: gettext('Add new person'), + }, + label: { + ADD_NEW_PERSON: gettext('Add new person'), + SPECIFY_NAME: gettext('Specify person name'), + }, + }, }, - errors: { - OBJECT_REQUIRED: gettext('Object is required'), - }, - common: { - OPTIONAL: gettext('optional'), - UNIDENTIFIED: gettext('Unidentified'), - MALE: gettext('Male'), - FEMALE: gettext('Female'), - CHILD: gettext('Child'), - ELDERLY: gettext('Elderly'), - ADULT: gettext('Adult'), - }, - button: { - CANCEL: gettext('Cancel'), - DELETE: gettext('Delete'), - SUBMIT: gettext('Submit'), - }, - popover: { - titles: { - NEW_ANNOTATION: gettext('What is displayed'), - EDIT_FACE_ANNOTATION: gettext('Edit face annotation'), - EDIT_OBJECT_ANNOTATION: gettext('Edit object annotation'), - ADD_FEEDBACK: gettext('Add feedback'), - }, - labels: { - CHANGE_PERSON_NAME: gettext('Change person name'), - CHANGE_OBJECT_CLASS: gettext('Change object class'), - FACE_ANNOTATION: gettext('Face'), - OBJECT_ANNOTATION: gettext('Object'), - }, - }, - queries: { - GET_ANNOTATION_CLASSES_FAILED: gettext( - 'Failed to load object annotation classes' - ), - GET_ANNOTATIONS_FAILED: gettext('Failed to load annotations'), - ADD_OBJECT_ANNOTATION_SUCCESS: gettext( - 'Successfully added object annotation' - ), - ADD_OBJECT_ANNOTATION_FAILED: gettext('Unable to save object annotation'), - UPDATE_OBJECT_ANNOTATION_SUCCESS: gettext( - 'Successfully updated object annotation' - ), - UPDATE_OBJECT_ANNOTATION_FAILED: gettext( - 'Unable to update object annotation' - ), - ADD_OBJECT_ANNOTATION_FEEDBACK_SUCCESS: gettext( - 'Successfully added object annotation feedback' - ), - ADD_OBJECT_ANNOTATION_FEEDBACK_FAILED: gettext( - 'Failed to add object annotation feedback' - ), - REMOVE_OBJECT_ANNOTATION_SUCCESS: gettext( - 'Successfully removed object annotation' - ), - REMOVE_OBJECT_ANNOTATION_FAILED: gettext( - 'Unable to remove object annotation' - ), - ADD_FACE_ANNOTATION_SUCCESS: gettext( - 'Successfully added face annotation' - ), - ADD_FACE_ANNOTATION_FAILED: gettext('Unable to save face annotation'), - UPDATE_FACE_ANNOTATION_SUCCESS: gettext( - 'Successfully edited face annotation' - ), - UPDATE_FACE_ANNOTATION_FAILED: gettext( - 'Failed to save face annotation edit' - ), - REMOVE_FACE_ANNOTATION_SUCCESS: gettext( - 'Successfully removed face annotation' - ), - REMOVE_FACE_ANNOTATION_FAILED: gettext( - 'Failed to remove face annotation' - ), - }, - autocomplete: { - objectSearch: { - PLACEHOLDER: gettext('Find object'), - SEARCHING_TEXT: gettext('Searching'), - SEARCH_PLACEHOLDER: gettext('Search for object'), - MIN_CHARACTERS_NEEDED: gettext('Need 2 characters'), - NO_RESULTS_FOUND: gettext('No results found'), - }, - subjectSearch: { - PLACEHOLDER: gettext('Find existing person'), - SEARCHING_TEXT: gettext('Searching'), - SEARCH_PLACEHOLDER: gettext('Enter person name'), - MIN_CHARACTERS_NEEDED: gettext('Need 2 characters'), - NO_RESULTS_TEXT: gettext('No results found'), - ADD_NEW_PERSON: gettext('Add new person'), - }, - label: { - ADD_NEW_PERSON: gettext('Add new person'), - SPECIFY_NAME: gettext('Specify person name'), - }, - }, - }, }; diff --git a/ajapaik/ajapaik/static/js/photoview/annotations.js b/ajapaik/ajapaik/static/js/photoview/annotations.js index fac902dfe..ead292656 100644 --- a/ajapaik/ajapaik/static/js/photoview/annotations.js +++ b/ajapaik/ajapaik/static/js/photoview/annotations.js @@ -5,18 +5,11 @@ function getCorrespondingAnnotations(annotationIdentifier) { return $(annotationsSelector); } -function openAnnotationRectanglePopover(id) { - if (!$('#modify-detected-object-annotation').is(":visible")) { - setTimeout(() => { $('#ajp-face-modify-rectangle-' + id).click(); }, 10); - $('#ajp-face-modify-rectangle-' + id).css('visibility', 'visible'); - } -} - function getDisplayCorrespondingAnnotation(annotationIdentifier) { if (!window.isAnnotatingDisabled) { hideAnnotationsWithoutOpenPopover(); let correspondingAnnotations = getCorrespondingAnnotations(annotationIdentifier); - correspondingAnnotations.css({visibility: ''}); + correspondingAnnotations.css({ visibility: '' }); } } @@ -24,24 +17,24 @@ function getHideCorrespondingAnnotation(annotationIdentifier) { if ((!window.openPersonPopoverLabelIds || !window.openPersonPopoverLabelIds.includes(annotationIdentifier)) && (!window.openObjectPopoverLabelIds || !window.openObjectPopoverLabelIds.includes(annotationIdentifier))) { let correspondingAnnotations = getCorrespondingAnnotations(annotationIdentifier); - correspondingAnnotations.css({visibility: 'hidden'}); + correspondingAnnotations.css({ visibility: 'hidden' }); } } function togglePersonAnnotationLabelPopover(event, annotation, faceAnnotations) { event.preventDefault(); if (!window.isAnnotatingDisabled) { - let popoverTarget = $(event.target).data("bs.popover") === undefined + let popoverTarget = $(event.target).data('bs.popover') === undefined ? $(event.target).parents('[data-toggle="popover"]') : $(event.target); - + if (popoverTarget.attr('aria-describedby') == undefined) { - $('.ajp-person-label-popover').not('[id=' + popoverTarget.attr('aria-describedby') +']').popover('hide'); + $('.ajp-person-label-popover').not('[id=' + popoverTarget.attr('aria-describedby') + ']').popover('hide'); popoverTarget.popover('show'); $('[id=' + popoverTarget.attr('aria-describedby') + ']').addClass('ajp-person-label-popover'); if (annotation.isAlbum) { displayAnnotations(true, false); - window.openPersonPopoverLabelIds = faceAnnotations.filter(fa=>fa!==null).map(fa=>getAnnotationIdentifier(fa)); + window.openPersonPopoverLabelIds = faceAnnotations.filter(fa => fa !== null).map(fa => getAnnotationIdentifier(fa)); } else { window.openPersonPopoverLabelIds = [getAnnotationIdentifier(annotation)]; $('#ajp-face-modify-rectangle-' + annotation.id).css('visibility', 'visible'); @@ -57,12 +50,12 @@ function togglePersonAnnotationLabelPopover(event, annotation, faceAnnotations) function toggleObjectAnnotationLabelPopover(event, annotation) { event.preventDefault(); if (!window.isAnnotatingDisabled) { - let popoverTarget = $(event.target).data("bs.popover") === undefined + let popoverTarget = $(event.target).data('bs.popover') === undefined ? $(event.target).parents('[data-toggle="popover"]') : $(event.target); - + if (popoverTarget.attr('aria-describedby') == undefined) { - $('.ajp-object-label-popover').not('[id=' + popoverTarget.attr('aria-describedby') +']').popover('hide'); + $('.ajp-object-label-popover').not('[id=' + popoverTarget.attr('aria-describedby') + ']').popover('hide'); popoverTarget.popover('show'); $('[id=' + popoverTarget.attr('aria-describedby') + ']').addClass('ajp-object-label-popover'); window.openObjectPopoverLabelIds = [getAnnotationIdentifier(annotation)]; @@ -79,16 +72,16 @@ function createIconButton(title, iconText, spanText, action) { let button = $(' + +
+ +
+ + - +
  • + + + + + + +
  • +
  • + + + + + + +
  • +
  • + + + + + + +
  • +
  • + + + + + + +
  • +
  • + + + + + + +
  • + + {% endif %} diff --git a/ajapaik/ajapaik/views.py b/ajapaik/ajapaik/views.py index a8027928a..fc1a45de0 100644 --- a/ajapaik/ajapaik/views.py +++ b/ajapaik/ajapaik/views.py @@ -35,7 +35,7 @@ AlbumSelectionFilteringForm, CuratorWholeSetAlbumsSelectionForm from ajapaik.ajapaik.models import Photo, GeoTag, Points, \ Album, AlbumPhoto, Area, Licence, \ - MuisCollection, PhotoLike, ImageSimilarity, get_pseudo_slug_for_photo + MuisCollection, PhotoLike, ImageSimilarity, get_pseudo_slug_for_photo, Dating from ajapaik.ajapaik.serializers import FrontpageAlbumSerializer, DatingSerializer, \ VideoSerializer, PhotoMapMarkerSerializer from ajapaik.ajapaik.stats_sql import AlbumStats @@ -359,7 +359,7 @@ def frontpage_async_albums(request): def _get_filtered_data_for_frontpage(request, album_id=None, page_override=None): - starttime = time() + start_time = time() profile = request.get_user().profile photos = Photo.objects.filter(rephoto_of__isnull=True) filter_form = GalleryFilteringForm(request.GET) @@ -409,7 +409,7 @@ def _get_filtered_data_for_frontpage(request, album_id=None, page_override=None) context['photos_with_similar_photos'] = None context['show_photos'] = None context['is_photoset'] = None - context['execution_time'] = str(time() - starttime) + context['execution_time'] = str(time() - start_time) return context else: show_photos = True @@ -438,6 +438,11 @@ def _get_filtered_data_for_frontpage(request, album_id=None, page_override=None) # multiple times in results so this needs to be distinct(). Distinct is slow. photos = photos.distinct() + date_from = filter_form.cleaned_data["date_from"] + date_to = filter_form.cleaned_data["date_to"] + if date_from or date_to: + photos = photos.exclude(datings=None).select_related("datings") + if filter_form.cleaned_data['people']: photos = photos.filter(face_recognition_rectangles__isnull=False, face_recognition_rectangles__deleted__isnull=True) @@ -475,6 +480,18 @@ def _get_filtered_data_for_frontpage(request, album_id=None, page_override=None) photos = photos.filter(likes__profile=profile) if rephotos_by_id: photos = photos.filter(rephotos__user_id=rephotos_by_id) + + if date_from or date_to: + datings = Dating.objects.filter(photo_id__in=photos.values_list("id", flat=True)) + + if date_from: + datings = datings.filter(start__gte=date_from) + + if date_to: + datings = datings.filter(end__lte=date_to) + + photos = photos.filter(id__in=datings.values_list("photo_id", flat=True)) + photos_with_comments = None photos_with_rephotos = None photos_with_similar_photos = None @@ -766,7 +783,7 @@ def _get_filtered_data_for_frontpage(request, album_id=None, page_override=None) context['show_photos'] = False context['max_page'] = ceil(float(context['total']) / float(page_size)) - context['execution_time'] = str(time() - starttime) + context['execution_time'] = str(time() - start_time) return context