Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vueify Generic Form Wrapper #12329

Merged
merged 21 commits into from
Aug 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c1f39f6
Add generic form component, and redirect permissions route
guerler Aug 7, 2021
daad9ff
Remove font awesome important, icons are dynamic
guerler Aug 7, 2021
7aedfc9
Add event handler to generic forms submit operation
guerler Aug 7, 2021
6884674
Replace all form-wrapper instances with form generic vue component, r…
guerler Aug 7, 2021
520eca9
Remove unused legacy condition for specific error highlighting in gen…
guerler Aug 7, 2021
1c27832
Handle title and icon parsing from client in generic form component
guerler Aug 7, 2021
89bef05
Remove unsued custom tooltip option from generic form component
guerler Aug 7, 2021
d1d6c16
Remove unused portlet and message dependencies from form-view
guerler Aug 7, 2021
3bec81d
Fix missing history rename form mounting
guerler Aug 7, 2021
bd74606
Remove unused ui module import in form-view
guerler Aug 8, 2021
28524c7
Add service module to generic form component
guerler Aug 8, 2021
e95a106
Add scrolling, replace vue scroll with js-native instant scrolling
guerler Aug 8, 2021
48ee8b6
Scroll to top of right panel when active node in workflow editor changes
guerler Aug 8, 2021
b279170
Assemble search string without jquery, add id to generic form
guerler Aug 8, 2021
25725bf
Fix selenium test cases, allow parameter replacement in generic forms
guerler Aug 8, 2021
15f6082
Align option parsing to generic form, remove unused props
guerler Aug 8, 2021
d54474d
Remove custom button title for form creator from backend
guerler Aug 8, 2021
18926ad
Remove unused config parsing to redirect option in generic form compo…
guerler Aug 8, 2021
3a2bf1b
Increase spacing between generic form and buttons below
guerler Aug 8, 2021
fb0b4af
Move icon determination to computed values in generic form component
guerler Aug 8, 2021
b8c5c56
Fix tour based selenium test for core galaxy ui
guerler Aug 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
"vue-observe-visibility": "^1.0.0",
"vue-router": "^3.3.1",
"vue-rx": "^6.2.0",
"vue-scrollto": "^2.20.0",
"vuedraggable": "2.24.1",
"vueisotope": "^3.1.2",
"vuex": "^3.4.0",
Expand Down
139 changes: 139 additions & 0 deletions client/src/components/Form/FormGeneric.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<template>
<UrlDataProvider :url="url" v-slot="{ result: config, loading }" @error="onError">
<div :id="id" v-if="!loading">
<b-alert v-if="config.message" :variant="configMessageVariant(config)" show>
{{ config.message }}
</b-alert>
<b-alert v-if="messageText" :variant="messageVariant" show>
{{ messageText }}
</b-alert>
<FormCard :title="configTitle(config)" :icon="configIcon(config)">
<template v-slot:body>
<FormDisplay :inputs="config.inputs" :replace-params="replaceParams" @onChange="onChange" />
</template>
</FormCard>
<div class="mt-3">
<b-button id="submit" variant="primary" class="mr-1" @click="onSubmit()">
<span :class="submitIconClass" />{{ submitTitle | l }}
</b-button>
<b-button v-if="cancelRedirect" @click="onCancel()">
<span class="mr-1 fa fa-times" />{{ "Cancel" | l }}
</b-button>
</div>
</div>
</UrlDataProvider>
</template>

<script>
import { getAppRoot } from "onload/loadConfig";
import { submitData } from "./services";
import { UrlDataProvider } from "components/providers/UrlDataProvider";
import { visitInputs } from "components/Form/utilities";
import FormCard from "components/Form/FormCard";
import FormDisplay from "components/Form/FormDisplay";

export default {
props: {
id: {
type: String,
required: false,
},
title: {
type: String,
required: false,
},
icon: {
type: String,
required: false,
},
submitIcon: {
type: String,
default: "fa-save",
},
submitTitle: {
type: String,
default: "Save",
},
cancelRedirect: {
type: String,
required: false,
},
url: {
type: String,
required: true,
},
redirect: {
type: String,
required: true,
},
},
components: {
FormCard,
FormDisplay,
UrlDataProvider,
},
data() {
return {
messageText: null,
messageVariant: null,
formData: {},
replaceParams: null,
};
},
computed: {
submitIconClass() {
return `mr-1 fa ${this.submitIcon}`;
},
},
methods: {
configTitle(options) {
return this.title || options.title;
},
configIcon(options) {
return this.icon || options.icon;
},
configMessageVariant(options) {
return options.status || "warning";
},
onChange(formData) {
this.formData = formData;
},
onCancel() {
window.location = `${getAppRoot()}${this.cancelRedirect}`;
},
onSubmit() {
submitData(this.url, this.formData).then((response) => {
let params = {};
if (response.id) {
params.id = response.id;
} else {
params = {
message: response.message,
status: "success",
persistent: false,
};
}
if (this.redirect) {
const urlParams = new URLSearchParams(params);
window.location = `${getAppRoot()}${this.redirect}?${urlParams.toString()}`;
} else {
const replaceParams = {};
visitInputs(response.inputs, (input, name) => {
replaceParams[name] = input.value;
});
this.replaceParams = replaceParams;
this.showMessage(response.message);
}
}, this.onError);
},
onError(error) {
this.showMessage(error || `Failed to load resource ${this.url}.`, "danger");
},
showMessage(message, variant = "success") {
this.messageText = message;
this.messageVariant = variant;
document.querySelector(".center-panel").scrollTop = 0;
},
},
};
</script>
12 changes: 12 additions & 0 deletions client/src/components/Form/services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import axios from "axios";
import { rethrowSimple } from "utils/simple-error";
import { getAppRoot } from "onload/loadConfig";

