Keep media rename file extensions fixed
This commit is contained in:
1 parent
70b45debde
commit
8d75b12354
8 files changed
+81
-8
No files matched your search
@@ -2,6 +2,12 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 2.15.6 - 2026-10-18
|
||||
|
||||
### Changed
|
||||
|
||||
- Media Library renaming now keeps the file extension fixed while allowing the filename to be edited.
|
||||
|
||||
## 2.15.5 - 2026-10-17
|
||||
|
||||
### Added
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pulse-signage-player",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"private": false,
|
||||
"description": "Pulse Signage player application bundle",
|
||||
"engines": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pulse-signage-web",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"private": false,
|
||||
"description": "Pulse Signage web and bridge application bundle",
|
||||
"engines": {
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pulse-signage",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pulse-signage",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"dependencies": {
|
||||
"@sparticuz/chromium": "^149.0.0",
|
||||
"animate.css": "^4.1.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pulse-signage",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"private": false,
|
||||
"description": "Pulse Signage application with MySQL and media storage",
|
||||
"engines": {
|
||||
|
||||
@@ -556,9 +556,11 @@ function showPreviewModal() {
|
||||
if (modal && body) {
|
||||
const renameForm = modal.querySelector('[data-media-gallery-rename-form]');
|
||||
const filenameInput = modal.querySelector('[data-media-gallery-filename]');
|
||||
const extensionLabel = modal.querySelector('[data-media-gallery-extension]');
|
||||
const renameSave = modal.querySelector('[data-media-gallery-rename-save]');
|
||||
const renameStatus = modal.querySelector('[data-media-gallery-rename-status]');
|
||||
let activePreview = null;
|
||||
let activeExtension = '';
|
||||
|
||||
if (renameForm && filenameInput && renameSave && renameStatus) {
|
||||
renameForm.addEventListener('submit', async function (event) {
|
||||
@@ -573,7 +575,7 @@ if (modal && body) {
|
||||
const response = await fetch(action, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
body: JSON.stringify({ name: filenameInput.value })
|
||||
body: JSON.stringify({ name: filenameInput.value + activeExtension })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!response.ok) throw new Error(result.error || 'Unable to rename media.');
|
||||
@@ -586,7 +588,7 @@ if (modal && body) {
|
||||
label.title = result.name;
|
||||
}
|
||||
if (activePreview === preview) {
|
||||
filenameInput.value = result.name;
|
||||
filenameInput.value = activeExtension ? result.name.slice(0, -activeExtension.length) : result.name;
|
||||
if (title) title.textContent = result.name;
|
||||
const image = body.querySelector('img');
|
||||
if (image) image.alt = result.name;
|
||||
@@ -625,7 +627,11 @@ if (modal && body) {
|
||||
const assetId = column && column.dataset.mediaId;
|
||||
renameForm.hidden = !assetId;
|
||||
renameForm.action = '/media-library/' + encodeURIComponent(assetId || '') + '/rename';
|
||||
filenameInput.value = name;
|
||||
const extensionIndex = name.lastIndexOf('.');
|
||||
activeExtension = extensionIndex > 0 && extensionIndex < name.length - 1 ? name.slice(extensionIndex) : '';
|
||||
filenameInput.value = activeExtension ? name.slice(0, extensionIndex) : name;
|
||||
filenameInput.maxLength = Math.max(1, 255 - activeExtension.length);
|
||||
if (extensionLabel) extensionLabel.textContent = activeExtension;
|
||||
filenameInput.disabled = false;
|
||||
renameSave.disabled = false;
|
||||
renameStatus.hidden = true;
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
<label for="media-gallery-filename" class="form-label">Filename</label>
|
||||
<div class="input-group">
|
||||
<input id="media-gallery-filename" name="name" type="text" class="form-control" maxlength="255" required data-media-gallery-filename />
|
||||
<span class="input-group-text" data-media-gallery-extension aria-label="File extension"></span>
|
||||
<button type="submit" class="btn btn-primary" title="Save filename" data-media-gallery-rename-save><i class="bi bi-floppy" aria-hidden="true"></i><span class="visually-hidden">Save filename</span></button>
|
||||
</div>
|
||||
<p class="small mb-0 mt-2" role="status" data-media-gallery-rename-status hidden></p>
|
||||
|
||||
@@ -408,5 +408,65 @@ test('media preview offers filename editing only with media update permission',
|
||||
const editable = renderMediaLibraryPage(data, '', { permissions: ['media-library.read', 'media-library.update'] });
|
||||
assert.match(editable, /data-media-gallery-rename-form/);
|
||||
assert.match(editable, /maxlength="255" required data-media-gallery-filename/);
|
||||
assert.match(editable, /data-media-gallery-extension/);
|
||||
assert.match(editable, /data-media-gallery-rename-save/);
|
||||
});
|
||||
|
||||
test('media preview rename keeps the original filename extension fixed', async () => {
|
||||
const handlers = {};
|
||||
const submittedNames = [];
|
||||
const input = { value: '', disabled: false, maxLength: 255 };
|
||||
const extension = { textContent: '' };
|
||||
const title = { textContent: '' };
|
||||
const body = { replaceChildren() {}, appendChild() {}, querySelector() { return null; } };
|
||||
const renameForm = { action: '', addEventListener(name, callback) { handlers['form:' + name] = callback; } };
|
||||
const renameSave = { disabled: false };
|
||||
const renameStatus = { hidden: true, classList: { add() {}, remove() {} } };
|
||||
const modal = {
|
||||
querySelector(selector) {
|
||||
return {
|
||||
'[data-media-gallery-preview-body]': body,
|
||||
'#media-gallery-preview-modal-label': title,
|
||||
'[data-media-gallery-rename-form]': renameForm,
|
||||
'[data-media-gallery-filename]': input,
|
||||
'[data-media-gallery-extension]': extension,
|
||||
'[data-media-gallery-rename-save]': renameSave,
|
||||
'[data-media-gallery-rename-status]': renameStatus
|
||||
}[selector] || null;
|
||||
},
|
||||
addEventListener(name, callback) { handlers['modal:' + name] = callback; }
|
||||
};
|
||||
const column = { dataset: { mediaId: '9' }, querySelector() { return null; } };
|
||||
const preview = {
|
||||
dataset: { mediaName: 'original.png' },
|
||||
getAttribute(name) { return { 'data-media-path': '/media/uploads/id.png', 'data-media-type': 'image', 'data-media-name': 'original.png' }[name]; },
|
||||
closest() { return column; },
|
||||
setAttribute() {}
|
||||
};
|
||||
const context = vm.createContext({
|
||||
URLSearchParams,
|
||||
window: { location: { search: '' }, innerWidth: 1200, pulseModal: { show() {} } },
|
||||
document: {
|
||||
getElementById() { return modal; },
|
||||
querySelector() { return null; },
|
||||
addEventListener(name, callback) { handlers['document:' + name] = callback; },
|
||||
createElement() { return {}; }
|
||||
},
|
||||
fetch: async (_url, options) => {
|
||||
if (options && options.body) {
|
||||
submittedNames.push(JSON.parse(options.body).name);
|
||||
return { ok: true, async json() { return { name: 'updated.png' }; } };
|
||||
}
|
||||
return { ok: true, async json() { return { assets: [], nextOffset: 0, hasMore: false, total: 0 }; } };
|
||||
}
|
||||
});
|
||||
vm.runInContext(fs.readFileSync(path.join(__dirname, '../src/web/public/js/settings/media-library.js'), 'utf8'), context);
|
||||
|
||||
handlers['document:click']({ target: { closest() { return preview; } } });
|
||||
assert.equal(input.value, 'original');
|
||||
assert.equal(extension.textContent, '.png');
|
||||
assert.equal(input.maxLength, 251);
|
||||
input.value = 'updated';
|
||||
await handlers['form:submit']({ preventDefault() {} });
|
||||
assert.deepEqual(submittedNames, ['updated.png']);
|
||||
});
|
||||
Reference in new issue
Block a user