Skip to content

Commit

Permalink
Merge pull request #18936 from itisAliRH/workflow-license-creator-key…
Browse files Browse the repository at this point in the history
…board
  • Loading branch information
itisAliRH authored Nov 18, 2024
2 parents 4a7c220 + 37b4fa4 commit 455da5c
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 148 deletions.
232 changes: 107 additions & 125 deletions client/src/components/License/LicenseSelector.vue
Original file line number Diff line number Diff line change
@@ -1,130 +1,112 @@
<script setup lang="ts">
import { watchImmediate } from "@vueuse/core";
import { BAlert } from "bootstrap-vue";
import { computed, ref } from "vue";
import Multiselect from "vue-multiselect";
import { GalaxyApi } from "@/api";
import { type components } from "@/api/schema";
import { errorMessageAsString } from "@/utils/simple-error";
import License from "@/components/License/License.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
const defaultLicense: LicenseType = {
licenseId: null,
name: "*Do not specify a license.*",
};
type LicenseMetadataModel = components["schemas"]["LicenseMetadataModel"];
type LicenseType = {
licenseId: string | null;
name: string;
};
interface Props {
inputLicense: string;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "onLicense", license: string | null): void;
}>();
const licensesLoading = ref(false);
const errorMessage = ref<string>("");
const currentLicense = ref<LicenseType>();
const licenses = ref<LicenseMetadataModel[] | undefined>([]);
const licenseOptions = computed(() => {
const options: LicenseType[] = [];
options.push(defaultLicense);
for (const license of licenses.value || []) {
if (license.licenseId == currentLicense.value?.licenseId || license.recommended) {
options.push({
licenseId: license.licenseId,
name: license.name,
});
}
}
return options;
});
function onLicense(license: LicenseType) {
emit("onLicense", license.licenseId);
}
async function fetchLicenses() {
const { error, data } = await GalaxyApi().GET("/api/licenses");
if (error) {
errorMessage.value = errorMessageAsString(error) || "Unable to fetch licenses.";
}
licenses.value = data;
licensesLoading.value = false;
}
async function setCurrentLicense() {
if (!licenses.value?.length && !licensesLoading.value) {
licensesLoading.value = true;
await fetchLicenses();
}
const inputLicense = props.inputLicense;
currentLicense.value = (licenses.value || []).find((l) => l.licenseId == inputLicense) || defaultLicense;
}
watchImmediate(
() => props.inputLicense,
() => {
setCurrentLicense();
}
);
</script>

<template>
<div v-if="editLicense">
<LoadingSpan v-if="licensesLoading" message="Loading licenses..." />
<b-form-select
<div>
<BAlert v-if="licensesLoading" variant="info" class="m-0" show>
<LoadingSpan message="Loading licenses" />
</BAlert>
<BAlert v-else-if="errorMessage" variant="danger" class="m-0" show>
{{ errorMessage }}
</BAlert>
<Multiselect
v-else
v-model="license"
v-model="currentLicense"
data-description="license select"
:options="licenseOptions"></b-form-select>
<License v-if="currentLicenseInfo" :license-id="license" :input-license-info="currentLicenseInfo">
<template v-slot:buttons>
<span v-b-tooltip.hover title="Save License"
><FontAwesomeIcon data-description="license save" icon="save" @click="onSave"
/></span>
<span v-b-tooltip.hover title="Cancel Edit"><FontAwesomeIcon icon="times" @click="disableEdit" /></span>
</template>
</License>
<div v-else>
<a href="#" @click.prevent="onSave">Save without license</a> or
<a href="#" @click.prevent="editLicense = false">cancel edit.</a>
</div>
</div>
<div v-else-if="license" data-description="license selector" :data-license="license">
<License :license-id="license">
<template v-slot:buttons>
<span v-b-tooltip.hover title="Edit License"
><FontAwesomeIcon icon="edit" data-description="edit license link" @click="editLicense = true"
/></span>
</template>
</License>
</div>
<div v-else data-description="license selector" data-license="null">
<i
><a href="#" data-description="edit license link" @click.prevent="editLicense = true"
>Specify a license for this workflow.</a
></i
>
track-by="licenseId"
:options="licenseOptions"
label="name"
placeholder="Select a license"
@select="onLicense" />
<License v-if="currentLicense?.licenseId" :license-id="currentLicense.licenseId" />
</div>
</template>

