Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: open edit file popup from file widget #1301

Merged
merged 24 commits into from Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
62bf814
feat: open edit file popup from file widget
fabien-michel Jul 27, 2022
0256544
fix: rename popup_response.js to filer_popup_response.js to ensure no…
fabien-michel Jul 28, 2022
9e00871
fix: minor
fabien-michel Jul 28, 2022
05c106b
chore: add edit from widget tests
fabien-michel Jul 28, 2022
5ba28c7
fix: clean-up file widget style
fabien-michel Jul 28, 2022
c15151b
Merge branch 'master' into edit_popup_from_widget
fabien-michel Jul 28, 2022
91cdc13
Merge branch 'master' into edit_popup_from_widget
fabien-michel Jul 28, 2022
cfa4f50
fix: mobile devices styling
fabien-michel Jul 28, 2022
3f10801
fix: hide edit file button when no file selected
fabien-michel Jul 29, 2022
c796f5e
Merge branch 'master' into edit_popup_from_widget
fabien-michel Sep 23, 2022
d6fe298
Merge branch 'master' into edit_popup_from_widget
fabien-michel May 31, 2023
05976ed
fix: lookup icon hidden on recent djangocms
fabien-michel May 31, 2023
d2b33af
style: format
fabien-michel May 31, 2023
c39a5f0
fix: missing updated compiled css
fabien-michel Jun 14, 2023
6d39221
Merge branch 'master' into edit_popup_from_widget
fabien-michel Jun 14, 2023
d45fd98
fix: jscs and jshint complaints
fabien-michel Jun 14, 2023
8dee52c
fix: legacyize code
fabien-michel Jun 14, 2023
1b1b31d
fix: restore const
fabien-michel Jun 14, 2023
4b747ab
fix: legacyize code again
fabien-michel Jun 14, 2023
30bebc0
fix: better ellipsis cut width + simplify css
fabien-michel Jun 15, 2023
d0e0ce6
fix: change choose and replace buttons icon
fabien-michel Jun 15, 2023
50accfd
test: add initial AdminFileWidget test
fabien-michel Jun 15, 2023
21e609f
Merge branch 'master' into edit_popup_from_widget
fabien-michel Jun 19, 2023
f585c1c
fix: consistent filer dropzone buttons margin left
fabien-michel Jun 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.rst
Expand Up @@ -2,6 +2,11 @@
CHANGELOG
=========

unreleased
==================

* Add an edit button to the file widget which open edit file popup

Unpublished
===========

Expand Down Expand Up @@ -121,7 +126,6 @@ Unpublished
* Fix #1247: Not owned files in unfiled folder can not be listed if perms are ON.
* Fix #1184: OSError close file before deletion on file move.


2.0.2 (2020-09-10)
==================

Expand Down
9 changes: 8 additions & 1 deletion filer/admin/fileadmin.py
Expand Up @@ -69,6 +69,7 @@ def response_change(self, request, obj):
and '_continue' not in request.POST
and '_saveasnew' not in request.POST
and '_addanother' not in request.POST
and '_edit_from_widget' not in request.POST
):
# Popup in pick mode or normal mode. In both cases we want to go
# back to the folder list view after save. And not the useless file
Expand All @@ -84,7 +85,13 @@ def response_change(self, request, obj):
admin_url_params_encoded(request),
)
return HttpResponseRedirect(url)
return super().response_change(request, obj)

# Add media to context to allow default django js inclusions in django/filer/base_site.html ({{ media.js }})
# This is required by popup_handling.js used in popup_response
template_response = super().response_change(request, obj)
if hasattr(template_response, 'context_data'):
template_response.context_data["media"] = self.media
return template_response

def render_change_form(self, request, context, add=False, change=False,
form_url='', obj=None):
Expand Down
6 changes: 6 additions & 0 deletions filer/admin/tools.py
Expand Up @@ -66,6 +66,10 @@ def popup_pick_type(request):
return None


def edit_from_widget(request):
return request.GET.get('_edit_from_widget') == '1'


