diff --git a/accounts/urls.py b/accounts/urls.py index 7b42fc756..3821d3b6e 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -95,6 +95,8 @@ path('bookmarks/get_form_for_sound//', bookmarks.get_form_for_sound, name="bookmarks-add-form-for-sound"), path('bookmarks/category//delete/', bookmarks.delete_bookmark_category, name="delete-bookmark-category"), path('bookmarks//delete/', bookmarks.delete_bookmark, name="delete-bookmark"), + path('bookmarks/category//edit_modal/', bookmarks.edit_bookmark_category, name="edit-bookmark-category"), + path('messages/', messages.inbox, name='messages'), path('messages/sent/', messages.sent_messages, name='messages-sent'), diff --git a/bookmarks/forms.py b/bookmarks/forms.py index 478327554..c1aa1786a 100644 --- a/bookmarks/forms.py +++ b/bookmarks/forms.py @@ -30,7 +30,15 @@ class Meta: widgets = { 'name': forms.TextInput(attrs={'class': 'category_name_widget'}), } + + def clean(self): + cleaned_data = super().clean() + name = self.cleaned_data.get("name", ) + if BookmarkCategory.objects.filter(user=self.instance.user, name=name).exists(): + raise forms.ValidationError("This name already exists for a bookmark category") + + return cleaned_data class BookmarkForm(forms.Form): category = forms.ChoiceField( diff --git a/bookmarks/views.py b/bookmarks/views.py index 75dbd625a..95fc298a5 100755 --- a/bookmarks/views.py +++ b/bookmarks/views.py @@ -27,7 +27,7 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse -from bookmarks.forms import BookmarkForm +from bookmarks.forms import BookmarkForm, BookmarkCategoryForm from bookmarks.models import Bookmark, BookmarkCategory from sounds.models import Sound from utils.pagination import paginate @@ -85,6 +85,33 @@ def delete_bookmark_category(request, category_id): return HttpResponseRedirect(reverse("bookmarks-for-user", args=[request.user.username])) +@transaction.atomic() +def edit_bookmark_category(request, category_id): + + if not request.GET.get('ajax'): + return HttpResponseRedirect(reverse("bookmarks-for-user", args=[request.user.username])) + + category = get_object_or_404(BookmarkCategory, id=category_id, user=request.user) + + if request.method == "POST": + edit_form = BookmarkCategoryForm(request.POST, instance=category) + print(edit_form.is_bound) + if edit_form.is_valid(): + category.name = edit_form.cleaned_data["name"] + category.save() + return JsonResponse({"success":True}) + if not edit_form.is_valid(): + print(edit_form.errors.as_json()) + else: + initial = {"name":category.name} + edit_form = BookmarkCategoryForm(initial=initial) + + tvars = {"category": category, + "form": edit_form} + return render(request, 'bookmarks/modal_edit_bookmark_category.html', tvars) + + + @login_required @transaction.atomic() def add_bookmark(request, sound_id): diff --git a/freesound/static/bw-frontend/src/components/loginModals.js b/freesound/static/bw-frontend/src/components/loginModals.js index 46d16cffd..ed6e1800c 100644 --- a/freesound/static/bw-frontend/src/components/loginModals.js +++ b/freesound/static/bw-frontend/src/components/loginModals.js @@ -129,7 +129,7 @@ const handleRegistrationModal = () => { // If registration succeeded, redirect to the registration feedback page const data = JSON.parse(req.responseText); window.location.href = data.redirectURL; - }, undefined); + }, undefined, undefined); } const handleRegistrationFeedbackModal = () => { diff --git a/freesound/static/bw-frontend/src/components/modal.js b/freesound/static/bw-frontend/src/components/modal.js index 32738a00a..af5700d58 100644 --- a/freesound/static/bw-frontend/src/components/modal.js +++ b/freesound/static/bw-frontend/src/components/modal.js @@ -85,19 +85,22 @@ const bindConfirmationModalElements = (container) => { // Logic to bind default modals -const handleDefaultModal = (modalUrl, modalActivationParam, atPage) => { - if ((atPage !== undefined) && modalUrl.indexOf('&page') == -1){ - modalUrl += '&page=' + atPage; - } +const handleDefaultModal = (modalUrl, modalActivationParam) => { handleGenericModal(modalUrl, undefined, undefined, true, true, modalActivationParam); } +const handleDefaultModalWithForm = (modalUrl, modalActivationParam) => { + handleGenericModalWithForm(modalUrl, undefined, undefined, (req) => {showToast('Form submitted succesfully!')}, undefined, true, true, modalActivationParam, true); +} + const bindDefaultModals = (container) => { bindModalActivationElements('[data-toggle="modal-default"]', handleDefaultModal, container); + bindModalActivationElements('[data-toggle="modal-default-with-form"]', handleDefaultModalWithForm, container); } const activateDefaultModalsIfParameters = () => { activateModalsIfParameters('[data-toggle="modal-default"]', handleDefaultModal); + activateModalsIfParameters('[data-toggle="modal-default-with-form"]', handleDefaultModalWithForm); } @@ -195,7 +198,7 @@ const handleGenericModal = (fetchContentUrl, onLoadedCallback, onClosedCallback, }; -const handleGenericModalWithForm = (fetchContentUrl, onLoadedCallback, onClosedCallback, onFormSubmissionSucceeded, onFormSubmissionError, doRequestAsync, showLoadingToast, modalActivationParam) => { +const handleGenericModalWithForm = (fetchContentUrl, onLoadedCallback, onClosedCallback, onFormSubmissionSucceeded, onFormSubmissionError, doRequestAsync, showLoadingToast, modalActivationParam, dataReloadOnSuccess) => { // This version of the generic modal is useful for modal contents that contain forms which, upon submission, will return HTML content if there were form errors // which should be used to replace the current contents of the form, and will return a JSON response if the form validated correctly in the backend. That JSON // response could include some relevant data or no data at all, but is used to differentiate from the HTML response @@ -218,6 +221,9 @@ const handleGenericModalWithForm = (fetchContentUrl, onLoadedCallback, onClosedC if (onFormSubmissionSucceeded !== undefined){ onFormSubmissionSucceeded(req); } + if(dataReloadOnSuccess == true){ + location.reload() + } } else { // If the response is not JSON, that means the response are the HTML elements of the // form (including error warnings) and we should replace current modal HTML with this one @@ -278,4 +284,4 @@ const handleGenericModalWithForm = (fetchContentUrl, onLoadedCallback, onClosedC }, onClosedCallback, doRequestAsync, showLoadingToast, modalActivationParam) } -export {activateModal, dismissModal, handleGenericModal, handleGenericModalWithForm, handleDefaultModal, bindModalActivationElements, bindConfirmationModalElements, activateModalsIfParameters, bindDefaultModals, activateDefaultModalsIfParameters}; +export {activateModal, dismissModal, handleGenericModal, handleGenericModalWithForm, handleDefaultModal, handleDefaultModalWithForm, bindModalActivationElements, bindConfirmationModalElements, activateModalsIfParameters, bindDefaultModals, activateDefaultModalsIfParameters}; diff --git a/freesound/static/bw-frontend/src/pages/sound.js b/freesound/static/bw-frontend/src/pages/sound.js index a3cebe1d9..9f3212c2c 100644 --- a/freesound/static/bw-frontend/src/pages/sound.js +++ b/freesound/static/bw-frontend/src/pages/sound.js @@ -137,7 +137,7 @@ const initSoundFlagForm = (modalContainer) => { } const handleFlagSoundModal = () => { - handleGenericModalWithForm(flagSoundButton.dataset.modalContentUrl, initSoundFlagForm, undefined, (req) => {showToast('Sound flagged successfully!')}, undefined); + handleGenericModalWithForm(flagSoundButton.dataset.modalContentUrl, initSoundFlagForm, undefined, (req) => {showToast('Sound flagged successfully!')}, undefined, undefined); } if (flagSoundModalParamValue) { diff --git a/templates/bookmarks/bookmarks.html b/templates/bookmarks/bookmarks.html index d6aa3a45b..29655befe 100644 --- a/templates/bookmarks/bookmarks.html +++ b/templates/bookmarks/bookmarks.html @@ -20,6 +20,7 @@

Bookmark categories

  • {{cat.name}} ยท {{cat.num_bookmarks|bw_intcomma}} bookmark{{ cat.num_bookmarks|pluralize }} {% if is_owner %} {% bw_icon 'trash' %} + {% bw_icon 'edit' %} {% endif %}
  • {% endfor %} @@ -39,7 +40,7 @@

    Category: {% if category %}{{category.n
    {% display_sound_small bookmark.sound %} {% if is_owner %} - + {% endif %}
    {% endfor %} diff --git a/templates/bookmarks/modal_edit_bookmark_category.html b/templates/bookmarks/modal_edit_bookmark_category.html new file mode 100644 index 000000000..120ea6663 --- /dev/null +++ b/templates/bookmarks/modal_edit_bookmark_category.html @@ -0,0 +1,21 @@ +{% extends "molecules/modal_base.html" %} +{% load util %} + +{% block id %}editBookMarkCategory{% endblock %} +{% block extra-class %}{% endblock %} +{% block aria-label %}Edit Bookmark Category{% endblock %} + +{% block body %} +
    +
    +

    Edit bookmark Category

    +
    {% csrf_token %} + {{form}} + +
    +
    +
    + +
    +
    +{% endblock %} \ No newline at end of file