Merge branch 'release_25.0' into dev

This commit is contained in:
Nicola Soranzo
2025-06-22 15:26:46 +01:00
7 changed files with 65 additions and 42 deletions
@@ -67,8 +67,10 @@ function revertToOriginal() {
v-model="localValue"
class="w-100 input-with-icon"
tabindex="0"
title="Press enter/return to save, esc to revert changes"
contenteditable
max-rows="4"
aria-label="Press enter/return to save, esc to revert changes"
@blur.prevent.stop="onBlur"
@keyup.prevent.stop.enter="editable = false"
@keyup.prevent.stop.escape="revertToOriginal"
@@ -17,6 +17,7 @@ defineProps<Props>();
:name="dsc.name ?? ''"
:tags="dsc.tags"
:writeable="writeable"
:renameable="writeable"
:show-annotation="false"
@save="$emit('update:dsc', $event)">
<template v-slot:description>
@@ -7,11 +7,15 @@ import DetailsLayout from "./DetailsLayout";
const localVue = getLocalVue();
async function createWrapper(component, localVue, userData) {
async function createWrapper(component, localVue, userData, unwritable = false) {
const pinia = createPinia();
const wrapper = mount(component, {
localVue,
pinia,
propsData: {
writeable: !unwritable,
renameable: !unwritable,
},
});
const userStore = useUserStore();
userStore.currentUser = { ...userStore.currentUser, ...userData };
@@ -19,18 +23,39 @@ async function createWrapper(component, localVue, userData) {
}
describe("DetailsLayout", () => {
it("allows logged-in users to edit details", async () => {
it("allows logged-in users to edit all details", async () => {
const wrapper = await createWrapper(DetailsLayout, localVue, {
id: "user.id",
email: "user.email",
});
expect(wrapper.find(".edit-button").attributes("title")).toBe("Edit");
// Click to edit and rename
expect(wrapper.find(".click-to-edit-label").exists()).toBe(true);
});
it("prompts anonymous users to log in", async () => {
it("prompts anonymous users to log in to edit all details, but allows rename", async () => {
const wrapper = await createWrapper(DetailsLayout, localVue, {});
expect(wrapper.find(".edit-button").attributes("title")).toContain("Log in");
// Click to edit and rename should still be available
expect(wrapper.find(".click-to-edit-label").exists()).toBe(true);
});
it("disallows editing and renaming if props set them to false", async () => {
const wrapper = await createWrapper(
DetailsLayout,
localVue,
{
id: "user.id",
email: "user.email",
},
true
);
expect(wrapper.find(".edit-button").attributes("title")).toContain("Not Editable");
expect(wrapper.find(".click-to-edit-label").exists()).toBe(false);
});
});
@@ -21,6 +21,7 @@ interface Props {
name?: string;
tags?: string[];
writeable?: boolean;
renameable?: boolean;
annotation?: string;
showAnnotation?: boolean;
summarized?: DetailsLayoutSummarized;
@@ -30,6 +31,7 @@ const props = withDefaults(defineProps<Props>(), {
name: undefined,
tags: undefined,
writeable: true,
renameable: true,
annotation: undefined,
showAnnotation: true,
summarized: undefined,
@@ -119,14 +121,19 @@ function selectText() {
<template>
<section :class="detailsClass" data-description="edit details">
<div class="d-flex justify-content-between w-100">
<ClickToEdit
v-if="!summarized && !editing"
v-model="clickToEditName"
component="h3"
title="..."
data-description="name display"
no-save-on-blur
class="my-2 w-100" />
<template v-if="!summarized && !editing">
<ClickToEdit
v-if="renameable"
v-model="clickToEditName"
component="h3"
title="..."
data-description="name display"
no-save-on-blur
class="my-2 w-100" />
<h3 v-else class="my-2 w-100">
{{ props.name || "..." }}
</h3>
</template>
<div v-else style="max-width: 80%">
<TextSummary
:description="name"
+19 -10
View File
@@ -34,18 +34,27 @@ simpleversioning_versions = [
# Additional versions added below
]
# Used for determining the latest stable release so the banner can be added to older releases.
_stable = None
# Use tags to determine versions - a stable version will have a branch before it's released, but not a tag.
tags = check_output(("git", "tag")).decode().splitlines()
for _tag in reversed(tags):
if _tag.startswith("v") and _tag.count(".") == 1:
# this version is released
_ver = _tag[1:]
if not _stable:
_stable = _ver
if Version(_ver) >= MIN_DOC_VERSION:
simpleversioning_versions.append({"id": f"release_{_ver}", "name": _ver})
found_versions = []
for _tag in sorted(tags, reverse=True):
if not _tag.startswith("v"):
continue
_ver_parts = _tag[1:].split(".")
if len(_ver_parts) == 1:
# No "."
continue
# Keep only major and minor version numbers
_ver = ".".join(_ver_parts[:2])
if Version(_ver) < MIN_DOC_VERSION:
continue
if _ver in found_versions:
continue
found_versions.append(_ver)
simpleversioning_versions.append({"id": f"release_{_ver}", "name": _ver})
# The latest stable release
_stable = found_versions[0] if found_versions else None
if re.fullmatch(r"release_\d{2}\.\d{1,2}", TARGET_GIT_BRANCH):
if _stable:
-12
View File
@@ -84,14 +84,6 @@ class Image(data.Data):
optional=True,
)
MetadataElement(
name="num_unique_values",
desc="Number of unique values in the image data (e.g., should be 2 for binary images)",
readonly=True,
visible=True,
optional=True,
)
MetadataElement(
name="width",
desc="Width of the image (in pixels)",
@@ -271,7 +263,6 @@ class Tiff(Image):
"channels",
"depth",
"frames",
"num_unique_values",
]
}
@@ -289,9 +280,6 @@ class Tiff(Image):
metadata["depth"].append(Tiff._get_axis_size(series.shape, axes, "Z"))
metadata["frames"].append(Tiff._get_axis_size(series.shape, axes, "T"))
# Determine the metadata values that require reading the image data
metadata["num_unique_values"].append(Tiff._get_num_unique_values(series))
# Populate the metadata fields based on the values determined above
for key, values in metadata.items():
if len(values) > 0:
-9
View File
@@ -52,7 +52,6 @@ def __assert_empty_metadata(metadata):
for key in (
"axes",
"dtype",
"num_unique_values",
"width",
"height",
"channels",
@@ -69,8 +68,6 @@ test_tiff_axes_zcyx = __create_test(Tiff, "im6_uint8.tif", "axes", "ZCYX")
test_tiff_dtype_uint8 = __create_test(Tiff, "im6_uint8.tif", "dtype", "uint8")
test_tiff_dtype_uint16 = __create_test(Tiff, "im8_uint16.tif", "dtype", "uint16")
test_tiff_dtype_float64 = __create_test(Tiff, "im4_float.tif", "dtype", "float64")
test_tiff_num_unique_values_2 = __create_test(Tiff, "im3_b.tif", "num_unique_values", 2)
test_tiff_num_unique_values_618 = __create_test(Tiff, "im4_float.tif", "num_unique_values", 618)
test_tiff_width_16 = __create_test(Tiff, "im7_uint8.tif", "width", 16) # axes: ZYX
test_tiff_width_32 = __create_test(Tiff, "im3_b.tif", "width", 32) # axes: YXS
test_tiff_height_8 = __create_test(Tiff, "im7_uint8.tif", "height", 8) # axes: ZYX
@@ -100,15 +97,11 @@ def test_tiff_unsupported_compression(metadata):
assert metadata.depth == 0
assert metadata.frames == 0
# The other fields should be missing
assert getattr(metadata, "num_unique_values", None) is None
@__test(Tiff, "im9_multiseries.tif")
def test_tiff_multiseries(metadata):
assert metadata.axes == ["YXS", "YX"]
assert metadata.dtype == ["uint8", "uint16"]
assert metadata.num_unique_values == [2, 255]
assert metadata.width == [32, 256]
assert metadata.height == [32, 256]
assert metadata.channels == [3, 0]
@@ -121,8 +114,6 @@ def test_tiff_multiseries(metadata):
test_png_axes_yx = __create_test(Image, "im1_uint8.png", "axes", "YX")
test_png_axes_yxc = __create_test(Image, "im3_a.png", "axes", "YXC")
test_png_dtype_uint8 = __create_test(Image, "im1_uint8.png", "dtype", "uint8")
test_png_num_unique_values_1 = __create_test(Image, "im2_a.png", "num_unique_values", None)
test_png_num_unique_values_2 = __create_test(Image, "im2_b.png", "num_unique_values", None)
test_png_width_32 = __create_test(Image, "im2_b.png", "width", 32)
test_png_height_32 = __create_test(Image, "im2_b.png", "height", 32)
test_png_channels_0 = __create_test(Image, "im1_uint8.png", "channels", 0)