def get_directory_listing_type(request):
list_type = request.GET.get('_list_type', None)
if list_type not in settings.FILER_FOLDER_ADMIN_LIST_TYPE_CHOICES:
Expand All @@ -84,6 +88,8 @@ def admin_url_params(request, params=None):
pick_type = popup_pick_type(request)
if pick_type:
params['_pick'] = pick_type
if edit_from_widget(request):
params['_edit_from_widget'] = '1'
list_type = get_directory_listing_type(request)
if list_type and '_list_type' not in params.keys():
params['_list_type'] = list_type
Expand Down
3 changes: 3 additions & 0 deletions filer/fields/file.py
Expand Up @@ -28,10 +28,12 @@ def render(self, name, value, attrs=None, renderer=None):
obj = self.obj_for_value(value)
css_id = attrs.get('id', 'id_image_x')
related_url = None
change_url = ''
if value:
try:
file_obj = File.objects.get(pk=value)
related_url = file_obj.logical_folder.get_admin_directory_listing_url_path()
change_url = file_obj.get_admin_change_url()
except Exception as e:
# catch exception and manage it. We can re-raise it for debugging
# purposes and/or just logging it, provided user configured
Expand All @@ -58,6 +60,7 @@ def render(self, name, value, attrs=None, renderer=None):
context = {
'hidden_input': hidden_input,
'lookup_url': '%s%s' % (related_url, lookup_url),
'change_url': change_url,
'object': obj,
'lookup_name': name,
'id': css_id,
Expand Down
59 changes: 30 additions & 29 deletions filer/private/sass/components/_drag-and-drop.scss
Expand Up @@ -170,6 +170,9 @@ form .form-row {
width: auto !important;
height: auto !important;
padding: 10px 20px !important;
margin-top: 24px;
margin-left: 10px;
text-align: center !important;
cursor: pointer;
.fa {
color: $white;
Expand All @@ -181,11 +184,15 @@ form .form-row {
display: none;
}
.choose-file,
.replace-file,
.edit-file {
color: $white;
margin: 0;
}
.edit-file {
.replace-file {
display: none;
}
&.edit {
display: none;
}
&.related-lookup-change {
Expand All @@ -208,16 +215,17 @@ form .form-row {
.choose-file {
display: none;
}
.edit-file {
.replace-file {
display: block;
}
&.lookup {
display: block !important;
}
&.edit {
display: block;
}
}
}
// makes sure that filer clear button has correct size #669
.filerClearer {
width: 36px !important;
height: 36px !important;
}
.filerFile {
position: absolute;
top: 9px;
Expand All @@ -228,11 +236,11 @@ form .form-row {
background-color: $white;
}
// make sure that text crops if there is not enough space #670
span:not(:empty):not(.choose-file):not(.edit-file) {
span:not(:empty):not(.choose-file):not(.replace-file):not(.edit-file) {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: calc(100% - 200px);
width: calc(100% - 260px);
}
// required for django CMS <= 3.1 #673
img {
Expand All @@ -249,10 +257,6 @@ form .form-row {
border-radius: $border-radius-base;
}
}
.related-lookup {
text-align: center !important;
margin-top: 24px;
}
// required for django CMS <= 3.1
a {
box-sizing: border-box;
Expand All @@ -275,23 +279,20 @@ form .form-row {
.filerClearer {
@include button-variant($btn-default-color, $btn-default-bgcolor, $btn-default-border, true);
float: right;
// make sure that clear button has correct size #272
width: 10px;
height: 10px;
margin: 24px 0 0 5px !important;
padding: 12px !important;
border: solid 1px $gray-lighter;
border-radius: $border-radius-base;
padding: 12px;
margin: 24px 0 0 10px;
width: 36px;
height: 36px;
cursor: pointer;
&:before {
color: $gray-light !important;
vertical-align: middle;
margin: 0;
&:focus {
background-color: $white;
}
@media screen and (max-width: 1024px) {
margin-left: 15px !important;
span {
text-align: center;
line-height: 24px;
}
}

}
&.filer-dropzone-mobile {
.filerFile {
Expand All @@ -310,13 +311,13 @@ form .form-row {
@media screen and (max-width: $screen-tablet-filer) {
.description_text {
text-overflow: ellipsis;
width: calc(100% - 200px);
width: calc(100% - 250px);
overflow: hidden;
height: 20px;
}
}
>span:not(.choose-file):not(.edit-file), .dz-name {
width: calc(100% - 200px);
>span:not(.choose-file):not(.replace-file):not(.edit-file), .dz-name {
width: calc(100% - 250px);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions filer/static/filer/css/admin_filer.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion filer/static/filer/css/maps/admin_filer.css.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions filer/static/filer/js/addons/dropzone.init.js
Expand Up @@ -22,6 +22,7 @@ djQuery(function ($) {
var dropzones = $(dropzoneSelector);
var messageSelector = '.js-filer-dropzone-message';
var lookupButtonSelector = '.js-related-lookup';
var editButtonSelector = '.js-related-edit';
var progressSelector = '.js-filer-dropzone-progress';
var previewImageWrapperSelector = '.js-img-wrapper';
var filerClearerSelector = '.filerClearer';
Expand Down Expand Up @@ -56,6 +57,7 @@ djQuery(function ($) {
var inputId = dropzone.find(fileIdInputSelector);
var isImage = inputId.is('[name="image"]');
var lookupButton = dropzone.find(lookupButtonSelector);
var editButton = dropzone.find(editButtonSelector);
var message = dropzone.find(messageSelector);
var clearButton = dropzone.find(filerClearerSelector);
var fileChoose = dropzone.find(fileChooseSelector);
Expand Down Expand Up @@ -99,6 +101,7 @@ djQuery(function ($) {
this.removeAllFiles(true);
fileChoose.hide();
lookupButton.addClass('related-lookup-change');
editButton.addClass('related-lookup-change');
message.addClass(hiddenClass);
dropzone.removeClass(dragHoverClass);
dropzone.addClass(objectAttachedClass);
Expand Down Expand Up @@ -144,6 +147,7 @@ djQuery(function ($) {
dropzone.removeClass(objectAttachedClass);
inputId.val('');
lookupButton.removeClass('related-lookup-change');
editButton.removeClass('related-lookup-change');
message.removeClass(hiddenClass);
inputId.trigger('change');
}
Expand Down
17 changes: 17 additions & 0 deletions filer/static/filer/js/addons/filer_popup_response.js
@@ -0,0 +1,17 @@
/*global opener */
(function () {
'use strict';
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
switch (initData.action) {
case 'change':
// Specific function for file editing popup opened from widget
opener.dismissRelatedImageLookupPopup(window, initData.new_value, null, initData.obj, null);
break;
case 'delete':
opener.dismissDeleteRelatedObjectPopup(window, initData.value);
break;
default:
opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj);
break;
}
})();
19 changes: 16 additions & 3 deletions filer/static/filer/js/addons/popup_handling.js
Expand Up @@ -19,10 +19,17 @@ if (django.jQuery) {
document.location.reload();
win.close();
};
window.dismissRelatedImageLookupPopup = function (win, chosenId, chosenThumbnailUrl, chosenDescriptionTxt) {
window.dismissRelatedImageLookupPopup = function (
win,
chosenId,
chosenThumbnailUrl,
chosenDescriptionTxt,
chosenAdminChangeUrl
) {
var id = windowname_to_id(win.name);
var lookup = $('#' + id);
var container = lookup.closest('.filerFile');
var edit = container.find('.edit');
var image = container.find('.thumbnail_img');
var descriptionText = container.find('.description_text');
var clearer = container.find('.filerClearer');
Expand All @@ -32,11 +39,17 @@ if (django.jQuery) {

element.val(chosenId);
element.closest('.js-filer-dropzone').addClass('js-object-attached');
image.attr('src', chosenThumbnailUrl).removeClass('hidden');
image.removeAttr('srcset'); // would be nicer, but much more complicate to also replace 'srcset'
if (chosenThumbnailUrl) {
image.attr('src', chosenThumbnailUrl).removeClass('hidden');
image.removeAttr('srcset'); // would be nicer, but much more complicate to also replace 'srcset'
}
descriptionText.text(chosenDescriptionTxt);
clearer.removeClass('hidden');
lookup.addClass('related-lookup-change');
edit.addClass('related-lookup-change');
if (chosenAdminChangeUrl) {
edit.attr('href', chosenAdminChangeUrl + '?_edit_from_widget=1');
}
dropzoneMessage.addClass('hidden');

if (oldId !== chosenId) {
Expand Down
2 changes: 2 additions & 0 deletions filer/static/filer/js/addons/widget.js
Expand Up @@ -16,6 +16,7 @@ djQuery(function ($) {
var thumbnail = container.find('.thumbnail_img');
var description = container.find('.description_text');
var addImageButton = container.find('.lookup');
var editImageButton = container.find('.edit');
var dropzoneMessage = container.siblings('.dz-message');
var hiddenClass = 'hidden';

Expand All @@ -24,6 +25,7 @@ djQuery(function ($) {
thumbnail.addClass(hiddenClass);
thumbnail.parent('a').removeAttr('href');
addImageButton.removeClass('related-lookup-change');
editImageButton.removeClass('related-lookup-change');
dropzoneMessage.removeClass(hiddenClass);
description.empty();
};
Expand Down
10 changes: 10 additions & 0 deletions filer/templates/admin/filer/file/popup_response.html
@@ -0,0 +1,10 @@
{% extends "admin/filer/base_site.html" %}
{% load static %}

{% block extrahead %}
{{ block.super }}
<script id="django-admin-popup-response-constants"
src="{% static "filer/js/addons/filer_popup_response.js" %}"
data-popup-response="{{ popup_response_data }}">
</script>
{% endblock %}
6 changes: 3 additions & 3 deletions filer/templates/admin/filer/folder/directory_table_list.html
Expand Up @@ -92,15 +92,15 @@
<tr>
<td class="column-checkbox">
{% if is_popup and filer_admin_context.pick_file %}
<a class="insertlink insertlinkButton" href="#" onclick="opener.dismissRelatedImageLookupPopup(window, '{{ file.id|unlocalize }}', '{% file_icon_url file %}', '{{ file.label|escapejs }}'); return false;"
<a class="insertlink insertlinkButton" href="#" onclick="opener.dismissRelatedImageLookupPopup(window, '{{ file.id|unlocalize }}', '{% file_icon_url file %}', '{{ file.label|escapejs }}', '{{ file.get_admin_change_url }}'); return false;"
title="{% trans 'Select this file' %}">&nbsp;</a>
{% elif action_form and not is_popup %}
<input type="checkbox" class="action-select" value="file-{{ item.pk|safe }}" name="_selected_action">
{% endif %}
</td>
<td class="column-icon">
{% if is_popup and filer_admin_context.pick_file %}
<a href="#" onclick="opener.dismissRelatedImageLookupPopup(window, {{ file.id|unlocalize }}, '{% file_icon_url file %}', '{{ file.label|escapejs }}'); return false;"
<a href="#" onclick="opener.dismissRelatedImageLookupPopup(window, {{ file.id|unlocalize }}, '{% file_icon_url file %}', '{{ file.label|escapejs }}', '{{ file.get_admin_change_url }}'); return false;"
title="{% trans 'Select this file' %}">
{% elif has_change_permission %}
<a href="{{ file.get_admin_change_url }}{% filer_admin_context_url_params %}"
Expand All @@ -115,7 +115,7 @@
<div>
<strong>
{% if is_popup and filer_admin_context.pick_file %}
<a href="#" onclick="opener.dismissRelatedImageLookupPopup(window, {{ file.id|unlocalize }}, '{% file_icon_url file %}', '{{ file.label|escapejs }}'); return false;"
<a href="#" onclick="opener.dismissRelatedImageLookupPopup(window, {{ file.id|unlocalize }}, '{% file_icon_url file %}', '{{ file.label|escapejs }}', '{{ file.get_admin_change_url }}'); return false;"
title="{% trans 'Select this file' %}">
{% elif has_change_permission %}
<a href="{{ file.get_admin_change_url }}{% filer_admin_context_url_params %}"
Expand Down
9 changes: 7 additions & 2 deletions filer/templates/admin/filer/widgets/admin_file.html
Expand Up @@ -40,10 +40,15 @@
width="10" height="10" alt="{% trans 'Clear' %}" title="{% trans 'Clear' %}"
data-no-icon-file="{% static 'filer/icons/file-unknown.svg' %}">

<a href="{{ change_url }}?_edit_from_widget=1" class="js-related-edit related-lookup {% if object %}related-lookup-change{% endif %} edit" id="{{ id }}_change"
title="{% trans 'Edit' %}">
<span class="edit-file"><span class="fa fa-pencil"></span></span>
</a>

<a href="{{ lookup_url }}" class="js-related-lookup related-lookup {% if object %}related-lookup-change{% endif %} lookup" id="{{ id }}_lookup"
title="{% trans 'Lookup' %}">
<span class="choose-file"><span class="fa fa-picture-o"></span>{% trans 'Choose File' %}</span>
<span class="edit-file"><span class="fa fa-pencil"></span></span>
<span class="choose-file"><span class="fa fa-search"></span>{% trans 'Choose File' %}</span>
<span class="replace-file"><span class="fa fa-search"></span></span>
</a>

<br>
Expand Down