Support Displayname property override

This commit is contained in:
Max Berger
2026-03-18 21:18:59 +01:00
parent 99e9b7ec56
commit f4dd3c5d50
4 changed files with 49 additions and 7 deletions

View File

@@ -140,14 +140,22 @@ def test_share_with_property_overrides(page: Page, radicale_server: str) -> None
page.click('button[data-name="sharebytoken"]') page.click('button[data-name="sharebytoken"]')
# Verify defaults # Verify defaults
expect(page.locator('input[data-name="displayname_override"]')).to_have_value(
"Test Collection"
)
expect(page.locator('input[data-name="description_override"]')).to_have_value( expect(page.locator('input[data-name="description_override"]')).to_have_value(
"Original Description" "Original Description"
) )
expect(page.locator('input[data-name="color_override"]')).to_have_value("#ff0000") expect(page.locator('input[data-name="color_override"]')).to_have_value("#ff0000")
expect(page.locator('input[data-name="displayname_override"]')).to_be_disabled()
expect(page.locator('input[data-name="description_override"]')).to_be_disabled() expect(page.locator('input[data-name="description_override"]')).to_be_disabled()
expect(page.locator('input[data-name="color_override"]')).to_be_disabled() expect(page.locator('input[data-name="color_override"]')).to_be_disabled()
# Set overrides # Set overrides
page.click('label[for="newshare_attr_displayname_enabled"]')
page.locator('input[data-name="displayname_override"]').fill(
"Overridden Displayname"
)
page.click('label[for="newshare_attr_description_enabled"]') page.click('label[for="newshare_attr_description_enabled"]')
page.locator('input[data-name="description_override"]').fill( page.locator('input[data-name="description_override"]').fill(
"Overridden Description" "Overridden Description"
@@ -182,8 +190,11 @@ def test_share_journal_no_overrides(page: Page, radicale_server: str) -> None:
page.click('article:not(.hidden) a[data-name="share"]', force=True, strict=True) page.click('article:not(.hidden) a[data-name="share"]', force=True, strict=True)
page.click('button[data-name="sharebytoken"]') page.click('button[data-name="sharebytoken"]')
# Verify property override fieldset is hidden # Verify property override visibility
expect(page.locator('fieldset[data-name="properties_override"]')).to_be_hidden() expect(page.locator('fieldset[data-name="properties_override"]')).to_be_visible()
expect(page.locator('input[data-name="displayname_override_enabled"]')).to_be_visible()
expect(page.locator('input[data-name="description_override_enabled"]')).to_be_hidden()
expect(page.locator('input[data-name="color_override_enabled"]')).to_be_hidden()
# Create the share # Create the share
page.click('#newshare button[data-name="submit"]') page.click('#newshare button[data-name="submit"]')

View File

@@ -262,6 +262,11 @@
</fieldset> </fieldset>
<fieldset data-name="properties_override"> <fieldset data-name="properties_override">
<legend>Properties override</legend> <legend>Properties override</legend>
<div class="property-override">
<input type="checkbox" data-name="displayname_override_enabled" id="newshare_attr_displayname_enabled">
<label for="newshare_attr_displayname_enabled">Displayname:</label>
<input type="text" data-name="displayname_override" disabled>
</div>
<div class="property-override"> <div class="property-override">
<input type="checkbox" data-name="description_override_enabled" id="newshare_attr_description_enabled"> <input type="checkbox" data-name="description_override_enabled" id="newshare_attr_description_enabled">
<label for="newshare_attr_description_enabled">Description:</label> <label for="newshare_attr_description_enabled">Description:</label>

View File

@@ -182,10 +182,13 @@ export const OVERLAY_PROPERTIES = {
/** /**
* Returns the correct internal property key for a given collection type and property name. * Returns the correct internal property key for a given collection type and property name.
* @param {string} type Collection type (ADDRESSBOOK, CALENDAR, etc.) * @param {string} type Collection type (ADDRESSBOOK, CALENDAR, etc.)
* @param {"DESCRIPTION" | "COLOR"} property Property name * @param {"DISPLAYNAME" | "DESCRIPTION" | "COLOR"} property Property name
* @returns {string | null} Internal property key or null if not supported * @returns {string | null} Internal property key or null if not supported
*/ */
export function get_property_key(type, property) { export function get_property_key(type, property) {
if (property === "DISPLAYNAME") {
return "D:displayname";
}
if (type === CollectionType.ADDRESSBOOK) { if (type === CollectionType.ADDRESSBOOK) {
return OVERLAY_PROPERTIES.ADDRESSBOOK[property]; return OVERLAY_PROPERTIES.ADDRESSBOOK[property];
} else if (CollectionType.is_subset(CollectionType.CALENDAR, type)) { } else if (CollectionType.is_subset(CollectionType.CALENDAR, type)) {

View File

@@ -52,6 +52,8 @@ export class CreateEditShareScene {
let permissions_rw_radio = /** @type {HTMLInputElement} */ (document.getElementById("newshare_attr_permissions_rw")); let permissions_rw_radio = /** @type {HTMLInputElement} */ (document.getElementById("newshare_attr_permissions_rw"));
/** @type {HTMLElement} */ let properties_fieldset = html_scene.querySelector("[data-name=properties_override]"); /** @type {HTMLElement} */ let properties_fieldset = html_scene.querySelector("[data-name=properties_override]");
/** @type {HTMLInputElement} */ let displayname_override_enabled = html_scene.querySelector("[data-name=displayname_override_enabled]");
/** @type {HTMLInputElement} */ let displayname_override_input = html_scene.querySelector("[data-name=displayname_override]");
/** @type {HTMLInputElement} */ let description_override_enabled = html_scene.querySelector("[data-name=description_override_enabled]"); /** @type {HTMLInputElement} */ let description_override_enabled = html_scene.querySelector("[data-name=description_override_enabled]");
/** @type {HTMLInputElement} */ let description_override_input = html_scene.querySelector("[data-name=description_override]"); /** @type {HTMLInputElement} */ let description_override_input = html_scene.querySelector("[data-name=description_override]");
/** @type {HTMLInputElement} */ let color_override_enabled = html_scene.querySelector("[data-name=color_override_enabled]"); /** @type {HTMLInputElement} */ let color_override_enabled = html_scene.querySelector("[data-name=color_override_enabled]");
@@ -69,6 +71,9 @@ export class CreateEditShareScene {
sharehref_input.addEventListener("input", onCleanHREFinput); sharehref_input.addEventListener("input", onCleanHREFinput);
displayname_override_enabled.onchange = function () {
displayname_override_input.disabled = !displayname_override_enabled.checked;
};
description_override_enabled.onchange = function () { description_override_enabled.onchange = function () {
description_override_input.disabled = !description_override_enabled.checked; description_override_input.disabled = !description_override_enabled.checked;
}; };
@@ -98,6 +103,10 @@ export class CreateEditShareScene {
let permissions = permissions_rw_radio.checked ? "rw" : "r"; let permissions = permissions_rw_radio.checked ? "rw" : "r";
let properties = {}; let properties = {};
if (displayname_override_enabled.checked) {
let key = get_property_key(collection.type, "DISPLAYNAME");
if (key) properties[key] = displayname_override_input.value;
}
if (description_override_enabled.checked) { if (description_override_enabled.checked) {
let key = get_property_key(collection.type, "DESCRIPTION"); let key = get_property_key(collection.type, "DESCRIPTION");
if (key) properties[key] = description_override_input.value; if (key) properties[key] = description_override_input.value;
@@ -166,19 +175,26 @@ export class CreateEditShareScene {
permissions_ro_radio.checked = edit ? share.Permissions.toLowerCase() === "r" : true; permissions_ro_radio.checked = edit ? share.Permissions.toLowerCase() === "r" : true;
permissions_rw_radio.checked = edit ? share.Permissions.toLowerCase() === "rw" : false; permissions_rw_radio.checked = edit ? share.Permissions.toLowerCase() === "rw" : false;
let displayname = collection.displayname || "";
let description = collection.description || ""; let description = collection.description || "";
let color = collection.color || "#ffffff"; let color = collection.color || "#ffffff";
let displayname_override_enabled_value = false;
let description_override_enabled_value = false; let description_override_enabled_value = false;
let color_override_enabled_value = false; let color_override_enabled_value = false;
if (edit && share.Properties) { if (edit && share.Properties) {
let displayname_key = get_property_key(collection.type, "DISPLAYNAME");
if (displayname_key && share.Properties[displayname_key] !== undefined) {
displayname = share.Properties[displayname_key];
displayname_override_enabled_value = true;
}
let description_key = get_property_key(collection.type, "DESCRIPTION"); let description_key = get_property_key(collection.type, "DESCRIPTION");
if (description_key && share.Properties[description_key]) { if (description_key && share.Properties[description_key] !== undefined) {
description = share.Properties[description_key]; description = share.Properties[description_key];
description_override_enabled_value = true; description_override_enabled_value = true;
} }
let color_key = get_property_key(collection.type, "COLOR"); let color_key = get_property_key(collection.type, "COLOR");
if (color_key && share.Properties[color_key]) { if (color_key && share.Properties[color_key] !== undefined) {
color = share.Properties[color_key]; color = share.Properties[color_key];
if (color.length === 9 && color.endsWith("ff")) { if (color.length === 9 && color.endsWith("ff")) {
color = color.substring(0, 7); color = color.substring(0, 7);
@@ -187,6 +203,10 @@ export class CreateEditShareScene {
} }
} }
displayname_override_enabled.checked = displayname_override_enabled_value;
displayname_override_input.value = displayname;
displayname_override_input.disabled = !displayname_override_enabled_value;
description_override_enabled.checked = description_override_enabled_value; description_override_enabled.checked = description_override_enabled_value;
description_override_input.value = description; description_override_input.value = description;
description_override_input.disabled = !description_override_enabled_value; description_override_input.disabled = !description_override_enabled_value;
@@ -197,10 +217,13 @@ export class CreateEditShareScene {
let is_calendar = CollectionType.is_subset(CollectionType.CALENDAR, collection.type); let is_calendar = CollectionType.is_subset(CollectionType.CALENDAR, collection.type);
let is_addressbook = collection.type === CollectionType.ADDRESSBOOK; let is_addressbook = collection.type === CollectionType.ADDRESSBOOK;
properties_fieldset.classList.remove("hidden");
if (is_calendar || is_addressbook) { if (is_calendar || is_addressbook) {
properties_fieldset.classList.remove("hidden"); description_override_enabled.parentElement.classList.remove("hidden");
color_override_enabled.parentElement.classList.remove("hidden");
} else { } else {
properties_fieldset.classList.add("hidden"); description_override_enabled.parentElement.classList.add("hidden");
color_override_enabled.parentElement.classList.add("hidden");
} }
if (shareType === "map") { if (shareType === "map") {