mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'release_25.0' into dev
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user