export async function submitData(url, payload) {
try {
const { data } = await axios.put(`${getAppRoot()}${url}`, payload);
return data;
} catch (e) {
rethrowSimple(e);
}
}
3 changes: 1 addition & 2 deletions client/src/components/Tool/ToolForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
</template>

<script>
import Scroller from "vue-scrollto";
import { getGalaxyInstance } from "app";
import { getToolFormData, updateToolFormData, submitJob } from "./services";
import { allowCachedJobs } from "./utilities";
Expand Down Expand Up @@ -287,7 +286,7 @@ export default {
if ([true, "true"].includes(config.enable_tool_recommendations)) {
this.showRecommendation = true;
}
Scroller.scrollTo("body");
document.querySelector(".center-panel").scrollTop = 0;
},
(e) => {
this.showExecuting = false;
Expand Down
16 changes: 8 additions & 8 deletions client/src/components/User/UserPreferencesModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export const getUserPreferencesModel = (user_id) => {
id: "manage-third-party-identities",
description: _l("Connect or disconnect access to your third-party identities."),
icon: "fa-id-card-o",
submit_title: "Disconnect identity",
submit_icon: "fa-trash",
submitTitle: "Disconnect identity",
submitIcon: "fa-trash",
shouldRender: config.enable_oidc,
},
permissions: {
Expand All @@ -41,7 +41,7 @@ export const getUserPreferencesModel = (user_id) => {
"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.",
url: `api/users/${user_id}/permissions/inputs`,
icon: "fa-users",
submit_title: "Save Permissions",
submitTitle: "Save Permissions",
redirect: "user",
shouldRender: !config.single_user,
},
Expand All @@ -58,16 +58,16 @@ export const getUserPreferencesModel = (user_id) => {
description: _l("Access your current API key or create a new one."),
url: `api/users/${user_id}/api_key/inputs`,
icon: "fa-key",
submit_title: "Create a new Key",
submit_icon: "fa-check",
submitTitle: "Create a new Key",
submitIcon: "fa-check",
},
cloud_auth: {
id: "edit-preferences-cloud-auth",
title: _l("Manage Cloud Authorization"),
description: _l("Add or modify the configuration that grants Galaxy to access your cloud-based resources."),
icon: "fa-cloud",
submit_title: "Create a new Key",
submit_icon: "fa-check",
submitTitle: "Create a new Key",
submitIcon: "fa-check",
shouldRender: config.enable_account_interface,
},
toolbox_filters: {
Expand All @@ -76,7 +76,7 @@ export const getUserPreferencesModel = (user_id) => {
description: _l("Customize your Toolbox by displaying or omitting sets of Tools."),
url: `api/users/${user_id}/toolbox_filters/inputs`,
icon: "fa-filter",
submit_title: "Save Filters",
submitTitle: "Save Filters",
redirect: "user",
shouldRender: !!config.has_user_tool_filters,
},
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/Workflow/Editor/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
/>
</div>
</div>
<div class="unified-panel-body workflow-right">
<div class="unified-panel-body workflow-right" ref="right-panel">
<div class="m-1">
<FormTool
v-if="hasActiveNodeTool"
Expand Down Expand Up @@ -335,6 +335,7 @@ export default {
node.makeActive();
this.activeNode = node;
this.canvasManager.drawOverview();
this.$refs["right-panel"].scrollTop = 0;
}
},
onDeactivate() {
Expand Down
15 changes: 15 additions & 0 deletions client/src/components/providers/UrlDataProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axios from "axios";
import { getAppRoot } from "onload/loadConfig";
import { SingleQueryProvider } from "components/providers/SingleQueryProvider";
import { rethrowSimple } from "utils/simple-error";

async function urlData({ url }) {
try {
const { data } = await axios.get(`${getAppRoot()}${url}`);
return data;
} catch (e) {
rethrowSimple(e);
}
}

export const UrlDataProvider = SingleQueryProvider(urlData);
6 changes: 3 additions & 3 deletions client/src/entry/admin/AdminRouter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getGalaxyInstance } from "app";
import { getAppRoot } from "onload";
import _l from "utils/localization";
import FormWrapper from "mvc/form/form-wrapper";
import FormGeneric from "components/Form/FormGeneric";
import GridView from "mvc/grid/grid-view";
import QueryStringParsing from "utils/query-string-parsing";
import Router from "layout/router";
Expand Down Expand Up @@ -164,7 +164,7 @@ export const getAdminRouter = (Galaxy, options) => {
title: _l("Reset passwords"),
url: `admin/reset_user_password${id}`,
icon: "fa-user",
submit_title: "Save new password",
submitTitle: "Save new password",
redirect: "admin/users",
},
manage_roles_and_groups_for_user: {
Expand Down Expand Up @@ -225,7 +225,7 @@ export const getAdminRouter = (Galaxy, options) => {
redirect: "admin/forms",
},
};
this.page.display(new FormWrapper.View(form_defs[form_id]));
this._display_vue_helper(FormGeneric, form_defs[form_id]);
},
});
};
Loading