Skip to content

Commit

Permalink
Merge pull request #17353 from itisAliRH/history-refactors
Browse files Browse the repository at this point in the history
History refactors
  • Loading branch information
bgruening authored Feb 15, 2024
2 parents 6fe4125 + 72f0128 commit 72c329b
Show file tree
Hide file tree
Showing 41 changed files with 1,438 additions and 1,208 deletions.
1 change: 1 addition & 0 deletions client/src/api/histories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export const deleteHistories = fetcher.path("/api/histories/batch/delete").metho
export const undeleteHistory = fetcher.path("/api/histories/deleted/{history_id}/undelete").method("post").create();
export const undeleteHistories = fetcher.path("/api/histories/batch/undelete").method("put").create();
export const publishedHistoriesFetcher = fetcher.path("/api/histories/published").method("get").create();
export const historyFetcher = fetcher.path("/api/histories/{history_id}").method("get").create();
5 changes: 5 additions & 0 deletions client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,8 @@ export function isCollectionElement(element: DCESummary): element is DCECollecti
export function hasDetails(entry: DatasetEntry): entry is DatasetDetails {
return "peek" in entry;
}

/**
* Contains dataset metadata information.
*/
export type MetadataFiles = components["schemas"]["MetadataFile"][];
Original file line number Diff line number Diff line change
@@ -1,74 +1,69 @@
<script setup lang="ts">
import { computed } from "vue";
import { type JobStateSummary } from "./JobStateSummary";
import CollectionProgress from "./CollectionProgress.vue";
interface Props {
elementCount?: number;
elementsDatatypes?: string[];
jobStateSummary: JobStateSummary;
collectionType: string;
}
const props = withDefaults(defineProps<Props>(), {
elementCount: undefined,
elementsDatatypes: undefined,
});
const labels = new Map([
["list", "list"],
["list:paired", "list"],
["list:list", "list"],
["paired", "pair"],
]);
const collectionLabel = computed(() => {
return labels.get(props.collectionType) ?? "nested list";
});
const hasSingleElement = computed(() => {
return props.elementCount === 1;
});
const isHomogeneous = computed(() => {
return props.elementsDatatypes?.length === 1;
});
const homogeneousDatatype = computed(() => {
return isHomogeneous.value ? ` ${props.elementsDatatypes?.[0]}` : "";
});
const pluralizedItem = computed(() => {
if (props.collectionType === "list:list") {
return pluralize("list");
}
if (props.collectionType === "list:paired") {
return pluralize("pair");
}
if (!labels.has(props.collectionType)) {
return pluralize("dataset collection");
}
return pluralize("dataset");
});
function pluralize(word: string) {
return hasSingleElement.value ? word : `${word}s`;
}
</script>

<template>
<div>
<span class="description mt-1 mb-1">
a {{ collectionLabel }} with {{ elementCount || 0 }}<b>{{ homogeneousDatatype }}</b> {{ pluralizedItem }}
</span>

<CollectionProgress v-if="jobStateSummary.size != 0" :summary="jobStateSummary" />
</div>
</template>

<script>
import CollectionProgress from "./CollectionProgress";
import { JobStateSummary } from "./JobStateSummary";
export default {
components: { CollectionProgress },
props: {
jobStateSummary: { type: JobStateSummary, required: true },
collectionType: { type: String, required: true },
elementCount: { type: Number, required: false, default: undefined },
elementsDatatypes: { type: Array, required: false, default: () => [] },
},
data() {
return {
labels: {
list: "list",
"list:paired": "list",
"list:list": "list",
paired: "pair",
},
};
},
computed: {
/**@return {String} */
collectionLabel() {
return this.labels[this.collectionType] || "nested list";
},
/**@return {Boolean} */
hasSingleElement() {
return this.elementCount === 1;
},
/**@return {Boolean} */
isHomogeneous() {
return this.elementsDatatypes.length === 1;
},
/**@return {String} */
homogeneousDatatype() {
return this.isHomogeneous ? ` ${this.elementsDatatypes[0]}` : "";
},
/**@return {String} */
pluralizedItem() {
if (this.collectionType === "list:list") {
return this.pluralize("list");
}
if (this.collectionType === "list:paired") {
return this.pluralize("pair");
}
if (!Object.keys(this.labels).includes(this.collectionType)) {
//Any other kind of nested collection
return this.pluralize("dataset collection");
}
return this.pluralize("dataset");
},
},
methods: {
pluralize(word) {
return this.hasSingleElement ? word : `${word}s`;
},
},
};
</script>

