darklow / django-suit

Modern theme for Django admin interface
http://djangosuit.com/
Other
2.32k stars 703 forks source link

Feature request: Smarter inline editing #578

Open beruic opened 7 years ago

beruic commented 7 years ago

It would be awesome if you could edit an inline object by unfolding it or opening it in a modal.

darklow commented 7 years ago

Why don't you use tabs instead? http://v2.djangosuit.com/admin/demo/country/170/change/#cities

beruic commented 7 years ago

How would I do that? It makes no sense to me right now.

I have an inline with a bunch of complex objects with many fields. The only thing I allow editing inline is the order (using suits SortableTabularInline). I don't show the admin page for these inlines either, they are only accessible through the inline, but they are hard to edit inline, so therefor I must either be able to unfold every inline, or have a link for every inline that makes a popup or modal.

The admin panel supports making a popup when doing this on for example a foreign key field, and right now I'm working on a solution with a popup, but the usability would be so much better with a modal or folding.

darklow commented 7 years ago

Modal would require handling extra routes for loading and saving data, so I will not implement such feature.

Popups are much better solution and you can already make popups by yourself, I have shown this approach previously and you don't need to have special support for it. Kind of inlines in inlines solution/workaround.

This is 100% valid solution using only Django admin templates to achieve this. I am planning to include this example in the demo app to show how it could be done. Here is a preview of stacked inline which has more related items in it: image

Popup once you click "Edit related": image

beruic commented 7 years ago

For the modal, I was thinking it could be achieved with the popup-content in an iframe. Do you think that is possible?

darklow commented 7 years ago

Sure it is possible, but there are so many ways different users would like to handle it, I don't see big point of adding it as a feature, it can be very easily made just by one read only field which holds link Edit and opens according popup.

darklow commented 7 years ago

Only thing than may be handy and universal is readonly field widget which would open edit modal, that is the only shortcut I find useful enough to consider.

beruic commented 7 years ago

I agree that would be very helpful. One for deleting would be nice too. If I had that and an inline extension to make the add form open in a popup as well, I could easily get around what I am working on now.

Perhaps you can use some of this template for it:

{% load admin_urls static misc %}
{% with obj|lookup:'_meta' as obj_meta %}
  <a href="{% url obj_meta|admin_urlname:'change' obj.pk %}?_popup=1"
     class="related-widget-wrapper-link change-related"
     id="change_related_{{obj_meta.app_label}}_{{obj_meta.model_name}}_{{ obj.pk }}"
  >
    {# This content is a fall back. It is replaced by django-suit because of the change-related class. #}
    <img src="{% static 'admin/img/icon_changelink.gif' %}" width="10" height="10" alt="Edit">
  </a>
  <div style="display: none; visibility: collapse">
    <select id="related_{{obj_meta.app_label}}_{{obj_meta.model_name}}_{{ obj.pk }}" disabled>
      <option selected id="related_{{obj_meta.app_label}}_{{obj_meta.model_name}}_{{ obj.pk }}_trigger_option" value="{{ obj.pk }}"></option>
    </select>
    <script>
        $("#related_{{obj_meta.app_label}}_{{obj_meta.model_name}}_{{ obj.pk }}_trigger_option").bind("DOMSubtreeModified", function (e) {
            {% if submit_action == "reload" %}
                window.location = window.location;
            {% elif submit_action == "replace_summary" %} {# Suggestion to what could also be done #}
                console.log("Replacing summary is not implemented");
            {% endif %}
        })
    </script>
  </div>
{% endwith %}
beruic commented 7 years ago

The reason for the obj.id is to make it inline compatible

beruic commented 7 years ago

Oh, my lookup filter is

@register.filter
def lookup(obj, key):
    """Gets an attribute of an object dynamically from a string name"""
    if hasattr(obj, str(key)):
        return getattr(obj, key)
    elif hasattr(obj, '__contains__') and key in obj:
        return obj[key]
    else:
        return None
darklow commented 7 years ago

Could you please post screenshot of your code in action?

beruic commented 7 years ago

Inline field function:

    def edit_link(self, obj):
        html = render_to_string(
            'admin/include/popup_editor_link.html',
            context={
                'obj': obj,
                'submit_action': 'reload',
            }
        )
        return html
    edit_link.short_description = _('edit')
    edit_link.allow_tags = True
beruic commented 7 years ago

Screenshot skaermbillede fra 2017-03-01 16-05-02

BTW, please notice the error with the sorting arrows. Is this a known issue?

beruic commented 7 years ago

FYI: I already posted issue #569 regarding the arrows