Merge pull request #17568 from dannon/drop-new-user-welcome

Drop plugin-based new user welcome.
This commit is contained in:
Marius van den Beek
2024-02-29 09:45:09 -06:00
committed by GitHub
15 changed files with 1 additions and 619 deletions
+1 -1
View File
@@ -193,7 +193,7 @@ export default {
if (response.data.message && response.data.status) {
alert(response.data.message);
}
window.location = this.redirect || withPrefix("/welcome/new");
window.location = this.redirect || withPrefix("/");
})
.catch((error) => {
this.disableCreate = false;
@@ -1,56 +0,0 @@
import { mount } from "@vue/test-utils";
import { createPinia } from "pinia";
import { getLocalVue } from "tests/jest/helpers";
import { mockFetcher } from "@/api/schema/__mocks__";
import { getResource } from "./getResource";
import testData from "./testData.json";
import NewUserWelcome from "./NewUserWelcome.vue";
const localVue = getLocalVue();
jest.mock("@/api/schema");
jest.mock("./getResource");
// mock resource connector
getResource.mockImplementation(() => null);
describe("New user first view", () => {
let wrapper;
beforeEach(async () => {
mockFetcher.path("/api/configuration").method("get").mock({ data: {} });
const pinia = createPinia();
wrapper = mount(NewUserWelcome, {
localVue,
pinia,
});
wrapper.setData({ loaded: true, newUser: testData });
});
it("Contains standard header", async () => {
expect(wrapper.find(".main-header").text()).toContain("Welcome to Galaxy");
});
it("Starts on overall topics", async () => {
wrapper.setData({ position: [] });
expect(wrapper.vm.depth).toBe(0);
expect(wrapper.vm.currentNode.topics).toHaveLength(1);
});
it("Displays second tier of topics", async () => {
wrapper.setData({ position: [0] });
expect(wrapper.vm.depth).toBe(1);
expect(wrapper.vm.currentNode.topics).toHaveLength(2);
expect(wrapper.vm.currentNode.title).toBe("testTopic");
});
it("Goes into subtopic", async () => {
wrapper.setData({ position: [0, 0] });
expect(wrapper.vm.depth).toBe(2);
expect(wrapper.vm.currentNode.title).toBe("subtopicTitle");
expect(wrapper.vm.currentNode.slides).toHaveLength(3);
});
});
@@ -1,198 +0,0 @@
<template>
<div class="new-user-welcome">
<component
:is="viewElement"
v-if="loaded === true"
v-bind="currentNode"
:image-loc="isConfigLoaded && config.welcome_directory"
@select="down"
@back="up">
</component>
<div v-else-if="loaded === false">
<!--
this shouldn't ever show unless the load actually fails,
which shouldn't happen -- just a barebones failsafe
-->
<Heading h1>Welcome to Galaxy!</Heading>
<p>
Galaxy is web-based platform for reproducible computational analysis. Research in Galaxy is supported by
3 pillars: data, tools, and workflows.
</p>
<p>
If this is your first time using Galaxy we strongly recommend looking at the introductory materials
available at <a href="https://training.galaxyproject.org">training.galaxyproject.org</a>.
</p>
</div>
</div>
</template>
<script>
import { BButton, BCard, BCardGroup, BCarousel, BCarouselSlide, BCol, BRow, BTab, BTabs } from "bootstrap-vue";
import Heading from "components/Common/Heading";
import Slides from "components/NewUserWelcome/components/Slides";
import Subtopics from "components/NewUserWelcome/components/Subtopics";
import Topics from "components/NewUserWelcome/components/Topics";
import { getAppRoot } from "onload/loadConfig";
import { useConfig } from "@/composables/config";
import { getResource } from "./getResource";
export default {
components: {
Heading,
BCard,
BCardGroup,
BTabs,
BTab,
BCarousel,
BCarouselSlide,
BButton,
BRow,
BCol,
Topics,
Subtopics,
Slides,
},
setup() {
const { config, isConfigLoaded } = useConfig(true);
return { config, isConfigLoaded };
},
data() {
return {
loaded: undefined,
position: [],
newUser: {},
};
},
computed: {
depth() {
return this.position.length;
},
currentNode() {
const userDict = this.newUser;
return this.position.reduce((node, i) => {
return node.topics[i];
}, userDict);
},
viewElement() {
let element;
switch (this.depth) {
case 0:
element = Topics;
break;
case 1:
element = Subtopics;
break;
case 2:
element = Slides;
break;
}
return element;
},
},
async mounted() {
// todo, move to config, use non-webpack import and load like a plugin
const resource = await getResource();
if (resource?.newUserDict) {
this.newUser = resource.newUserDict;
this.loaded = true;
} else {
// Custom contents in component if this happens to fail, redirecting to tours or something?
}
},
methods: {
imgUrl(src) {
const root = getAppRoot();
const url = `${root}static/${this.imageLoc}${src}`.replace("//", "/");
return url;
},
up() {
this.position.pop();
},
down(index) {
this.position.push(index);
},
},
};
</script>
<style scoped type="scss">
.new-user-welcome:deep() {
.carousel-fig {
padding-bottom: 10;
}
.carousel-caption {
position: relative;
left: 0;
top: 0;
color: black;
padding-bottom: 10;
padding-left: 1vw;
padding-right: 1vw;
}
.carousel-item {
float: none;
margin-right: auto;
margin-left: auto;
}
.carousel-indicators {
position: sticky;
bottom: 30px;
}
.button-housing {
position: sticky;
z-index: 21;
padding-right: 67.88px;
}
.carousel-button {
position: fixed;
z-index: 20;
bottom: 10px;
}
.carousel-control-next,
.carousel-control-prev,
.carousel-indicators {
filter: invert(100%);
}
.carousel-control-next,
.carousel-control-prev {
border-left: 1px;
border-right: 1px;
z-index: 11;
align-items: center;
justify-content: center;
height: fit-content;
height: 85vh;
width: 2vw;
}
.carousel-control-next:hover,
.carousel-control-prev:hover {
background-color: grey;
}
#logos img {
max-width: 100%;
}
.carousel-inner {
position: absolute;
}
.mini-img {
max-width: 100px;
}
.small-img {
max-width: 300px;
}
.med-img {
max-width: 500px;
}
.large-img {
max-width: 700px;
}
.slide-header {
text-align: center;
padding-bottom: 3;
}
.section-header {
filter: invert(16%) sepia(14%) saturate(1113%) hue-rotate(189deg) brightness(99%) contrast(91%);
}
}
</style>
@@ -1,28 +0,0 @@
{
"topics": [
{
"title": "testTopic",
"image": "testTopicImage",
"alt": "testTopic",
"blurb": "topicBlurb",
"intro": "testTopicIntro",
"topics": [
{
"title": "subtopicTitle",
"header": "subtopicHeader",
"image": "subtopicImage",
"alt": "subtopicAlt",
"intro": "subtopicIntro",
"slides": [
{
"file": "slideImage",
"size": "small-img",
"alt": "slideAlt",
"text": "slideText"
}
]
}
]
}
]
}
@@ -1,50 +0,0 @@
<template>
<div class="text-center">
<h1 class="slide-header">
{{ header }}
</h1>
<hr />
<b-carousel
indicators
controls
:interval="0"
class="new-user-welcome-slides"
no-animation
align="center"
position="float">
<b-carousel-slide v-for="(slide, idx) in slides" :key="idx">
<h2 class="carousel-caption h-md">
{{ slide.text | localize }}
</h2>
<img class="carousel-fig" :src="imgUrl(slide.file)" :class="slide.size" :alt="slide.alt" />
</b-carousel-slide>
<b-carousel-slide>
<h2 class="h-md">{{ "Enjoy using Galaxy!" | localize }}</h2>
<img class="large-img" :src="imgUrl('sections/galaxy_logo.png')" alt="Galaxy logo" />
</b-carousel-slide>
</b-carousel>
<div class="button-housing">
<b-button class="mt-auto carousel-button new-user-welcome-return" variant="primary" @click="$emit('back')"
>Return</b-button
>
</div>
</div>
</template>
<script>
import { getAppRoot } from "onload/loadConfig";
export default {
props: {
header: { type: String, required: true },
slides: { type: Array, required: true },
imageLoc: { type: String, required: false, default: "plugins/welcome_page/new_user/dist/static/topics/" },
},
methods: {
imgUrl(src) {
const root = getAppRoot();
const url = `${root}static/${this.imageLoc}${src}`.replace("//", "/");
return url;
},
},
};
</script>
@@ -1,56 +0,0 @@
<template>
<div>
<header class="main-header">
<h1 class="text-center my-3">{{ title | localize }}</h1>
<h2 class="text-center my-3 h-sm">{{ intro | localize }}</h2>
</header>
<b-row class="justify-content-md-center mb-3" :data-new-user-welcome-topic-title="title">
<b-card-group v-for="(subject, idx) in topics" :key="idx">
<b-card
class="text-center m-2 border-0 new-user-welcome-subtopic"
body-class="d-flex flex-column"
:data-new-user-welcome-subtopic-title="subject.title">
<b-card-img
class="section-header mb-3"
height="50h"
:src="imgUrl(subject.image)"
:alt="subject.alt"></b-card-img>
<b-card-text class="font-weight-light">{{ subject.intro | localize }}</b-card-text>
<b-button class="mt-auto" variant="info" @click="$emit('select', idx)">{{
subject.title | localize
}}</b-button>
</b-card>
</b-card-group>
</b-row>
<b-button class="mt-auto new-user-welcome-return" variant="primary" role="link" @click="$emit('back')">
<span class="fa fa-caret-left mr-1" />
<span>Return</span>
</b-button>
</div>
</template>
<script>
import { getAppRoot } from "onload/loadConfig";
export default {
props: {
topics: { type: Array, required: true },
title: { type: String, required: true },
image: { type: String, required: true },
blurb: { type: String, required: true },
intro: { type: String, required: true },
imageLoc: { type: String, required: false, default: "plugins/welcome_page/new_user/dist/static/topics/" },
},
methods: {
imgUrl(src) {
const root = getAppRoot();
const url = `${root}static/${this.imageLoc}${src}`.replace("//", "/");
return url;
},
},
};
</script>
<style scoped>
.card {
width: 15rem;
}
</style>
@@ -1,66 +0,0 @@
<template>
<div>
<header class="main-header">
<h1 class="text-center my-3">{{ title | localize }}</h1>
<h2 class="text-center my-3 h-sm">{{ intro | localize }}</h2>
</header>
<b-row class="justify-content-md-center mb-3">
<b-card-group v-for="(subject, idx) in topics" :key="idx">
<b-card
class="text-center m-2 border-0 new-user-welcome-topic"
:data-new-user-welcome-topic-title="subject.title"
body-class="d-flex flex-column">
<b-card-img
class="section-header mb-3"
height="50h"
:src="imgUrl(subject.image)"
:alt="subject.alt"></b-card-img>
<b-card-text class="font-weight-light">{{ subject.blurb | localize }}</b-card-text>
<b-button class="mt-auto" variant="info" @click="$emit('select', idx)">{{
subject.title | localize
}}</b-button>
</b-card>
</b-card-group>
</b-row>
</div>
</template>
<script>
import { getAppRoot } from "onload/loadConfig";
export default {
props: {
topics: {
type: Array,
required: true,
},
imageLoc: {
type: String,
required: false,
default: "plugins/welcome_page/new_user/dist/static/topics/",
},
title: {
type: String,
default: "Welcome to Galaxy",
},
intro: {
type: String,
default:
"Galaxy is web-based platform for reproducible computational analysis. Research in Galaxy \
is supported by 3 pillars: data, tools, and workflows. For an introduction to each, visit the \
below pages, or begin your analysis by selting a tool from the toolbar to the left.",
},
},
methods: {
imgUrl(src) {
const root = getAppRoot();
const url = `${root}static/${this.imageLoc}${src}`.replace("//", "/");
return url;
},
},
};
</script>
<style scoped>
.card {
width: 15rem;
}
</style>
@@ -1,4 +0,0 @@
export async function getResource() {
const resourceBundle = await import("../../../../static/plugins/welcome_page/new_user/dist/static/topics/index.js");
return resourceBundle;
}
@@ -1,55 +0,0 @@
{
"topics": [
{
"title": "testTopic",
"image": "testTopicImage",
"alt": "testTopic",
"blurb": "topicBlurb",
"intro": "testTopicIntro",
"topics": [
{
"title": "subtopicTitle",
"header": "subtopicHeader",
"image": "subtopicImage",
"alt": "subtopicAlt",
"intro": "subtopicIntro",
"slides": [
{
"file": "slideImage",
"size": "small-img",
"alt": "slideAlt",
"text": "slideText"
},
{
"file": "slideImage2",
"size": "small-img2",
"alt": "slideAlt2",
"text": "slideText2"
},
{
"file": "slideImage3",
"size": "small-img3",
"alt": "slideAlt3",
"text": "slideText3"
}
]
},
{
"title": "subtopicTitle2",
"header": "subtopicHeader2",
"image": "subtopicImage2",
"alt": "subtopicAlt2",
"intro": "subtopicIntro2",
"slides": [
{
"file": "slideImage4",
"size": "small-img4",
"alt": "slideAlt4",
"text": "slideText4"
}
]
}
]
}
]
}
-4
View File
@@ -182,10 +182,6 @@ export function fetchMenu(options = {}) {
title: _l("Interactive Tours"),
url: "/tours",
},
{
title: _l("Introduction to Galaxy"),
url: "/welcome/new",
},
{
title: _l("About"),
url: "/about",
-5
View File
@@ -16,7 +16,6 @@ import HistoryImport from "components/HistoryImport";
import InteractiveTools from "components/InteractiveTools/InteractiveTools";
import JobDetails from "components/JobInformation/JobDetails";
import CarbonEmissionsCalculations from "components/JobMetrics/CarbonEmissions/CarbonEmissionsCalculations";
import NewUserWelcome from "components/NewUserWelcome/NewUserWelcome";
import PageDisplay from "components/PageDisplay/PageDisplay";
import PageEditor from "components/PageEditor/PageEditor";
import ToolSuccess from "components/Tool/ToolSuccess";
@@ -501,10 +500,6 @@ export function getRouter(Galaxy) {
activeList: "published",
},
},
{
path: "welcome/new",
component: NewUserWelcome,
},
{
path: "workflows/create",
component: WorkflowCreate,
@@ -1,24 +0,0 @@
{
"name": "galaxy_new_user",
"version": "1.0.0",
"description": "Set of image files and json used to generate Galaxy new user page",
"main": "index.js",
"scripts": {
"build": "webpack --mode production"
},
"dependencies": {
"@galaxyproject/new_user_welcome": "^1.0.6"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"file-loader": "^6.2.0",
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0"
},
"keywords": [
"galaxy",
"new_user"
],
"author": "Alex Ostrovsky",
"license": "AFL-3.0"
}
@@ -1,2 +0,0 @@
import { newUserDict } from '@galaxyproject/new_user_welcome';
export default newUserDict;
@@ -1,20 +0,0 @@
const webpack = require("webpack");
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
mode: "production",
entry: path.resolve(__dirname, "src/index.js"),
output: {
filename: "topics.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new CopyPlugin({
patterns: [{ from: "node_modules/@galaxyproject/new_user_welcome", to: "static/topics" }],
}),
],
resolve: {
modules: ["node_modules"],
},
};
@@ -1,50 +0,0 @@
from .framework import (
selenium_test,
SeleniumTestCase,
)
EXPECTED__NEW_USER_WELCOME_AXE_IMPACT = "moderate"
class TestNewUserWelcome(SeleniumTestCase):
@selenium_test
def test_new_user_welcome_landing(self):
self.home()
# assert valid (the default) causes a refresh and then you lose the new
# user welcome.
self.register(assert_valid=None)
new_user_welcome = self.components.new_user_welcome
new_user_welcome._.wait_for_present()
new_user_welcome._.assert_no_axe_violations_with_impact_of_at_least(EXPECTED__NEW_USER_WELCOME_AXE_IMPACT)
new_user_welcome.topics.wait_for_element_count_of_at_least(3)
topic_titles = []
for topic in new_user_welcome.topics.all():
topic_titles.append(topic.get_attribute("data-new-user-welcome-topic-title"))
assert "Data in Galaxy" in topic_titles
self.screenshot("new_user_welcome_landing")
new_user_welcome._.assert_no_axe_violations_with_impact_of_at_least(EXPECTED__NEW_USER_WELCOME_AXE_IMPACT)
new_user_welcome.topic_button(title="Data in Galaxy").wait_for_and_click()
new_user_welcome.subtopics.wait_for_element_count_of_at_least(3)
self.screenshot("new_user_welcome_data_subtopic")
subtopic_titles = []
for topic in new_user_welcome.subtopics.all():
subtopic_titles.append(topic.get_attribute("data-new-user-welcome-subtopic-title"))
assert "Importing via Data Uploader" in subtopic_titles
new_user_welcome._.assert_no_axe_violations_with_impact_of_at_least(EXPECTED__NEW_USER_WELCOME_AXE_IMPACT)
new_user_welcome.subtopic_button(title="Importing via Data Uploader").wait_for_and_click()
new_user_welcome.slides.wait_for_present()
# slides violate AXE accessibility test violation found [list] with impact serious: Ensures that lists are structured correctly.
# probably a vue bootstrap issue
new_user_welcome._.assert_no_axe_violations_with_impact_of_at_least("critical")
self.screenshot("new_user_welcome_import_slides_data_0")
# test back button brings you back...
new_user_welcome.back.wait_for_and_click()
new_user_welcome.subtopics.wait_for_element_count_of_at_least(4)
new_user_welcome.back.wait_for_and_click()
new_user_welcome.topics.wait_for_element_count_of_at_least(3)