Loading .github/workflows/lint_openapi_schema.yml +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: actions/setup-node@v4 with: node-version: '18.12.1' cache: 'yarn' cache-dependency-path: 'galaxy root/client/yarn.lock' - name: Get full Python version id: full-python-version shell: bash Loading client/src/api/schema/schema.ts +12 −1 Original line number Diff line number Diff line Loading @@ -5648,6 +5648,15 @@ export interface components { */ url: string; }; /** GroupUpdatePayload */ GroupUpdatePayload: { /** name of the group */ name?: string | null; /** role IDs */ role_ids?: string[] | null; /** user IDs */ user_ids?: string[] | null; }; /** GroupUserListResponse */ GroupUserListResponse: components["schemas"]["GroupUserResponse"][]; /** GroupUserResponse */ Loading Loading @@ -6282,6 +6291,8 @@ export interface components { * @enum {string} */ model_class: "HistoryDatasetAssociation"; /** Purged */ purged: boolean; /** * State * @description The current state of this dataset. Loading Loading @@ -15969,7 +15980,7 @@ export interface operations { }; requestBody: { content: { "application/json": components["schemas"]["GroupCreatePayload"]; "application/json": components["schemas"]["GroupUpdatePayload"]; }; }; responses: { client/src/components/Form/Elements/FormData/FormData.test.js +4 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ import { mount } from "@vue/test-utils"; import { PiniaVuePlugin } from "pinia"; import { dispatchEvent, getLocalVue } from "tests/jest/helpers"; import { testDatatypesMapper } from "@/components/Datatypes/test_fixtures"; import { useDatatypesMapperStore } from "@/stores/datatypesMapperStore"; import { useEventStore } from "@/stores/eventStore"; import MountTarget from "./FormData.vue"; Loading @@ -15,6 +17,8 @@ let eventStore; function createTarget(propsData) { const pinia = createTestingPinia({ stubActions: false }); eventStore = useEventStore(); const datatypesStore = useDatatypesMapperStore(); datatypesStore.datatypesMapper = testDatatypesMapper; return mount(MountTarget, { localVue, propsData, Loading client/src/components/Form/Elements/FormData/FormData.vue +62 −12 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import { BAlert, BButton, BButtonGroup, BCollapse, BFormCheckbox, BTooltip } fro import { computed, onMounted, type Ref, ref, watch } from "vue"; import { getGalaxyInstance } from "@/app"; import { useDatatypesMapper } from "@/composables/datatypesMapper"; import { useUid } from "@/composables/utils/uid"; import { type EventData, useEventStore } from "@/stores/eventStore"; import { orList } from "@/utils/strings"; Loading Loading @@ -35,6 +36,7 @@ const props = withDefaults( }; extensions?: Array<string>; type?: string; collectionTypes?: Array<string>; flavor?: string; tag?: string; }>(), Loading @@ -45,14 +47,16 @@ const props = withDefaults( value: undefined, extensions: () => [], type: "data", collectionTypes: undefined, flavor: undefined, tag: undefined, } ); const eventStore = useEventStore(); const { datatypesMapper } = useDatatypesMapper(); const $emit = defineEmits(["input"]); const $emit = defineEmits(["input", "alert"]); // Determines wether values should be processed as linked or unlinked const currentLinked = ref(true); Loading Loading @@ -302,6 +306,10 @@ function getSourceType(val: DataOption) { function handleIncoming(incoming: Record<string, unknown>, partial = true) { if (incoming) { const values = Array.isArray(incoming) ? incoming : [incoming]; const extensions = values.map((v) => v.extension || v.elements_datatypes).filter((v) => (v ? true : false)); if (!canAcceptDatatype(extensions)) { return false; } if (values.length > 0) { const incomingValues: Array<DataOption> = []; values.forEach((v) => { Loading @@ -311,14 +319,28 @@ function handleIncoming(incoming: Record<string, unknown>, partial = true) { const newName = v.name ? v.name : newId; const newSrc = v.src || (v.history_content_type === "dataset_collection" ? SOURCE.COLLECTION : SOURCE.DATASET); const newValue = { const newValue: DataOption = { id: newId, src: newSrc, batch: false, map_over_type: undefined, hid: newHid, name: newName, keep: true, tags: [], }; if (v.collection_type && props.collectionTypes?.length > 0) { if (!props.collectionTypes.includes(v.collection_type)) { const mapOverType = props.collectionTypes.find((collectionType) => v.collection_type.endsWith(collectionType) ); if (!mapOverType) { return false; } newValue["batch"] = true; newValue["map_over_type"] = mapOverType; } } // Verify that new value has corresponding option const keepKey = `${newId}_${newSrc}`; const existingOptions = props.options && props.options[newSrc]; Loading Loading @@ -349,6 +371,7 @@ function handleIncoming(incoming: Record<string, unknown>, partial = true) { } } } return true; } /** Loading @@ -372,10 +395,36 @@ function onBrowse() { } } function canAcceptDatatype(itemDatatypes: string | Array<string>) { if (!(props.extensions?.length > 0)) { return true; } let datatypes: Array<string>; if (!Array.isArray(itemDatatypes)) { datatypes = [itemDatatypes]; } else { datatypes = itemDatatypes; } const incompatibleItem = datatypes.find( (extension) => !datatypesMapper.value?.isSubTypeOfAny(extension, props.extensions) ); if (incompatibleItem) { return false; } return true; } // Drag/Drop event handlers function onDragEnter(evt: MouseEvent) { const eventData = eventStore.getDragData(); if (eventData) { const extensions = (eventData.extension as string) || (eventData.elements_datatypes as Array<string>); if (!canAcceptDatatype(extensions)) { currentHighlighting.value = "warning"; $emit("alert", `${extensions} is not an acceptable format for this parameter.`); } else { currentHighlighting.value = "success"; } dragTarget.value = evt.target; dragData.value = eventData; } Loading @@ -384,23 +433,24 @@ function onDragEnter(evt: MouseEvent) { function onDragLeave(evt: MouseEvent) { if (dragTarget.value === evt.target) { currentHighlighting.value = null; } } function onDragOver() { if (dragData.value !== null) { currentHighlighting.value = "warning"; $emit("alert", undefined); } } function onDrop() { if (dragData.value) { let accept = false; if (eventStore.multipleDragData) { handleIncoming(Object.values(dragData.value) as any, false); accept = handleIncoming(Object.values(dragData.value) as any, false); } else { handleIncoming(dragData.value); accept = handleIncoming(dragData.value); } if (accept) { currentHighlighting.value = "success"; } else { currentHighlighting.value = "warning"; } $emit("alert", undefined); dragData.value = null; clearHighlighting(); } Loading Loading @@ -468,7 +518,7 @@ const noOptionsWarningMessage = computed(() => { :class="currentHighlighting && `ui-dragover-${currentHighlighting}`" @dragenter.prevent="onDragEnter" @dragleave.prevent="onDragLeave" @dragover.prevent="onDragOver" @dragover.prevent @drop.prevent="onDrop"> <div class="d-flex flex-column"> <BButtonGroup v-if="variant && variant.length > 1" buttons class="align-self-start"> Loading client/src/components/Form/Elements/FormData/types.ts +1 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ export type DataOption = { hid: number; is_dataset?: boolean; keep: boolean; batch: boolean; map_over_type?: string; name: string; src: string; Loading Loading
.github/workflows/lint_openapi_schema.yml +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: actions/setup-node@v4 with: node-version: '18.12.1' cache: 'yarn' cache-dependency-path: 'galaxy root/client/yarn.lock' - name: Get full Python version id: full-python-version shell: bash Loading
client/src/api/schema/schema.ts +12 −1 Original line number Diff line number Diff line Loading @@ -5648,6 +5648,15 @@ export interface components { */ url: string; }; /** GroupUpdatePayload */ GroupUpdatePayload: { /** name of the group */ name?: string | null; /** role IDs */ role_ids?: string[] | null; /** user IDs */ user_ids?: string[] | null; }; /** GroupUserListResponse */ GroupUserListResponse: components["schemas"]["GroupUserResponse"][]; /** GroupUserResponse */ Loading Loading @@ -6282,6 +6291,8 @@ export interface components { * @enum {string} */ model_class: "HistoryDatasetAssociation"; /** Purged */ purged: boolean; /** * State * @description The current state of this dataset. Loading Loading @@ -15969,7 +15980,7 @@ export interface operations { }; requestBody: { content: { "application/json": components["schemas"]["GroupCreatePayload"]; "application/json": components["schemas"]["GroupUpdatePayload"]; }; }; responses: {
client/src/components/Form/Elements/FormData/FormData.test.js +4 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ import { mount } from "@vue/test-utils"; import { PiniaVuePlugin } from "pinia"; import { dispatchEvent, getLocalVue } from "tests/jest/helpers"; import { testDatatypesMapper } from "@/components/Datatypes/test_fixtures"; import { useDatatypesMapperStore } from "@/stores/datatypesMapperStore"; import { useEventStore } from "@/stores/eventStore"; import MountTarget from "./FormData.vue"; Loading @@ -15,6 +17,8 @@ let eventStore; function createTarget(propsData) { const pinia = createTestingPinia({ stubActions: false }); eventStore = useEventStore(); const datatypesStore = useDatatypesMapperStore(); datatypesStore.datatypesMapper = testDatatypesMapper; return mount(MountTarget, { localVue, propsData, Loading
client/src/components/Form/Elements/FormData/FormData.vue +62 −12 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import { BAlert, BButton, BButtonGroup, BCollapse, BFormCheckbox, BTooltip } fro import { computed, onMounted, type Ref, ref, watch } from "vue"; import { getGalaxyInstance } from "@/app"; import { useDatatypesMapper } from "@/composables/datatypesMapper"; import { useUid } from "@/composables/utils/uid"; import { type EventData, useEventStore } from "@/stores/eventStore"; import { orList } from "@/utils/strings"; Loading Loading @@ -35,6 +36,7 @@ const props = withDefaults( }; extensions?: Array<string>; type?: string; collectionTypes?: Array<string>; flavor?: string; tag?: string; }>(), Loading @@ -45,14 +47,16 @@ const props = withDefaults( value: undefined, extensions: () => [], type: "data", collectionTypes: undefined, flavor: undefined, tag: undefined, } ); const eventStore = useEventStore(); const { datatypesMapper } = useDatatypesMapper(); const $emit = defineEmits(["input"]); const $emit = defineEmits(["input", "alert"]); // Determines wether values should be processed as linked or unlinked const currentLinked = ref(true); Loading Loading @@ -302,6 +306,10 @@ function getSourceType(val: DataOption) { function handleIncoming(incoming: Record<string, unknown>, partial = true) { if (incoming) { const values = Array.isArray(incoming) ? incoming : [incoming]; const extensions = values.map((v) => v.extension || v.elements_datatypes).filter((v) => (v ? true : false)); if (!canAcceptDatatype(extensions)) { return false; } if (values.length > 0) { const incomingValues: Array<DataOption> = []; values.forEach((v) => { Loading @@ -311,14 +319,28 @@ function handleIncoming(incoming: Record<string, unknown>, partial = true) { const newName = v.name ? v.name : newId; const newSrc = v.src || (v.history_content_type === "dataset_collection" ? SOURCE.COLLECTION : SOURCE.DATASET); const newValue = { const newValue: DataOption = { id: newId, src: newSrc, batch: false, map_over_type: undefined, hid: newHid, name: newName, keep: true, tags: [], }; if (v.collection_type && props.collectionTypes?.length > 0) { if (!props.collectionTypes.includes(v.collection_type)) { const mapOverType = props.collectionTypes.find((collectionType) => v.collection_type.endsWith(collectionType) ); if (!mapOverType) { return false; } newValue["batch"] = true; newValue["map_over_type"] = mapOverType; } } // Verify that new value has corresponding option const keepKey = `${newId}_${newSrc}`; const existingOptions = props.options && props.options[newSrc]; Loading Loading @@ -349,6 +371,7 @@ function handleIncoming(incoming: Record<string, unknown>, partial = true) { } } } return true; } /** Loading @@ -372,10 +395,36 @@ function onBrowse() { } } function canAcceptDatatype(itemDatatypes: string | Array<string>) { if (!(props.extensions?.length > 0)) { return true; } let datatypes: Array<string>; if (!Array.isArray(itemDatatypes)) { datatypes = [itemDatatypes]; } else { datatypes = itemDatatypes; } const incompatibleItem = datatypes.find( (extension) => !datatypesMapper.value?.isSubTypeOfAny(extension, props.extensions) ); if (incompatibleItem) { return false; } return true; } // Drag/Drop event handlers function onDragEnter(evt: MouseEvent) { const eventData = eventStore.getDragData(); if (eventData) { const extensions = (eventData.extension as string) || (eventData.elements_datatypes as Array<string>); if (!canAcceptDatatype(extensions)) { currentHighlighting.value = "warning"; $emit("alert", `${extensions} is not an acceptable format for this parameter.`); } else { currentHighlighting.value = "success"; } dragTarget.value = evt.target; dragData.value = eventData; } Loading @@ -384,23 +433,24 @@ function onDragEnter(evt: MouseEvent) { function onDragLeave(evt: MouseEvent) { if (dragTarget.value === evt.target) { currentHighlighting.value = null; } } function onDragOver() { if (dragData.value !== null) { currentHighlighting.value = "warning"; $emit("alert", undefined); } } function onDrop() { if (dragData.value) { let accept = false; if (eventStore.multipleDragData) { handleIncoming(Object.values(dragData.value) as any, false); accept = handleIncoming(Object.values(dragData.value) as any, false); } else { handleIncoming(dragData.value); accept = handleIncoming(dragData.value); } if (accept) { currentHighlighting.value = "success"; } else { currentHighlighting.value = "warning"; } $emit("alert", undefined); dragData.value = null; clearHighlighting(); } Loading Loading @@ -468,7 +518,7 @@ const noOptionsWarningMessage = computed(() => { :class="currentHighlighting && `ui-dragover-${currentHighlighting}`" @dragenter.prevent="onDragEnter" @dragleave.prevent="onDragLeave" @dragover.prevent="onDragOver" @dragover.prevent @drop.prevent="onDrop"> <div class="d-flex flex-column"> <BButtonGroup v-if="variant && variant.length > 1" buttons class="align-self-start"> Loading
client/src/components/Form/Elements/FormData/types.ts +1 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ export type DataOption = { hid: number; is_dataset?: boolean; keep: boolean; batch: boolean; map_over_type?: string; name: string; src: string; Loading