Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions src/Bridge/SonataAdmin/assets/js/components/mediaSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,51 @@ const MediaSelector = class {
this.modal = false;
this.modalContent = false;
this.currentFolder = false;
this.currentSearchValue = '';
}

fetchFolder = (url) => {
this.currentFolder = url;
return fetch(url).then((response) => response.text());
};

getSearchUrl = (baseUrl) => {
if (!this.currentSearchValue) return baseUrl;
const separator = baseUrl.includes('?') ? '&' : '?';
return `${baseUrl}${separator}search=${encodeURIComponent(this.currentSearchValue)}`;
};

setupSearch = () => {
const searchForm = this.modalContent.querySelector('.joli-media-search-form');
const searchInput = this.modalContent.querySelector('.joli-media-search-input');
if (!searchForm || !searchInput) return;

this.currentSearchValue = searchInput.value;

const newSearchForm = searchForm.cloneNode(true);
searchForm.parentNode.replaceChild(newSearchForm, searchForm);

const newInput = newSearchForm.querySelector('.joli-media-search-input');

newSearchForm.addEventListener('submit', (e) => {
e.preventDefault();
e.stopPropagation();
this.currentSearchValue = newInput.value.trim();
this.fetchFolder(this.getSearchUrl(this.currentFolder)).then(this.configureModal);
});

newInput.addEventListener('search', () => {
if (!newInput.value) {
this.currentSearchValue = '';
this.fetchFolder(this.currentFolder).then(this.configureModal);
}
});
};

configureModal = (html) => {
this.modalContent.innerHTML = html;
Admin.shared_setup(this.modal);
this.setupSearch();
};

