diff --git a/client/src/components/Common/PublishedItem.vue b/client/src/components/Common/PublishedItem.vue
index 7f4aa88fc25..7be9e46c5f9 100644
--- a/client/src/components/Common/PublishedItem.vue
+++ b/client/src/components/Common/PublishedItem.vue
@@ -82,11 +82,11 @@ const { showActivityBar, showToolbox } = usePanels();
Related Pages
- All published {{ plural }}.
+ All published {{ plural }}
- Published {{ plural }} by {{ owner }}.
+ Published {{ plural }} by {{ owner }}
diff --git a/client/src/components/Grid/GridHistory.vue b/client/src/components/Grid/GridHistory.vue
index 071ab611c15..fe61e4ab010 100644
--- a/client/src/components/Grid/GridHistory.vue
+++ b/client/src/components/Grid/GridHistory.vue
@@ -18,9 +18,10 @@ library.add(faPlus);
interface Props {
activeList?: "my" | "shared" | "published";
+ username?: string;
}
-withDefaults(defineProps(), {
+const props = withDefaults(defineProps(), {
activeList: "my",
});
@@ -66,6 +67,6 @@ withDefaults(defineProps(), {
-
+
diff --git a/client/src/components/Grid/GridList.vue b/client/src/components/Grid/GridList.vue
index 267cd0ec913..da08de2739c 100644
--- a/client/src/components/Grid/GridList.vue
+++ b/client/src/components/Grid/GridList.vue
@@ -37,6 +37,8 @@ interface Props {
embedded?: boolean;
// rows per page to be shown
limit?: number;
+ // username for initial search
+ usernameSearch?: string;
}
const props = withDefaults(defineProps(), {
@@ -213,6 +215,11 @@ function onSelectAll(current: boolean): void {
* Initialize grid data
*/
onMounted(() => {
+ if (props.usernameSearch) {
+ const search_query = `user:${props.usernameSearch}`.trim();
+ filterText.value = search_query;
+ onSearch(search_query);
+ }
getGridData();
eventBus.on(onRouterPush);
displayInitialMessage();
diff --git a/client/src/components/Grid/GridPage.vue b/client/src/components/Grid/GridPage.vue
index e340c9eaecf..3508bba416f 100644
--- a/client/src/components/Grid/GridPage.vue
+++ b/client/src/components/Grid/GridPage.vue
@@ -17,9 +17,10 @@ library.add(faPlus);
interface Props {
activeList?: "my" | "published";
+ username?: string;
}
-withDefaults(defineProps(), {
+const props = withDefaults(defineProps(), {
activeList: "my",
});
@@ -47,6 +48,6 @@ withDefaults(defineProps(), {
Public Pages
-
+
diff --git a/client/src/components/History/Content/ContentItem.vue b/client/src/components/History/Content/ContentItem.vue
index 0e5497d645c..70059b96f61 100644
--- a/client/src/components/History/Content/ContentItem.vue
+++ b/client/src/components/History/Content/ContentItem.vue
@@ -185,41 +185,54 @@ function onKeyDown(event: KeyboardEvent) {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
- onClick(event);
- } else if ((event.key === "ArrowUp" || event.key === "ArrowDown") && event.shiftKey) {
+ onClick();
+ } else if ((event.key === "ArrowUp" || event.key === "ArrowDown") && !event.shiftKey) {
event.preventDefault();
- emit("shift-select", event.key);
- } else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
- event.preventDefault();
- emit("init-key-selection");
emit("arrow-navigate", event.key);
- } else if (event.key === "Tab") {
- emit("init-key-selection");
- } else if (event.key === "Delete" && !props.selected && !props.item.deleted) {
- event.preventDefault();
- onDelete(event.shiftKey);
- } else if (event.key === "Escape") {
- event.preventDefault();
- emit("hide-selection");
- } else if (event.key === "a" && isSelectKey(event)) {
- event.preventDefault();
- emit("select-all");
+ }
+
+ if (props.writable) {
+ if (event.key === "Tab") {
+ emit("init-key-selection");
+ } else {
+ event.preventDefault();
+ if ((event.key === "ArrowUp" || event.key === "ArrowDown") && event.shiftKey) {
+ emit("shift-select", event.key);
+ } else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
+ emit("init-key-selection");
+ } else if (event.key === "Delete" && !props.selected && !props.item.deleted) {
+ onDelete(event.shiftKey);
+ emit("arrow-navigate", "ArrowDown");
+ } else if (event.key === "Escape") {
+ emit("hide-selection");
+ } else if (event.key === "a" && isSelectKey(event)) {
+ emit("select-all");
+ }
+ }
}
}
-function onClick(e: Event) {
+function onClick(e?: Event) {
const event = e as KeyboardEvent;
- if (event && event.shiftKey && isSelectKey(event)) {
- emit("selected-to", false);
- } else if (event && isSelectKey(event)) {
- emit("init-key-selection");
- emit("update:selected", !props.selected);
- } else if (event && event.shiftKey) {
- emit("selected-to", true);
- } else if (props.isPlaceholder) {
- emit("init-key-selection");
- } else if (props.isDataset) {
- emit("init-key-selection");
+ if (event && props.writable) {
+ if (event.shiftKey && isSelectKey(event)) {
+ emit("selected-to", false);
+ return;
+ } else if (isSelectKey(event)) {
+ emit("init-key-selection");
+ emit("update:selected", !props.selected);
+ return;
+ } else if (event.shiftKey) {
+ emit("selected-to", true);
+ return;
+ } else {
+ emit("init-key-selection");
+ }
+ }
+ if (props.isPlaceholder) {
+ return;
+ }
+ if (props.isDataset) {
emit("update:expand-dataset", !props.expandDataset);
} else {
emit("view-collection", props.item, props.name);
diff --git a/client/src/components/History/CurrentHistory/HistoryPanel.vue b/client/src/components/History/CurrentHistory/HistoryPanel.vue
index 8be2868a9c5..8b2062323ca 100644
--- a/client/src/components/History/CurrentHistory/HistoryPanel.vue
+++ b/client/src/components/History/CurrentHistory/HistoryPanel.vue
@@ -50,7 +50,6 @@ interface Props {
history: HistorySummary;
filter?: string;
canEditHistory?: boolean;
- shouldShowControls?: boolean;
filterable?: boolean;
isMultiViewItem?: boolean;
}
@@ -61,7 +60,6 @@ const props = withDefaults(defineProps(), {
listOffset: 0,
filter: "",
canEditHistory: true,
- shouldShowControls: true,
filterable: false,
isMultiViewItem: false,
});
@@ -80,7 +78,7 @@ const querySelectionBreak = ref(false);
const dragTarget = ref(null);
const contentItemRefs = computed(() => {
return historyItems.value.reduce((acc: ContentItemRef, item) => {
- acc[`item-${item.id}`] = ref(null);
+ acc[itemUniqueKey(item)] = ref(null);
return acc;
}, {});
});
@@ -405,6 +403,10 @@ function getItemKey(item: HistoryItem) {
return item.type_id;
}
+function itemUniqueKey(item: HistoryItem) {
+ return `${item.history_content_type}-${item.id}`;
+}
+
onMounted(async () => {
// `filterable` here indicates if this is the current history panel
if (props.filterable && !props.filter) {
@@ -413,9 +415,11 @@ onMounted(async () => {
await loadHistoryItems();
// if there is a listOffset, we are coming from a collection view, so focus on item at that offset
if (props.listOffset) {
- const itemId = historyItems.value[props.listOffset]?.id;
- const itemElement = contentItemRefs.value[`item-${itemId}`]?.value?.$el as HTMLElement;
- itemElement?.focus();
+ const itemAtOffset = historyItems.value[props.listOffset];
+ if (itemAtOffset) {
+ const itemElement = contentItemRefs.value[itemUniqueKey(itemAtOffset)]?.value?.$el as HTMLElement;
+ itemElement?.focus();
+ }
}
});
@@ -427,7 +431,7 @@ function arrowNavigate(item: HistoryItem, eventKey: string) {
nextItem = historyItems.value[historyItems.value.indexOf(item) - 1];
}
if (nextItem) {
- const itemElement = contentItemRefs.value[`item-${nextItem.id}`]?.value?.$el as HTMLElement;
+ const itemElement = contentItemRefs.value[itemUniqueKey(nextItem)]?.value?.$el as HTMLElement;
itemElement?.focus();
}
return nextItem;
@@ -510,13 +514,13 @@ function setItemDragstart(
:history="history"
:is-watching="isWatching"
:last-checked="lastCheckedTime"
- :show-controls="shouldShowControls"
+ :show-controls="canEditHistory"
:filter-text.sync="filterText"
:hide-reload="isMultiViewItem"
@reloadContents="reloadContents" />
();
const history = ref({});
onMounted(async () => {
- const result = await historyFetcher({ history_id: props.id });
-
- history.value = result;
+ const { data } = await historyFetcher({ history_id: props.id });
+ history.value = data;
});
diff --git a/client/src/components/History/HistoryView.test.js b/client/src/components/History/HistoryView.test.js
index 37fa9c79d49..f87a3324f5b 100644
--- a/client/src/components/History/HistoryView.test.js
+++ b/client/src/components/History/HistoryView.test.js
@@ -94,12 +94,15 @@ describe("History center panel View", () => {
expect(tags.text()).toContain("tag_1");
expect(tags.text()).toContain("tag_2");
// HistoryCounter
- expect(wrapper.find("[data-description='storage dashboard button']").attributes("disabled")).toBeTruthy();
expect(wrapper.find("[data-description='show active items button']").text()).toEqual("8");
expect(wrapper.find("[data-description='include deleted items button']").text()).toEqual("1");
expect(wrapper.find("[data-description='include hidden items button']").text()).toEqual("2");
}
+ function storageDashboardButtonDisabled(wrapper) {
+ return wrapper.find("[data-description='storage dashboard button']").attributes("disabled");
+ }
+
it("current user's current history", async () => {
const history = create_history("history_1", "user_1", false);
const wrapper = await createWrapper(localVue, "user_1", history);
@@ -117,6 +120,9 @@ describe("History center panel View", () => {
// parts of the layout that should be similar for all cases
expectCorrectLayout(wrapper);
+ // storage dashboard button should be enabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeFalsy();
+
// make sure all history items show up
const historyItems = wrapper.findAllComponents(ContentItem);
expect(historyItems.length).toBe(10);
@@ -138,6 +144,9 @@ describe("History center panel View", () => {
expect(switchButton.exists()).toBe(false);
expect(importButton.attributes("disabled")).toBeFalsy();
+ // storage dashboard button should be disabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeTruthy();
+
// parts of the layout that should be similar for all cases
expectCorrectLayout(wrapper);
});
@@ -153,6 +162,9 @@ describe("History center panel View", () => {
expect(switchButton.attributes("disabled")).toBeFalsy();
expect(importButton.exists()).toBe(false);
+ // storage dashboard button should be enabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeFalsy();
+
// parts of the layout that should be similar for all cases
expectCorrectLayout(wrapper);
});
@@ -168,6 +180,9 @@ describe("History center panel View", () => {
expect(switchButton.attributes("disabled")).toBeTruthy();
expect(importButton.exists()).toBe(false);
+ // storage dashboard button should be disabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeTruthy();
+
// instead we have an alert
expect(wrapper.find("[data-description='history state info']").text()).toBe("This history has been purged.");
});
@@ -183,6 +198,9 @@ describe("History center panel View", () => {
expect(importButton.exists()).toBe(true);
expect(importButton.attributes("disabled")).toBeFalsy();
+ // storage dashboard button should be disabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeTruthy();
+
expectCorrectLayout(wrapper);
expect(wrapper.find("[data-description='history state info']").exists()).toBe(false);
});
@@ -198,6 +216,9 @@ describe("History center panel View", () => {
expect(switchButton.attributes("disabled")).toBeTruthy();
expect(importButton.exists()).toBe(false);
+ // storage dashboard button should be disabled
+ expect(storageDashboardButtonDisabled(wrapper)).toBeTruthy();
+
expectCorrectLayout(wrapper);
expect(wrapper.find("[data-description='history state info']").text()).toBe("This history has been archived.");
});
diff --git a/client/src/components/History/HistoryView.vue b/client/src/components/History/HistoryView.vue
index a6dbee74fd1..9fa3061b4e0 100644
--- a/client/src/components/History/HistoryView.vue
+++ b/client/src/components/History/HistoryView.vue
@@ -37,7 +37,6 @@
v-else
:history="history"
:can-edit-history="canEditHistory"
- :should-show-controls="false"
filterable
@view-collection="onViewCollection" />
diff --git a/client/src/entry/analysis/router.js b/client/src/entry/analysis/router.js
index 26268196303..87202bbd41c 100644
--- a/client/src/entry/analysis/router.js
+++ b/client/src/entry/analysis/router.js
@@ -281,9 +281,10 @@ export function getRouter(Galaxy) {
{
path: "histories/list_published",
component: GridHistory,
- props: {
+ props: (route) => ({
activeList: "published",
- },
+ username: route.query["f-username"],
+ }),
},
{
path: "histories/archived",
@@ -381,9 +382,10 @@ export function getRouter(Galaxy) {
{
path: "pages/list_published",
component: GridPage,
- props: {
+ props: (route) => ({
activeList: "published",
- },
+ username: route.query["f-username"],
+ }),
},
{
path: "storage/history/:historyId",
diff --git a/config/plugins/webhooks/news/config.yml b/config/plugins/webhooks/news/config.yml
deleted file mode 100644
index cf49026fef9..00000000000
--- a/config/plugins/webhooks/news/config.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-id: news
-type:
- - masthead
-activate: true
-
-icon: fa-bullhorn
-tooltip: See the Galaxy Release Notes
diff --git a/config/plugins/webhooks/news/script.js b/config/plugins/webhooks/news/script.js
deleted file mode 100644
index d5b7928e832..00000000000
--- a/config/plugins/webhooks/news/script.js
+++ /dev/null
@@ -1,111 +0,0 @@
-(function () {
- function hideNewsOverlay() {
- const container = document.getElementById("news-container");
- if (container) {
- container.style.visibility = "hidden";
- }
- }
-
- function newsSeen(currentGalaxyVersion) {
- // When it's seen, remove the red indicator if it exists and store the current version.
- const newsIndicator = document.getElementById("news-indicator");
- if (newsIndicator) {
- newsIndicator.remove();
- }
- window.localStorage.setItem("galaxy-news-seen-release", currentGalaxyVersion);
- }
-
- function newsUnseen() {
- // When there is news, add an red indicator to the icon.
- const newsIconSpan = document.querySelector("#news .nav-link");
- newsIconSpan.insertAdjacentHTML("beforeend", '');
- }
-
- /* The masthead icon may not exist yet when this webhook executes; we need this to wait for that to happen.
- * elementReady function from gist:
- * https://gist.github.com/jwilson8767/db379026efcbd932f64382db4b02853e
- */
- function elementReadyNews(selector) {
- return new Promise((resolve, reject) => {
- const el = document.querySelector(selector);
- if (el) {
- resolve(el);
- }
- new MutationObserver((mutationRecords, observer) => {
- // Query for elements matching the specified selector
- Array.from(document.querySelectorAll(selector)).forEach((element) => {
- resolve(element);
- //Once we have resolved we don't need the observer anymore.
- observer.disconnect();
- });
- }).observe(document.documentElement, {
- childList: true,
- subtree: true,
- });
- });
- }
-
- elementReadyNews("#news a").then((el) => {
- // External stuff may also have attached a click handler here (vue-based masthead)
- // replace with a clean copy of the node to remove all that cruft.
- clean = el.cloneNode(true);
- el.parentNode.replaceChild(clean, el);
-
- let currentGalaxyVersion = Galaxy.config.version_major;
- const lastSeenVersion = window.localStorage.getItem("galaxy-news-seen-release");
-
- // If we're at a deployed release candidate, just mark it seen and show
- // the previous notes if someone clicks the link. RC notes won't exist.
- if (Galaxy.config.version_minor.startsWith("rc")) {
- // If we, for whatever reason, need to do this again just add
- // another case here. It's not worth parsing and doing version
- // math, and we should be able to drop preferring notifications
- // framework moving forward in 23.2
- if (currentGalaxyVersion == "23.1") {
- currentGalaxyVersion = "23.0";
- }
- newsSeen(currentGalaxyVersion);
- } else if (lastSeenVersion != currentGalaxyVersion) {
- newsUnseen();
- } else {
- newsSeen(currentGalaxyVersion);
- }
-
- const releaseNotes = `https://docs.galaxyproject.org/en/latest/releases/${currentGalaxyVersion}_announce_user.html`;
-
- clean.addEventListener("click", (e) => {
- e.preventDefault();
- e.stopPropagation();
-
- // If element doesn't exist, add it.
- if (document.getElementById("news-container") == null) {
- document.querySelector("body.full-content").insertAdjacentHTML(
- "afterbegin",
- `
- `
- );
- // Clicking outside of GTN closes it
- document.getElementById("news-screen").addEventListener("click", () => {
- hideNewsOverlay();
- });
- }
- document.getElementById("news-container").style.visibility = "visible";
- newsSeen(currentGalaxyVersion);
- });
- });
-
- // Remove the overlay on escape button click
- document.addEventListener("keydown", (e) => {
- // Check for escape button - "27"
- if (e.which === 27 || e.keyCode === 27) {
- hideNewsOverlay();
- }
- });
-})();
diff --git a/config/plugins/webhooks/news/styles.css b/config/plugins/webhooks/news/styles.css
deleted file mode 100644
index d343e02312c..00000000000
--- a/config/plugins/webhooks/news/styles.css
+++ /dev/null
@@ -1,38 +0,0 @@
-#news-screen {
- position: fixed;
- z-index: 5100;
- width: 100%;
- height: 100%;
-}
-
-#news-screen-overlay {
- position: fixed;
- top: 0;
- left: 0;
- background: rgba(224, 224, 224, 0.75);
- z-index: 5000;
- width: 100%;
- height: 100%;
- opacity: 2;
-}
-
-#news-header {
- position: fixed;
- height: 100%;
- width: 100%;
- z-index: 5200;
- display: flex;
- justify-content: center;
- flex-direction: column;
- align-items: center;
-}
-
-#news-indicator {
- position: absolute;
- top: 0.5rem;
- right: 0.2rem;
- width: 0.6rem;
- height: 0.6rem;
- border-radius: 50%;
- background: #e31a1e;
-}