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.
|
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
|
## 2.15.5 - 2026-10-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-player",
|
"name": "pulse-signage-player",
|
||||||
"version": "2.15.5",
|
"version": "2.15.6",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage player application bundle",
|
"description": "Pulse Signage player application bundle",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-web",
|
"name": "pulse-signage-web",
|
||||||
"version": "2.15.5",
|
"version": "2.15.6",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage web and bridge application bundle",
|
"description": "Pulse Signage web and bridge application bundle",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.15.5",
|
"version": "2.15.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.15.5",
|
"version": "2.15.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sparticuz/chromium": "^149.0.0",
|
"@sparticuz/chromium": "^149.0.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.15.5",
|
"version": "2.15.6",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage application with MySQL and media storage",
|
"description": "Pulse Signage application with MySQL and media storage",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -556,9 +556,11 @@ function showPreviewModal() {
|
|||||||
if (modal && body) {
|
if (modal && body) {
|
||||||
const renameForm = modal.querySelector('[data-media-gallery-rename-form]');
|
const renameForm = modal.querySelector('[data-media-gallery-rename-form]');
|
||||||
const filenameInput = modal.querySelector('[data-media-gallery-filename]');
|
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 renameSave = modal.querySelector('[data-media-gallery-rename-save]');
|
||||||
const renameStatus = modal.querySelector('[data-media-gallery-rename-status]');
|
const renameStatus = modal.querySelector('[data-media-gallery-rename-status]');
|
||||||
let activePreview = null;
|
let activePreview = null;
|
||||||
|
let activeExtension = '';
|
||||||
|
|
||||||
if (renameForm && filenameInput && renameSave && renameStatus) {
|
if (renameForm && filenameInput && renameSave && renameStatus) {
|
||||||
renameForm.addEventListener('submit', async function (event) {
|
renameForm.addEventListener('submit', async function (event) {
|
||||||
@@ -573,7 +575,7 @@ if (modal && body) {
|
|||||||
const response = await fetch(action, {
|
const response = await fetch(action, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
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();
|
const result = await response.json();
|
||||||
if (!response.ok) throw new Error(result.error || 'Unable to rename media.');
|
if (!response.ok) throw new Error(result.error || 'Unable to rename media.');
|
||||||
@@ -586,7 +588,7 @@ if (modal && body) {
|
|||||||
label.title = result.name;
|
label.title = result.name;
|
||||||
}
|
}
|
||||||
if (activePreview === preview) {
|
if (activePreview === preview) {
|
||||||
filenameInput.value = result.name;
|
filenameInput.value = activeExtension ? result.name.slice(0, -activeExtension.length) : result.name;
|
||||||
if (title) title.textContent = result.name;
|
if (title) title.textContent = result.name;
|
||||||
const image = body.querySelector('img');
|
const image = body.querySelector('img');
|
||||||
if (image) image.alt = result.name;
|
if (image) image.alt = result.name;
|
||||||
@@ -625,7 +627,11 @@ if (modal && body) {
|
|||||||
const assetId = column && column.dataset.mediaId;
|
const assetId = column && column.dataset.mediaId;
|
||||||
renameForm.hidden = !assetId;
|
renameForm.hidden = !assetId;
|
||||||
renameForm.action = '/media-library/' + encodeURIComponent(assetId || '') + '/rename';
|
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;
|
filenameInput.disabled = false;
|
||||||
renameSave.disabled = false;
|
renameSave.disabled = false;
|
||||||
renameStatus.hidden = true;
|
renameStatus.hidden = true;
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
<label for="media-gallery-filename" class="form-label">Filename</label>
|
<label for="media-gallery-filename" class="form-label">Filename</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="media-gallery-filename" name="name" type="text" class="form-control" maxlength="255" required data-media-gallery-filename />
|
<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>
|
<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>
|
</div>
|
||||||
<p class="small mb-0 mt-2" role="status" data-media-gallery-rename-status hidden></p>
|
<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'] });
|
const editable = renderMediaLibraryPage(data, '', { permissions: ['media-library.read', 'media-library.update'] });
|
||||||
assert.match(editable, /data-media-gallery-rename-form/);
|
assert.match(editable, /data-media-gallery-rename-form/);
|
||||||
assert.match(editable, /maxlength="255" required data-media-gallery-filename/);
|
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/);
|
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