Allow editing Site Preferences table

This commit is contained in:
varjolintu 2025-03-02 10:14:48 +02:00
parent 609bcfa83b
commit 6bd531a7cf
4 changed files with 146 additions and 5 deletions

View file

@ -7,6 +7,10 @@
"message": "Add Site Preferences for this URL.",
"description": "Add button title text on Site Preferences tab."
},
"editSitePreferenceButtonTitle": {
"message": "Edit URL for this Site Preferences.",
"description": "Edit button title text on Site Preferences tab."
},
"allowIframeButtonTitle": {
"message": "Allows Cross-Origin iframes for the current page.",
"description": "Allow Cross-Origin iframes button title text."
@ -686,6 +690,10 @@
"message": "Add",
"description": "Add button text."
},
"optionsButtonEdit": {
"message": "Edit",
"description": "Edit button text."
},
"optionsButtonUpdate": {
"message": "Check for updates",
"description": "Check for updates button text."

View file

@ -51,7 +51,7 @@ input:invalid {
border: 2px solid red;
}
input[disabled] {
input:disabled {
opacity: .3!important;
}
@ -112,6 +112,18 @@ tbody {
background-color: var(--kpxc-checkbox-background-color) !important;
}
.table-striped > tbody > tr:nth-of-type(even) input[type="url"] {
--bs-table-bg-type: var(--kpxc-card-background-color) !important;
background-color: var(--kpxc-card-background-color) !important;
color: var(--kpxc-text-color) !important;
}
.table-striped > tbody > tr:nth-of-type(odd) input[type="url"] {
--bs-table-bg-type: var(--kpxc-table-odd-color) !important;
background-color: var(--kpxc-table-odd-color) !important;
color: var(--kpxc-text-color) !important;
}
.table tbody td {
vertical-align: middle;
}
@ -213,6 +225,29 @@ table td:last-of-type {
color: var(--kpxc-text-color);
}
.site-preferences-input {
border: 0;
border-bottom-right-radius: 4px !important;
border-top-right-radius: 4px !important;
}
.site-preferences-input:disabled {
opacity: 1 !important;
pointer-events: none;
}
button#sitePreferencesEditUrl {
border-bottom-left-radius: 4px !important;
border-bottom-right-radius: 4px !important;
border-top-left-radius: 4px !important;
border-top-right-radius: 4px !important;
}
button#sitePreferencesCancelEdit {
border-bottom-left-radius: 4px !important;
border-top-left-radius: 4px !important;
}
@media (min-width: 768px) {
.sidebar {
height: auto;

View file

@ -760,7 +760,23 @@
<td colspan="5"><span data-i18n="optionsSitePreferencesNotFound"></span></td>
</tr>
<tr class="clone d-none">
<td class="text-nowrap"></td>
<td class="text-nowrap">
<div class="input-group was-validated" id="manualUrlGroup">
<input class="form-control form-control-sm site-preferences-input" type="url" id="editUrl" aria-label="Edit URL" pattern="file://.*|ftp://.*|http://.*|https://.*" minlength="5" maxlength="2000" required disabled>
<button class="btn btn-sm btn-primary" type="button" id="sitePreferencesEditUrl" data-i18n="[title]editSitePreferenceButtonTitle">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
<span data-i18n="optionsButtonEdit"></span>
</button>
<button class="btn btn-sm btn-danger" type="button" id="sitePreferencesCancelEdit" data-i18n="[title]editSitePreferenceButtonTitle" style="display: none;">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
<span data-i18n="optionsButtonCancel"></span>
</button>
<button class="btn btn-sm btn-primary" type="button" id="sitePreferencesSaveEdit" data-i18n="[title]editSitePreferenceButtonTitle" style="display: none;">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
<span data-i18n="optionsButtonSave"></span>
</button>
</div>
</td>
<td>
<select class="form-select form-select-sm" name="ignore" data-i18n="[title]optionsSitePreferencesSelect">
<option value="ignoreNothing" data-i18n="optionsSelectionNothing"></option>

View file

@ -521,14 +521,68 @@ options.initSitePreferences = function() {
const removeButtonClicked = function(e) {
e.preventDefault();
const closestTr = this.closest('tr');
const closestTr = e.target.closest('tr');
$('#dialogDeleteSite').setAttribute('url', closestTr.getAttribute('url'));
$('#dialogDeleteSite').setAttribute('tr-id', closestTr.getAttribute('id'));
$('#dialogDeleteSite .modal-body strong').textContent = closestTr.children[0].textContent;
$('#dialogDeleteSite .modal-body strong').textContent = closestTr.getAttribute('url');
dialogDeleteSiteModal.show();
};
// Shows or hides Cancel / Save buttons on row
const enterEditMode = function(e, row, inputField, editButton, cancelButton, saveButton) {
e.preventDefault();
if (!row || !inputField) {
return;
}
if (inputField.disabled) {
inputField.disabled = false;
cancelButton.show();
saveButton.show();
saveButton.disabled = true;
editButton.hide();
inputField.focus();
inputField.setSelectionRange(inputField.value?.length || 0, inputField.value?.length || 0);
}
};
const exitEditMode = function(e, row, inputField, editButton, cancelButton, saveButton) {
e.preventDefault();
if (!row || !inputField) {
return;
}
if (!inputField.disabled) {
inputField.disabled = true;
inputField.value = row.getAttribute('url');
cancelButton.hide();
saveButton.hide();
editButton.show();
}
};
const saveModifiedUrl = function(e, row, inputField, editButton, cancelButton, saveButton) {
e.preventDefault();
if (!row || !inputField) {
return;
}
const currentUrl = row.getAttribute('url');
for (const site of options.settings['sitePreferences']) {
if (site.url === currentUrl && inputField.validity.valid && inputField.value !== currentUrl) {
if (slashNeededForUrl(inputField.value)) {
inputField.value += '/';
}
site.url = inputField.value;
row.setAttribute('url', inputField.value);
exitEditMode(e, row, inputField, editButton, cancelButton, saveButton);
options.saveSettings();
return;
}
}
};
const checkboxClicked = function() {
const closestTr = this.closest('tr');
const url = closestTr.getAttribute('url');
@ -565,7 +619,35 @@ options.initSitePreferences = function() {
const row = rowClone.cloneNode(true);
row.setAttribute('url', url);
row.setAttribute('id', 'tr-scf' + newIndex);
row.children[0].textContent = url;
// Handle listeners for Edit/Cancel/Save buttons
const inputField = row?.querySelector('input#editUrl');
const editButton = row?.querySelector('button#sitePreferencesEditUrl');
const cancelButton = row?.querySelector('button#sitePreferencesCancelEdit');
const saveButton = row?.querySelector('button#sitePreferencesSaveEdit');
inputField?.addEventListener('keyup', (e) => {
if (e.key === 'Enter') {
saveModifiedUrl(e, row, inputField, editButton, cancelButton, saveButton);
} else if (e.key === 'Escape') {
exitEditMode(e, row, inputField, editButton, cancelButton, saveButton);
} else {
saveButton.disabled = !inputField.validity.valid || inputField.value === url;
}
});
editButton?.addEventListener('click', (e) =>
enterEditMode(e, row, inputField, editButton, cancelButton, saveButton)
);
cancelButton?.addEventListener('click', (e) =>
exitEditMode(e, row, inputField, editButton, cancelButton, saveButton)
);
saveButton?.addEventListener('click', (e) =>
saveModifiedUrl(e, row, inputField, editButton, cancelButton, saveButton)
);
row.children[0].children[0].children[0].value = url;
row.children[0].children[0]?.addEventListener('dblclick', (e) =>
enterEditMode(e, row, inputField, editButton, cancelButton, saveButton)
);
row.children[1].children[0].value = ignore;
row.children[1].children[0].addEventListener('change', selectionChanged);
row.children[2].children['usernameOnly'].checked = usernameOnly;