handleModalClick = (event) => {
Expand All @@ -41,7 +76,7 @@ const MediaSelector = class {

if (target.dataset.mediaTemplate === undefined || target.dataset.mediaUrl === undefined) {
// this is not a selectable media
this.fetchFolder(target.attributes.href.value).then(this.configureModal);
this.fetchFolder(this.getSearchUrl(target.attributes.href.value)).then(this.configureModal);
return;
}

Expand All @@ -57,6 +92,11 @@ const MediaSelector = class {
event.stopPropagation();

const form = event.target.closest("form");

if (form && form.dataset.component === 'media-search') {
return;
}

const formData = new FormData(form);
const url = form.action;

Expand Down Expand Up @@ -98,8 +138,10 @@ const MediaSelector = class {
}

this.modalContent.innerHTML = '';
this.currentSearchValue = '';
this.currentFolder = this.editButton.attributes.href.value + '/' + this.editButton.dataset.folder;

this.fetchFolder(this.editButton.attributes.href.value + '/' + this.editButton.dataset.folder).then((html) => {
this.fetchFolder(this.currentFolder).then((html) => {
this.configureModal(html);
jQuery(this.modal).modal();
Admin.setup_list_modal(this.modal);
Expand Down
4 changes: 4 additions & 0 deletions src/Bridge/SonataAdmin/assets/styles/media-choice.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@
display: none;
}
}

.joli-media-search {
padding: 15px;
}
4 changes: 2 additions & 2 deletions src/Bridge/SonataAdmin/public/entrypoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"entrypoints": {
"joli-media-sonata-admin": {
"css": [
"./joli-media-sonata-admin.501cbd68.css"
"./joli-media-sonata-admin.b1b110a9.css"
],
"js": [
"./joli-media-sonata-admin.4deda32b.js"
"./joli-media-sonata-admin.27ab3a73.js"
]
}
}
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/Bridge/SonataAdmin/public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"joli-media-sonata-admin.css": "./joli-media-sonata-admin.501cbd68.css",
"joli-media-sonata-admin.js": "./joli-media-sonata-admin.4deda32b.js"
"joli-media-sonata-admin.css": "./joli-media-sonata-admin.b1b110a9.css",
"joli-media-sonata-admin.js": "./joli-media-sonata-admin.27ab3a73.js"
}
24 changes: 21 additions & 3 deletions src/Bridge/SonataAdmin/src/Controller/MediaAdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,26 @@ public function list(Request $request, string $key = ''): Response
path: $currentKey,
));

$searchValue = $request->query->getString('search', '');
$hasSearch = '' !== $searchValue;

try {
$trashPath = $this->getOriginalStorage()->getTrashPath();

if ($trashPath === $currentKey || str_starts_with($currentKey, $trashPath . '/')) {
throw new ForbiddenPathException($trashPath);
}

$directories = $this->getOriginalStorage()->listDirectories($currentKey, recursive: false);
natcasesort($directories);
$dirFilter = null;
if ($hasSearch) {
$dirFilter = static fn (string $a): bool => str_contains(strtolower($a), strtolower($searchValue));
}

$directories = $this->getOriginalStorage()->listDirectories($currentKey, recursive: $hasSearch, filter: $dirFilter);
Comment on lines +251 to +266

if (!$hasSearch) {
natcasesort($directories);
}
} catch (ForbiddenPathException|PathTraversalDetected|UnableToListContents) {
$this->addFlash(
'sonata_flash_error',
Expand All @@ -278,12 +289,18 @@ public function list(Request $request, string $key = ''): Response

$routeName = $request->attributes->get('_route') ?? 'joli_media_sonata_admin_explore';

$mediaFilter = null;
if ($hasSearch) {
$mediaFilter = static fn ($media): bool => str_contains(strtolower($media->getPath()), strtolower($searchValue));
}

try {
$paginatedMedias = $this->getOriginalStorage()->listMediasPaginated(
$currentKey,
recursive: false,
recursive: $hasSearch,
page: $request->query->getInt('page', 1),
perPage: $this->config->getPaginationSize(),
filter: $mediaFilter,
);
} catch (\OutOfRangeException) {
throw new BadRequestException('The requested page number is out of range.');
Expand All @@ -306,6 +323,7 @@ public function list(Request $request, string $key = ''): Response
'pager' => $pager,
'parent_key' => \dirname($currentKey),
'rename_directory_form' => $this->createRenameDirectoryForm($key)->createView(),
'search' => $searchValue,
]));
}

Expand Down
12 changes: 12 additions & 0 deletions src/Bridge/SonataAdmin/templates/list.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@

{% block content %}
{{ block('content_header') }}
{% if 'choose' in base_template or 'explore' in base_template %}
<div class="joli-media-search">
<form class="joli-media-search-form" {% if 'explore' in base_template %}method="GET" action="{{ path(app.request.attributes.get('_route'), { key: current_key }) }}"{% else %}data-component="media-search"{% endif %}>
<div class="input-group">
<input type="search" class="form-control joli-media-search-input" {% if 'explore' in base_template %}name="search"{% endif %} placeholder="{{ 'media.search_label'|trans }}" value="{{ search }}" autocomplete="off">
<span class="input-group-btn">
<button class="btn btn-default joli-media-search-btn" type="submit"><i class="fas fa-search"></i> {{ 'action.search'|trans }}</button>
</span>
</div>
</form>
</div>
{% endif %}
Comment on lines +90 to +101
<div class="gallery">
{% if app.session.get('view_mode') == 'list' %}
<div class="box box-primary">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ action:
remove: 'Remove'
rename_directory: 'Rename directory'
rename_file: 'Rename file'
search: 'Search'
browser:
audio:
unsupported: 'Your browser does not support the audio element.'
Expand Down Expand Up @@ -41,6 +42,7 @@ media:
add: 'Add media'
deleted_success: 'Media "%media%" deleted successfully'
dimensions: 'Dimensions'
search_label: 'Search media...'
error:
in_use: 'The media "%media%" is used in the "%field%" field of the "%entity%" entity. It cannot be deleted.'
inaccessible:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ action:
remove: 'Détacher'
rename_directory: 'Renommer le dossier'
rename_file: 'Renommer le fichier'
search: 'Rechercher'
browser:
audio:
unsupported: 'Votre navigateur ne supporte pas la lecture audio.'
Expand Down Expand Up @@ -42,8 +43,9 @@ media:
add: 'Ajouter un média'
delete:
confirm: 'Êtes-vous sûr de vouloir supprimer ce média ? Cette action ne peut pas être annulée.'
deleted_success: 'Le média %media% a été supprimé avec succès'
deleted_success: 'Le média "%media%" a été supprimé avec succès'
dimensions: 'Dimensions'
search_label: 'Rechercher un média...'
error:
in_use: 'Le media "%media%" est utilisé dans le champ "%field%" de l''entité "%entity%". Il ne peut pas être supprimé.'
inaccessible:
Expand Down
Loading