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

Masthead Revision #17927

Merged
merged 60 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
46c247d
Remove masthead icons
guerler Apr 7, 2024
9cbb318
Adjust masthead size
guerler Apr 7, 2024
97cc442
Remove masthead dropdown handler, only allow regular tabs
guerler May 20, 2024
43c1226
Remove unused imports from masthead item component
guerler May 20, 2024
832d62e
Start splitting object property into individual attributes in masthead
guerler May 20, 2024
bb46203
Remove interactive tools from masthead, since already available in th…
guerler May 20, 2024
d11ab54
Remove pseudo class handling, will use id instead
guerler May 20, 2024
5d5301f
Move away from json blob configuration for masthead options
guerler May 20, 2024
0eb2203
Decouple menu.js configuration module
guerler May 20, 2024
723f92d
Delete menu.js
guerler May 20, 2024
2e49d3f
Fix icon handling
guerler May 20, 2024
9827dcb
Remove unused props from masthead
guerler May 20, 2024
080a72a
Fix window manager handling in masthead
guerler May 20, 2024
6dcc6f8
Reorder masthead tabs
guerler May 21, 2024
e245919
Fix icon handling, avoid reload when returning to home
guerler May 21, 2024
06709ff
Fix toggle state, adjust icon styles
guerler May 21, 2024
e978ee0
Add configuration conditions
guerler May 21, 2024
636f6f4
Show navbar while loading config, reduce margin
guerler May 21, 2024
18caa0e
Move quota margin to navbar, adjust alignment
guerler May 21, 2024
b78612b
Fix tooltips in masthead
guerler May 21, 2024
3abbe62
Adjust jest tests
guerler May 23, 2024
f5b1e96
Preliminary adjustment of workflow run selenium test
guerler May 27, 2024
b6d8ab8
Remove additional login confirmation tests for now
guerler May 27, 2024
f212d04
More selenium adjustments, using the activity bar to navigate instead…
guerler May 27, 2024
bf132e1
Fix tool exection in selenium tests
guerler May 27, 2024
11428d0
Fix client formatting
guerler May 27, 2024
38ef60c
Extend list of visible activity items to anon user
guerler May 27, 2024
5755aa4
Fix workflow bookmarking test
guerler May 28, 2024
8952b28
Fix workflow invocations selenium test
guerler May 28, 2024
c0237f4
Fix tour test
guerler May 28, 2024
e590a89
Remove legacy navigation selectors
guerler May 28, 2024
63e2a81
Add help and community links to about page
guerler May 28, 2024
3d07d2a
Adjust library identifier to align with selenium tests
guerler May 28, 2024
4b90ffe
Fix visualization activity, adjust tour
guerler May 29, 2024
f1e1317
Add dropdown for user tab in masthead
guerler May 29, 2024
e0b4820
Remove unused popover plugin from masthead components
guerler May 29, 2024
5a54090
Move activity toggle icon to the left, treat like favorites selection
guerler May 29, 2024
83d484e
Reframe activity settings as list of all activities
guerler May 29, 2024
b3f4bb2
Only display optional activities when user clicks on more
guerler May 29, 2024
20d77f1
Fix regular icon state in activity list
guerler May 29, 2024
4d2fe61
Adjust selenium tests with regard to updated user dropdown
guerler May 30, 2024
3eeb107
Adjust jest test with regard to changes in activity panel
guerler May 30, 2024
ca11e91
Add username to user tab in masthead
guerler May 30, 2024
0f5b261
Adjust quota meter, consistently show progress bar, adjust tooltip
guerler May 30, 2024
fc3dd1e
Add loading spinner to masthead
guerler May 30, 2024
c0de496
Adjust quota meter test case
guerler May 30, 2024
aa4a8b8
Adjust tool running selenium test case in the context of object store
guerler May 31, 2024
765bab3
Convert quota meter to composition api and typescript
guerler May 31, 2024
5cdd404
Adjust quota meter jest test
guerler May 31, 2024
4430b42
Add total quota to quota meter
guerler May 31, 2024
af8350a
Fix typescript error in jest test
guerler May 31, 2024
136e8a6
Add prop for library metadata, possible reactivity issue?
guerler Jun 1, 2024
f170db9
Make masthead tooltips noninteractive
guerler Jun 1, 2024
f5b73ab
Remove redundant home icon from masthead
guerler Jun 28, 2024
b29c828
Adjust masthead test case
guerler Jun 28, 2024
360b147
Disable storage dashboard for anon users
guerler Jun 28, 2024
04c68ea
Link to login instead of disabling storage tab
guerler Jun 28, 2024
8d20256
Add prevent directive to masthead item click handler
guerler Jun 28, 2024
9766387
Limit username text length in masthead
guerler Jun 28, 2024
3255601
Improve brand alignment padding
guerler Jun 28, 2024
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: 1 addition & 0 deletions client/src/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const REGISTERED_USER: User = {

const ANONYMOUS_USER: AnonymousUser = {
isAnonymous: true,
total_disk_usage: 0,
};

const SESSIONLESS_USER = null;
Expand Down
2 changes: 1 addition & 1 deletion client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export interface User extends QuotaUsageResponse {
username?: string;
}

export interface AnonymousUser {
export interface AnonymousUser extends QuotaUsageResponse {
id?: string;
isAnonymous: true;
is_admin?: false;
Expand Down
137 changes: 96 additions & 41 deletions client/src/components/AboutGalaxy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* (injected by webpack) */

import { computed } from "vue";
import { RouterLink } from "vue-router";

import { useConfig } from "@/composables/config";
import { getAppRoot } from "@/onload/loadConfig";
Expand All @@ -28,47 +29,101 @@ const versionUserDocumentationUrl = computed(() => {

<template>
<div v-if="isConfigLoaded" class="about-galaxy">
<Heading h1 :icon="['gxd', 'galaxyLogo']" size="xl">About This Galaxy</Heading>
<div>
<!-- Galaxy version (detailed), with a link to the release notes -->
<Heading h2 separator size="md">Galaxy Version Information</Heading>
<p>
The Galaxy Server is running version
<ExternalLink :href="versionUserDocumentationUrl">
<strong> {{ config.version_major }}.{{ config.version_minor }}</strong> </ExternalLink
>, and the web client was built on <UtcDate :date="clientBuildDate" mode="pretty" />.
</p>
<template v-if="config.version_extra">
<p>The server also provides the following extra version information</p>
<ul>
<li v-for="(value, name, index) in config.version_extra" :key="index">
<strong>{{ name }}</strong>
: {{ value }}
</li>
</ul>
</template>
</div>
<div>
<Heading h2 separator size="md">Galaxy API Documentation</Heading>
<!-- API documentation link -->
<p>
The Galaxy API is available, and explorable, at
<ExternalLink :href="apiDocsLink">
{{ apiDocsLink }}
</ExternalLink>
</p>
</div>
<div>
<Heading h2 separator size="md">License Information</Heading>
<p>The Galaxy Software is licensed under <License :license-id="galaxyLicense" /></p>
</div>
<div v-if="config.terms_url">
<!-- Terms, if available.-->
<Heading h2 separator size="md">Terms and Conditions</Heading>
<p>
This Galaxy Server has specified Terms and Conditions that apply to use of the service.
<ExternalLink :href="config.terms_url">Review them here.</ExternalLink>
</p>
<Heading h1 :icon="['gxd', 'galaxyLogo']" size="xl">Help and Support</Heading>
<div class="py-4">
<div v-if="config.wiki_url">
<Heading h2 separator size="md">Community Hub</Heading>
<p>
Interact with the our community, explore and publish tutorials at
<ExternalLink :href="config.wiki_url">
{{ config.wiki_url }}
</ExternalLink>
</p>
</div>
<div v-if="config.citation_url">
<Heading h2 separator size="md">How to Cite Us</Heading>
<p>
Find more details on how to properly cite Galaxy at
<ExternalLink :href="config.citation_url">
{{ config.citation_url }}
</ExternalLink>
</p>
</div>
<div>
<Heading h2 separator size="md">Interactive Tours</Heading>
<p>
Explore and learn about Galaxy through interactive
<RouterLink to="tours">tours</RouterLink>.
</p>
</div>
<div v-if="config.screencasts_url">
<Heading h2 separator size="md">Videos and Screencasts</Heading>
<p>
Learn more about Galaxy by watching videos and screencasts at
<ExternalLink :href="config.screencasts_url">
{{ config.screencasts_url }}
</ExternalLink>
</p>
</div>
<div v-if="config.helpsite_url">
<Heading h2 separator size="md">User Documentation</Heading>
<p>
Learn more about Galaxy at
<ExternalLink :href="config.helpsite_url">
{{ config.helpsite_url }}
</ExternalLink>
</p>
</div>
<div>
<Heading h2 separator size="md">API Documentation</Heading>
<!-- API documentation link -->
<p>
The Galaxy API is available, and explorable, at
<ExternalLink :href="apiDocsLink">
{{ apiDocsLink }}
</ExternalLink>
</p>
</div>
<div>
<!-- Galaxy version (detailed), with a link to the release notes -->
<Heading h2 separator size="md">Version Information</Heading>
<p>
The Galaxy Server is running version
<ExternalLink :href="versionUserDocumentationUrl">
<strong> {{ config.version_major }}.{{ config.version_minor }}</strong> </ExternalLink
>, and the web client was built on <UtcDate :date="clientBuildDate" mode="pretty" />.
</p>
<template v-if="config.version_extra">
<p>The server also provides the following extra version information</p>
<ul>
<li v-for="(value, name, index) in config.version_extra" :key="index">
<strong>{{ name }}</strong>
: {{ value }}
</li>
</ul>
</template>
</div>
<div>
<Heading h2 separator size="md">License Information</Heading>
<p>The Galaxy Software is licensed under <License :license-id="galaxyLicense" /></p>
</div>
<div v-if="config.terms_url">
<!-- Terms, if available.-->
<Heading h2 separator size="md">Terms and Conditions</Heading>
<p>
This Galaxy Server has specified Terms and Conditions that apply to use of the service.
<ExternalLink :href="config.terms_url">Review them here.</ExternalLink>
</p>
</div>
<div v-if="config.support_url">
<Heading h2 separator size="md">Support</Heading>
<p>
Do you need help? Reach out at
<ExternalLink :href="config.support_url">
{{ config.support_url }}
</ExternalLink>
</p>
</div>
</div>
</div>
</template>
Expand Down
12 changes: 4 additions & 8 deletions client/src/components/ActivityBar/ActivityBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@

<template>
<div class="d-flex">
<div

Check warning on line 145 in client/src/components/ActivityBar/ActivityBar.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Visible, non-interactive elements should not have an interactive handler
class="activity-bar d-flex flex-column no-highlight"
data-description="activity bar"
@dragover.prevent="onDragOver"
Expand Down Expand Up @@ -179,11 +179,7 @@
:to="activity.to"
@click="onToggleSidebar()" />
<ActivityItem
v-else-if="
['admin', 'tools', 'visualizations', 'multiview', 'invocation'].includes(
activity.id
)
"
v-else-if="activity.id === 'admin' || activity.panel"
:id="`activity-${activity.id}`"
:key="activity.id"
:icon="activity.icon"
Expand Down Expand Up @@ -216,10 +212,10 @@
@click="onToggleSidebar('notifications')" />
<ActivityItem
id="activity-settings"
icon="cog"
icon="ellipsis-h"
:is-active="isActiveSideBar('settings')"
title="Settings"
tooltip="Edit preferences"
title="More"
tooltip="View additional activities"
@click="onToggleSidebar('settings')" />
<ActivityItem
v-if="isAdmin"
Expand Down
27 changes: 14 additions & 13 deletions client/src/components/ActivityBar/ActivitySettings.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function testActivity(id, newOptions = {}) {
description: "activity-test-description",
icon: "activity-test-icon",
mutable: true,
optional: false,
optional: true,
title: "activity-test-title",
to: null,
tooltip: "activity-test-tooltip",
Expand Down Expand Up @@ -56,22 +56,23 @@ describe("ActivitySettings", () => {

it("availability of built-in activities", async () => {
const items = wrapper.findAll(activityItemSelector);
expect(items.length).toBe(Activities.length);
const nOptional = Activities.filter((x) => x.optional).length;
expect(items.length).toBe(nOptional);
});

it("visible but non-optional activity", async () => {
it("visible and optional activity", async () => {
activityStore.setAll([testActivity("1")]);
await wrapper.vm.$nextTick();
const items = wrapper.findAll(activityItemSelector);
expect(items.length).toBe(1);
const pinnedCheckbox = items.at(0).find("[data-icon='thumbtack']");
expect(pinnedCheckbox.exists()).toBeTruthy();
const pinnedIcon = wrapper.find("[icon='activity-test-icon'");
expect(pinnedIcon.exists()).toBeTruthy();
const checkbox = items.at(0).find("[title='Hide in Activity Bar']");
expect(checkbox.exists()).toBeTruthy();
const icon = wrapper.find("[icon='activity-test-icon'");
expect(icon.exists()).toBeTruthy();
expect(activityStore.getAll()[0].visible).toBeTruthy();
pinnedCheckbox.trigger("click");
checkbox.trigger("click");
await wrapper.vm.$nextTick();
expect(activityStore.getAll()[0].visible).toBeTruthy();
expect(activityStore.getAll()[0].visible).toBeFalsy();
});

it("non-visible but optional activity", async () => {
Expand All @@ -84,12 +85,12 @@ describe("ActivitySettings", () => {
await wrapper.vm.$nextTick();
const items = wrapper.findAll(activityItemSelector);
expect(items.length).toBe(1);
const hiddenCheckbox = items.at(0).find("[data-icon='square']");
expect(hiddenCheckbox.exists()).toBeTruthy();
const checkbox = items.at(0).find("[title='Show in Activity Bar']");
expect(checkbox.exists()).toBeTruthy();
expect(activityStore.getAll()[0].visible).toBeFalsy();
hiddenCheckbox.trigger("click");
checkbox.trigger("click");
await wrapper.vm.$nextTick();
const visibleCheckbox = items.at(0).find("[data-icon='check-square']");
const visibleCheckbox = items.at(0).find("[title='Hide in Activity Bar']");
expect(visibleCheckbox.exists()).toBeTruthy();
expect(activityStore.getAll()[0].visible).toBeTruthy();
});
Expand Down
74 changes: 42 additions & 32 deletions client/src/components/ActivityBar/ActivitySettings.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
<script setup lang="ts">
import { library } from "@fortawesome/fontawesome-svg-core";
import { faSquare } from "@fortawesome/free-regular-svg-icons";
import { faCheckSquare, faThumbtack, faTrash } from "@fortawesome/free-solid-svg-icons";
import { faSquare, faStar as faStarRegular } from "@fortawesome/free-regular-svg-icons";
import { faCheckSquare, faStar, faThumbtack, faTrash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";
import { computed, type ComputedRef } from "vue";

import { useActivityAction } from "@/composables/useActivityAction";
import { type Activity, useActivityStore } from "@/stores/activityStore";

library.add({
faCheckSquare,
faSquare,
faStar,
faStarRegular,
faTrash,
faThumbtack,
});
Expand All @@ -21,6 +24,7 @@ const props = defineProps<{

const activityStore = useActivityStore();
const { activities } = storeToRefs(activityStore);
const activityAction = useActivityAction();

const filteredActivities = computed(() => {
if (props.query?.length > 0) {
Expand All @@ -44,7 +48,7 @@ const foundActivities: ComputedRef<boolean> = computed(() => {
return filteredActivities.value.length > 0;
});

function onClick(activity: Activity) {
function onFavorite(activity: Activity) {
if (activity.optional) {
activity.visible = !activity.visible;
}
Expand All @@ -59,36 +63,49 @@ function onRemove(activity: Activity) {
<div class="activity-settings rounded no-highlight">
<div v-if="foundActivities" class="activity-settings-content">
<div v-for="activity in filteredActivities" :key="activity.id">
<button class="activity-settings-item p-2 cursor-pointer" @click="onClick(activity)">
<button
v-if="activity.optional"
class="activity-settings-item p-2 cursor-pointer"
@click="activityAction.executeActivity(activity)">
<div class="d-flex justify-content-between align-items-start">
<span class="w-100">
<FontAwesomeIcon
v-if="!activity.optional"
class="icon-check mr-1"
icon="fas fa-thumbtack"
fa-fw />
<FontAwesomeIcon
v-else-if="activity.visible"
class="icon-check mr-1"
icon="fas fa-check-square"
fa-fw />
<FontAwesomeIcon v-else class="mr-1" icon="far fa-square" fa-fw />
<span class="d-flex justify-content-between w-100">
<span>
<icon class="mr-1" :icon="activity.icon" />
<span v-localize class="font-weight-bold">{{
activity.title || "No title available"
}}</span>
</span>
<div>
<BButton
v-if="activity.mutable"
v-b-tooltip.hover
data-description="delete activity"
size="sm"
title="Delete Activity"
variant="link"
@click.stop="onRemove(activity)">
<FontAwesomeIcon icon="fa-trash" fa-fw />
</BButton>
<BButton
v-if="activity.visible"
v-b-tooltip.hover
size="sm"
title="Hide in Activity Bar"
variant="link"
@click.stop="onFavorite(activity)">
<FontAwesomeIcon icon="fas fa-star" fa-fw />
</BButton>
<BButton
v-else
v-b-tooltip.hover
size="sm"
title="Show in Activity Bar"
variant="link"
@click.stop="onFavorite(activity)">
<FontAwesomeIcon icon="far fa-star" fa-fw />
</BButton>
</div>
</span>
<b-button
v-if="activity.mutable"
data-description="delete activity"
class="button-delete"
size="sm"
variant="link"
@click.stop="onRemove(activity)">
<FontAwesomeIcon icon="fa-trash" fa-fw />
</b-button>
</div>
<div v-localize class="text-muted">
{{ activity.description || "No description available" }}
Expand Down Expand Up @@ -121,13 +138,6 @@ function onRemove(activity: Activity) {
text-align: left;
transition: none;
width: 100%;

.icon-check {
color: darken($brand-success, 15%);
}
.button-delete {
background: transparent;
}
}
.activity-settings-item:hover {
background: $gray-200;
Expand Down
Loading
Loading