<style lang="scss" scoped>
@import "scss/theme/blue.scss";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { getLocalVue } from "@tests/jest/helpers";
import { mount } from "@vue/test-utils";
import flushPromises from "flush-promises";

import { JobStateSummary } from "./JobStateSummary";

import CollectionProgress from "./CollectionProgress.vue";

const localVue = getLocalVue();

async function mountComponent(dsc: object) {
const jobStateSummary = new JobStateSummary(dsc);

const wrapper = mount(CollectionProgress as object, {
propsData: {
summary: jobStateSummary,
},
localVue,
});

await flushPromises();

return wrapper;
}

describe("CollectionProgress", () => {
it("should display the correct number of items", async () => {
const dsc = { job_state_summary: { all_jobs: 3, running: 3 }, populated_state: {} };

const wrapper = await mountComponent(dsc);

expect(wrapper.find(".progress").find(".bg-warning").attributes("aria-valuenow")).toBe("3");
});

it("should correctly display states", async () => {
const dsc = { job_state_summary: { all_jobs: 5, running: 3, failed: 1, ok: 1 }, populated_state: {} };

const wrapper = await mountComponent(dsc);

expect(wrapper.find(".progress").find(".bg-warning").attributes("aria-valuenow")).toBe("3");
expect(wrapper.find(".progress").find(".bg-success").attributes("aria-valuenow")).toBe("1");
expect(wrapper.find(".progress").find(".bg-danger").attributes("aria-valuenow")).toBe("1");
});

it("should update as dataset states change", async () => {
const dsc = { job_state_summary: { all_jobs: 3, running: 3, ok: 0 }, populated_state: {} };

const wrapper = await mountComponent(dsc);

expect(wrapper.find(".progress").find(".bg-warning").attributes("aria-valuenow")).toBe("3");

dsc["job_state_summary"]["ok"] = 2;
dsc["job_state_summary"]["running"] = 1;

await wrapper.setProps({ summary: new JobStateSummary(dsc) });

expect(wrapper.find(".progress").find(".bg-warning").attributes("aria-valuenow")).toBe("1");
expect(wrapper.find(".progress").find(".bg-success").attributes("aria-valuenow")).toBe("2");
});

it("should be visible when all jobs are queued", async () => {
const dsc = { job_state_summary: { all_jobs: 3, queued: 3 }, populated_state: {} };

const wrapper = await mountComponent(dsc);

expect(wrapper.find(".progress").find(".bg-secondary").attributes("aria-valuenow")).toBe("3");
});
});
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
<!-- Job state progress bar for a collection. There's another similar component
at components/JobStates/CollectionJobStates but it relies on the backbone data
model, so probably has to go eventually.-->
<script setup lang="ts">
import { JobStateSummary } from "./JobStateSummary";

interface Props {
summary: JobStateSummary;
}

defineProps<Props>();
</script>

<template>
<div class="collection-progress">
<b-progress v-if="!summary.isTerminal" :max="summary.jobCount">
<b-progress-bar
<BProgress v-if="!summary.isTerminal" :max="summary.jobCount">
<BProgressBar
v-if="summary.errorCount"
v-b-tooltip.hover="summary.errorCountText"
:value="summary.errorCount"
variant="danger" />
<b-progress-bar
<BProgressBar
v-if="summary.okCount"
v-b-tooltip.hover="summary.okCountText"
:value="summary.okCount"
variant="success" />
<b-progress-bar
<BProgressBar
v-if="summary.runningCount"
v-b-tooltip.hover="summary.runningCountText"
:value="summary.runningCount"
variant="warning" />
<b-progress-bar
<BProgressBar
v-if="summary.waitingCount"
v-b-tooltip.hover="summary.waitingCountText"
:value="summary.waitingCount"
variant="secondary" />
</b-progress>
</BProgress>
</div>
</template>
<script>
import { JobStateSummary } from "./JobStateSummary";

export default {
props: {
summary: { type: JobStateSummary, required: true },
},
};
</script>
Loading

0 comments on commit 72c329b

Please sign in to comment.