<script>
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEdit, faSave, faTimes } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import axios from "axios";
import BootstrapVue from "bootstrap-vue";
import LoadingSpan from "components/LoadingSpan";
import { getAppRoot } from "onload/loadConfig";
import Vue from "vue";
import License from "./License";
library.add(faSave);
library.add(faTimes);
library.add(faEdit);
Vue.use(BootstrapVue);
export default {
components: { License, LoadingSpan, FontAwesomeIcon },
props: {
inputLicense: {
type: String,
},
},
data() {
return {
license: this.inputLicense || null,
licensesLoading: false,
licenses: [],
editLicense: false,
};
},
computed: {
currentLicenseInfo() {
for (const license of this.licenses) {
if (license.licenseId == this.license) {
return license;
}
}
return null;
},
licenseOptions() {
const options = [];
options.push({
value: null,
text: "*Do not specify a license.*",
});
for (const license of this.licenses) {
if (license.licenseId == this.license || license.recommended) {
options.push({
value: license.licenseId,
text: license.name,
});
}
}
return options;
},
},
watch: {
inputLicense() {
this.license = this.inputLicense;
},
},
mounted() {
const url = `${getAppRoot()}api/licenses`;
axios
.get(url)
.then((response) => response.data)
.then((data) => {
this.licenses = data;
this.licensesLoading = false;
})
.catch((e) => {
console.error(e);
});
},
methods: {
onSave() {
this.onLicense(this.license);
this.disableEdit();
},
disableEdit() {
this.editLicense = false;
},
onLicense(license) {
this.$emit("onLicense", license);
},
},
};
</script>
24 changes: 18 additions & 6 deletions client/src/components/SchemaOrg/CreatorEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@
<div v-for="(creator, index) in creatorsCurrent" :key="index">
<CreatorViewer :creator="creator">
<template v-slot:buttons>
<span v-b-tooltip.hover title="Edit Creator"
><FontAwesomeIcon icon="edit" @click="onEdit(index)"
/></span>
<span v-b-tooltip.hover title="Remove Creator">
<FontAwesomeIcon icon="times" @click="onRemove(index)" />
</span>
<BButton
v-b-tooltip.hover
class="inline-icon-button"
variant="link"
size="sm"
title="Edit Creator"
@click="onEdit(index)">
<FontAwesomeIcon icon="edit" />
</BButton>
<BButton
v-b-tooltip.hover
class="inline-icon-button"
variant="link"
size="sm"
title="Remove Creator"
@click="onRemove(index)">
<FontAwesomeIcon icon="times" />
</BButton>
</template>
</CreatorViewer>
</div>
Expand Down
13 changes: 4 additions & 9 deletions client/src/utils/navigation/navigation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -747,15 +747,10 @@ workflow_editor:
canvas_body: '#workflow-canvas'
edit_annotation: '#workflow-annotation'
edit_name: '#workflow-name'
license_selector:
selector: 'license selector'
type: data-description
edit_license_link:
selector: 'edit license link'
type: data-description
license_select:
selector: 'license select'
type: data-description
license_selector: '[data-description="license select"]'
license_current_value: '[data-description="license select"] .multiselect__single'
license_selector_input: '[data-description="license select"] input.multiselect__input'
license_selector_option: '[data-description="license select"] .multiselect__element'
license_save:
selector: 'license save'
type: data-description
Expand Down
11 changes: 6 additions & 5 deletions lib/galaxy/selenium/navigates_galaxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,11 +1204,12 @@ def rule_builder_enter_source_text(self, json):
text_area_elem.send_keys(json)

def workflow_editor_set_license(self, license: str) -> None:
editor = self.components.workflow_editor
editor.edit_license_link.wait_for_and_click()
select = editor.license_select.wait_for_select()
select.select_by_value(license)
editor.license_save.wait_for_and_click()
license_selector = self.components.workflow_editor.license_selector
license_selector.wait_for_and_click()
license_selector.wait_for_and_send_keys(license)

license_selector_option = self.components.workflow_editor.license_selector_option
license_selector_option.wait_for_and_click()

def workflow_editor_click_option(self, option_label):
self.workflow_editor_click_options()
Expand Down
5 changes: 2 additions & 3 deletions lib/galaxy_test/selenium/test_workflow_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,14 @@ def test_edit_license(self):
name = self.workflow_create_new()
editor.canvas_body.wait_for_visible()
editor.license_selector.wait_for_visible()
editor.license_selector.assert_no_axe_violations_with_impact_of_at_least("serious")
editor.license_selector.assert_data_value("license", "null")
assert "Do not specify" in editor.license_current_value.wait_for_text()

self.workflow_editor_set_license("MIT")
self.workflow_editor_click_save()

self.workflow_index_open_with_name(name)
editor.license_selector.wait_for_visible()
editor.license_selector.assert_data_value("license", "MIT")
assert "MIT" in editor.license_current_value.wait_for_text()

@selenium_test
def test_optional_select_data_field(self):
Expand Down

0 comments on commit 455da5c

Please sign in to comment.