Skip to content

Commit

Permalink
Merge pull request #16996 from ahmedhamidawan/empty_collection_histor…
Browse files Browse the repository at this point in the history
…y_item_state

Add history items display state for collections/lists with failed or new populated_state
  • Loading branch information
dannon authored Nov 29, 2023
2 parents dbe1e74 + e02040b commit fdf6ae2
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<span class="description mt-1 mb-1">
a {{ collectionLabel }} with {{ elementCount }}<b>{{ homogeneousDatatype }}</b> {{ pluralizedItem }}
a {{ collectionLabel }} with {{ elementCount || 0 }}<b>{{ homogeneousDatatype }}</b> {{ pluralizedItem }}
</span>
<CollectionProgress v-if="jobStateSummary.size != 0" :summary="jobStateSummary" />
</div>
Expand Down
17 changes: 15 additions & 2 deletions client/src/components/History/Content/ContentItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
:id="contentId"
:class="['content-item m-1 p-0 rounded btn-transparent-background', contentCls, isBeingUsed]"
:data-hid="id"
:data-state="state"
:data-state="dataState"
tabindex="0"
role="button"
@keydown="onKeyDown">
Expand Down Expand Up @@ -43,7 +43,11 @@
<FontAwesomeIcon class="text-info" icon="arrow-circle-down" />
</b-button>
<span v-if="hasStateIcon" class="state-icon">
<icon fixed-width :icon="contentState.icon" :spin="contentState.spin" />
<icon
fixed-width
:icon="contentState.icon"
:spin="contentState.spin"
:title="item.populated_state_message || contentState.text" />
</span>
<span class="id hid">{{ id }}:</span>
<span class="content-title name font-weight-bold">{{ name }}</span>
Expand Down Expand Up @@ -170,6 +174,12 @@ export default {
if (this.isPlaceholder) {
return "placeholder";
}
if (this.item.populated_state === "failed") {
return "failed_populated_state";
}
if (this.item.populated_state === "new") {
return "new_populated_state";
}
if (this.item.job_state_summary) {
for (const state of HIERARCHICAL_COLLECTION_JOB_STATES) {
if (this.item.job_state_summary[state] > 0) {
Expand All @@ -181,6 +191,9 @@ export default {
}
return "ok";
},
dataState() {
return this.state === "new_populated_state" ? "new" : this.state;
},
tags() {
return this.item.tags;
},
Expand Down
18 changes: 15 additions & 3 deletions client/src/components/History/Content/model/StatesInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ if (props.excludeStates) {
}
}
function dataState(state: string) {
return state === "new_populated_state" ? "new" : state;
}
function onFilter(value: string) {
emit("set-filter", `state`, value);
}
Expand All @@ -30,13 +34,21 @@ function onFilter(value: string) {
<template>
<div>
<p>Here are all available item states in Galaxy:</p>
<p><i>(Note that the colors for each state correspond to content item state colors in the history)</i></p>
<p>
<i>
(Note that the colors for each state correspond to content item state colors in the history, and if it
exists, hovering over the icon on a history item will display the state message.)
</i>
</p>
<dl v-for="(state, key, index) in states" :key="index">
<div :class="['alert', 'content-item', 'alert-' + state.status]" :data-state="key">
<div :class="['alert', 'content-item', 'alert-' + state.status]" :data-state="dataState(key)">
<dt>
<a class="text-decoration-none" href="javascript:void(0)" @click="onFilter(key)"
<a v-if="!state.nonDb" class="text-decoration-none" href="javascript:void(0)" @click="onFilter(key)"
><code>{{ key }}</code></a
>
<span v-else
><code>{{ key }}</code></span
>
<icon v-if="state.icon" :icon="state.icon" />
</dt>
<dd>{{ helpText[key] || state.text }}</dd>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type State = {
text?: string;
icon?: string;
spin?: boolean;
nonDb?: boolean;
};

export type States = {
Expand Down
18 changes: 17 additions & 1 deletion client/src/components/History/Content/model/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import type { components } from "@/api/schema";

type DatasetState = components["schemas"]["DatasetState"];
// The 'failed' state is for the collection job state summary, not a dataset state.
type State = DatasetState | "failed" | "placeholder";
type State = DatasetState | "failed" | "placeholder" | "failed_populated_state" | "new_populated_state";

interface StateRepresentation {
status: "success" | "warning" | "info" | "danger" | "secondary";
text?: string;
icon?: string;
spin?: boolean;
nonDb?: boolean;
}

type StateMap = {
Expand Down Expand Up @@ -103,6 +104,21 @@ export const STATES: StateMap = {
text: "This dataset is being fetched.",
icon: "spinner",
spin: true,
nonDb: true,
},
/** the `populated_state: failed`. This state is only visual and transitional, it does not exist in the database. */
failed_populated_state: {
status: "danger",
text: "Failed to populate the collection.",
icon: "exclamation-triangle",
nonDb: true,
},
/** the `populated_state: new`. This state is only visual and transitional, it does not exist in the database. */
new_populated_state: {
status: "warning",
text: "This is a new collection and not all of its data are available yet.",
icon: "clock",
nonDb: true,
},
} as const satisfies StateMap;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const dsc = computed(() => {
const collectionElements = computed(() => collectionElementsStore.getCollectionElements(dsc.value, offset.value));
const loading = computed(() => collectionElementsStore.isLoadingCollectionElements(dsc.value));
const jobState = computed(() => ("job_state_summary" in dsc.value ? dsc.value.job_state_summary : undefined));
const populatedStateMsg = computed(() =>
"populated_state_message" in dsc.value ? dsc.value.populated_state_message : undefined
);
const rootCollection = computed(() => {
if (isHDCA(props.selectedCollections[0])) {
return props.selectedCollections[0];
Expand Down Expand Up @@ -115,7 +118,15 @@ watch(
</section>
<section class="position-relative flex-grow-1 scroller">
<div>
<b-alert
v-if="collectionElements.length === 0"
class="m-2"
:variant="populatedStateMsg ? 'danger' : 'info'"
show>
{{ populatedStateMsg || "This is an empty collection." }}
</b-alert>
<ListingLayout
v-else
data-key="element_index"
:items="collectionElements"
:loading="loading"
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/History/HistoryFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { STATES } from "components/History/Content/model/states";
import StatesInfo from "components/History/Content/model/StatesInfo";
import Filtering, { compare, contains, equals, expandNameTag, toBool, toDate } from "utils/filtering";

const excludeStates = ["empty", "failed", "upload"];
const excludeStates = ["empty", "failed", "upload", "placeholder", "failed_populated_state", "new_populated_state"];
const states = Object.keys(STATES).filter((state) => !excludeStates.includes(state));

const validFilters = {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/History/HistoryPublishedList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ async function load() {
onMounted(async () => {
if (props.fUsername) {
filterText.value = filters.getFilterText({ "user_eq:": props.fUsername });
filterText.value = filters.getFilterText({ user_eq: props.fUsername });
}
await load();
useInfiniteScroll(scrollableDiv.value, () => load());
Expand Down

0 comments on commit fdf6ae2

Please sign in to comment.