Skip to content

Commit

Permalink
Merge pull request #18028 from davelopez/refactor_history_export_to_t…
Browse files Browse the repository at this point in the history
…ypescript

Refactor convert HistoryExport component to Typescript
  • Loading branch information
bgruening authored Apr 22, 2024
2 parents 5097cb7 + a37b42f commit f96ca10
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 72 deletions.
9 changes: 6 additions & 3 deletions client/src/api/histories.export.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { components } from "@/api/schema";
import { fetcher } from "@/api/schema";
import type { ObjectExportTaskResponse } from "@/components/Common/models/exportRecordModel";
import { ExportRecordModel } from "@/components/Common/models/exportRecordModel";
import {
type ExportRecord,
ExportRecordModel,
type ObjectExportTaskResponse,
} from "@/components/Common/models/exportRecordModel";
import { DEFAULT_EXPORT_PARAMS } from "@/composables/shortTermStorage";

type ModelStoreFormat = components["schemas"]["ModelStoreFormat"];
Expand Down Expand Up @@ -69,7 +72,7 @@ export async function exportHistoryToFileSource(
* @param record The export record to be imported
* @returns A promise with the request response
*/
export async function reimportHistoryFromRecord(record: ExportRecordModel) {
export async function reimportHistoryFromRecord(record: ExportRecord) {
return _importFromStoreAsync({
store_content_uri: record.importUri,
model_store_format: record.modelStoreFormat,
Expand Down
15 changes: 8 additions & 7 deletions client/src/components/Common/ExportRecordDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { BAlert, BButton, BCard, BCardTitle } from "bootstrap-vue";
import { computed } from "vue";
import { ExportRecordModel } from "./models/exportRecordModel";
import type { ColorVariant } from ".";
import { ExportRecord } from "./models/exportRecordModel";
import LoadingSpan from "@/components/LoadingSpan.vue";
library.add(faCheckCircle, faClock, faExclamationCircle, faExclamationTriangle, faLink);
interface Props {
record: ExportRecordModel;
record: ExportRecord;
objectType: string;
actionMessage?: string;
actionMessageVariant?: string;
actionMessageVariant?: ColorVariant;
}
const props = withDefaults(defineProps<Props>(), {
Expand All @@ -31,9 +32,9 @@ const props = withDefaults(defineProps<Props>(), {
const emit = defineEmits<{
(e: "onActionMessageDismissed"): void;
(e: "onReimport", record: ExportRecordModel): void;
(e: "onDownload", record: ExportRecordModel): void;
(e: "onCopyDownloadLink", record: ExportRecordModel): void;
(e: "onReimport", record: ExportRecord): void;
(e: "onDownload", record: ExportRecord): void;
(e: "onCopyDownloadLink", record: ExportRecord): void;
}>();
const title = computed(() => (props.record.isReady ? `Exported` : `Export started`));
Expand Down Expand Up @@ -112,7 +113,7 @@ function onMessageDismissed() {
<p class="mt-3">You can do the following actions with this {{ props.objectType }} export:</p>

<BAlert
v-if="props.actionMessage !== null"
v-if="props.actionMessage !== undefined"
:variant="props.actionMessageVariant"
show
fade
Expand Down
16 changes: 8 additions & 8 deletions client/src/components/Common/ExportRecordTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { BButton, BButtonGroup, BButtonToolbar, BCard, BCollapse, BLink, BTable } from "bootstrap-vue";
import { computed, ref } from "vue";
import { type ExportRecordModel } from "./models/exportRecordModel";
import { type ExportRecord } from "./models/exportRecordModel";
library.add(faCheckCircle, faDownload, faExclamationCircle, faFileImport, faLink, faSpinner);
interface Props {
records: ExportRecordModel[];
records: ExportRecord[];
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "onReimport", record: ExportRecordModel): void;
(e: "onDownload", record: ExportRecordModel): void;
(e: "onCopyDownloadLink", record: ExportRecordModel): void;
(e: "onReimport", record: ExportRecord): void;
(e: "onDownload", record: ExportRecord): void;
(e: "onCopyDownloadLink", record: ExportRecord): void;
}>();
const fields = [
Expand All @@ -40,15 +40,15 @@ const isExpanded = ref(false);
const title = computed(() => (isExpanded.value ? `Hide old export records` : `Show old export records`));
async function reimportObject(record: ExportRecordModel) {
async function reimportObject(record: ExportRecord) {
emit("onReimport", record);
}
function downloadObject(record: ExportRecordModel) {
function downloadObject(record: ExportRecord) {
emit("onDownload", record);
}
function copyDownloadLink(record: ExportRecordModel) {
function copyDownloadLink(record: ExportRecord) {
emit("onCopyDownloadLink", record);
}
</script>
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/Common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// TODO: Not sure if this is the best place for this type
export type ColorVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
23 changes: 15 additions & 8 deletions client/src/components/Common/models/exportRecordModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface ExportRecord {
readonly stsDownloadId?: string;
readonly isStsDownload: boolean;
readonly canDownload: boolean;
readonly modelStoreFormat: string;
readonly modelStoreFormat: ModelStoreFormat;
readonly exportParams?: ExportParams;
readonly duration?: number | null;
readonly canExpire: boolean;
Expand Down Expand Up @@ -62,17 +62,24 @@ export class ExportParamsModel implements ExportParams {
return Boolean(this._params?.include_hidden);
}

public equals(otherExportParams?: ExportParamsModel) {
public equals(otherExportParams?: ExportParams) {
if (!otherExportParams) {
return false;
}
return (
this.modelStoreFormat === otherExportParams.modelStoreFormat &&
this.includeFiles === otherExportParams.includeFiles &&
this.includeDeleted === otherExportParams.includeDeleted &&
this.includeHidden === otherExportParams.includeHidden
);
return areEqual(this, otherExportParams);
}
}

export function areEqual(params1?: ExportParams, params2?: ExportParams): boolean {
if (!params1 || !params2) {
return false;
}
return (
params1.modelStoreFormat === params2.modelStoreFormat &&
params1.includeFiles === params2.includeFiles &&
params1.includeDeleted === params2.includeDeleted &&
params1.includeHidden === params2.includeHidden
);
}

export class ExportRecordModel implements ExportRecord {
Expand Down
13 changes: 6 additions & 7 deletions client/src/components/History/Export/ExportOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import { BCard, BCollapse, BFormCheckbox, BFormGroup, BFormSelect, BLink } from
import { computed, reactive, ref } from "vue";
import { AVAILABLE_EXPORT_FORMATS } from "@/api/histories.export";
import { ExportParamsModel } from "@/components/Common/models/exportRecordModel";
import type { ExportParams } from "@/components/Common/models/exportRecordModel";
const props = defineProps({
exportParams: {
type: ExportParamsModel,
required: true,
},
});
interface Props {
exportParams: ExportParams;
}
const props = defineProps<Props>();
const emit = defineEmits(["onValueChanged"]);
Expand Down
77 changes: 39 additions & 38 deletions client/src/components/History/Export/HistoryExport.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
<script setup>
<script setup lang="ts">
import { library } from "@fortawesome/fontawesome-svg-core";
import { faFileExport } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { BAlert, BButton, BCard, BTab, BTabs } from "bootstrap-vue";
import LoadingSpan from "components/LoadingSpan";
import { useConfirmDialog } from "composables/confirmDialog";
import { useFileSources } from "composables/fileSources";
import { DEFAULT_EXPORT_PARAMS, useShortTermStorage } from "composables/shortTermStorage";
import { useTaskMonitor } from "composables/taskMonitor";
import { copy as sendToClipboard } from "utils/clipboard";
import { computed, onMounted, reactive, ref, watch } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import { RouterLink } from "vue-router";
import {
exportHistoryToFileSource,
fetchHistoryExportRecords,
reimportHistoryFromRecord,
} from "@/api/histories.export";
import type { ColorVariant } from "@/components/Common";
import { areEqual, ExportParams, ExportRecord } from "@/components/Common/models/exportRecordModel";
import { useConfirmDialog } from "@/composables/confirmDialog";
import { useFileSources } from "@/composables/fileSources";
import { DEFAULT_EXPORT_PARAMS, useShortTermStorage } from "@/composables/shortTermStorage";
import { useTaskMonitor } from "@/composables/taskMonitor";
import { useHistoryStore } from "@/stores/historyStore";
import { copy as sendToClipboard } from "@/utils/clipboard";
import { absPath } from "@/utils/redirect";
import { errorMessageAsString } from "@/utils/simple-error";
import ExportOptions from "./ExportOptions.vue";
import ExportToFileSourceForm from "@/components/Common/ExportForm.vue";
import ExportToRDMRepositoryForm from "@/components/Common/ExportRDMForm.vue";
import ExportRecordDetails from "@/components/Common/ExportRecordDetails.vue";
import ExportRecordTable from "@/components/Common/ExportRecordTable.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
const {
isRunning: isExportTaskRunning,
Expand All @@ -45,20 +48,19 @@ const {
const { confirm } = useConfirmDialog();
const props = defineProps({
historyId: {
type: String,
required: true,
},
});
interface Props {
historyId: string;
}
const props = defineProps<Props>();
library.add(faFileExport);
const POLLING_DELAY = 3000;
const exportParams = reactive(DEFAULT_EXPORT_PARAMS);
const exportParams = ref(DEFAULT_EXPORT_PARAMS);
const isLoadingRecords = ref(true);
const exportRecords = ref(null);
const exportRecords = ref<ExportRecord[]>([]);
const historyName = computed(() => history.value?.name ?? props.historyId);
const latestExportRecord = computed(() => (exportRecords.value?.length ? exportRecords.value.at(0) : null));
Expand All @@ -67,10 +69,10 @@ const isLatestExportRecordReadyToDownload = computed(
latestExportRecord.value &&
latestExportRecord.value.isUpToDate &&
latestExportRecord.value.canDownload &&
latestExportRecord.value.exportParams?.equals(exportParams)
areEqual(latestExportRecord.value.exportParams, exportParams.value)
);
const canGenerateDownload = computed(() => !isPreparingDownload.value && !isLatestExportRecordReadyToDownload.value);
const previousExportRecords = computed(() => (exportRecords.value ? exportRecords.value.slice(1) : null));
const previousExportRecords = computed(() => (exportRecords.value ? exportRecords.value.slice(1) : []));
const hasPreviousExports = computed(() => previousExportRecords.value?.length > 0);
const availableRecordsMessage = computed(() =>
isLoadingRecords.value
Expand All @@ -85,9 +87,9 @@ const history = computed(() => {
return history;
});
const errorMessage = ref(null);
const actionMessage = ref(null);
const actionMessageVariant = ref(null);
const errorMessage = ref<string | undefined>(undefined);
const actionMessage = ref<string | undefined>(undefined);
const actionMessageVariant = ref<ColorVariant | undefined>(undefined);
onMounted(async () => {
updateExports();
Expand All @@ -103,7 +105,7 @@ watch(isExportTaskRunning, (newValue, oldValue) => {
async function updateExports() {
isLoadingRecords.value = true;
try {
errorMessage.value = null;
errorMessage.value = undefined;
exportRecords.value = await fetchHistoryExportRecords(props.historyId);
const shouldWaitForTask =
latestExportRecord.value?.isPreparing &&
Expand All @@ -120,36 +122,36 @@ async function updateExports() {
errorMessage.value = "Something went wrong trying to export the history. Please try again later.";
}
} catch (error) {
errorMessage.value = error;
errorMessage.value = errorMessageAsString(error);
} finally {
isLoadingRecords.value = false;
}
}
async function doExportToFileSource(exportDirectory, fileName) {
await exportHistoryToFileSource(props.historyId, exportDirectory, fileName, exportParams);
async function doExportToFileSource(exportDirectory: string, fileName: string) {
await exportHistoryToFileSource(props.historyId, exportDirectory, fileName, exportParams.value);
updateExports();
}
async function prepareDownload() {
await prepareHistoryDownload(props.historyId, { pollDelayInMs: POLLING_DELAY, exportParams: exportParams });
await prepareHistoryDownload(props.historyId, { pollDelayInMs: POLLING_DELAY, exportParams: exportParams.value });
updateExports();
}
function downloadFromRecord(record) {
function downloadFromRecord(record: ExportRecord) {
if (record.canDownload) {
downloadObjectByRequestId(record.stsDownloadId);
downloadObjectByRequestId(record.stsDownloadId!);
}
}
function copyDownloadLinkFromRecord(record) {
function copyDownloadLinkFromRecord(record: ExportRecord) {
if (record.canDownload) {
const relativeLink = getDownloadObjectUrl(record.stsDownloadId);
const relativeLink = getDownloadObjectUrl(record.stsDownloadId!);
sendToClipboard(absPath(relativeLink), "Download link copied to your clipboard");
}
}
async function reimportFromRecord(record) {
async function reimportFromRecord(record: ExportRecord) {
const confirmed = await confirm(
`Do you really want to import a new copy of this history exported ${record.elapsedTime}?`
);
Expand All @@ -168,15 +170,14 @@ async function reimportFromRecord(record) {
}
function onActionMessageDismissedFromRecord() {
actionMessage.value = null;
actionMessageVariant.value = null;
actionMessage.value = undefined;
actionMessageVariant.value = undefined;
}
function updateExportParams(newParams) {
exportParams.modelStoreFormat = newParams.modelStoreFormat;
exportParams.includeFiles = newParams.includeFiles;
exportParams.includeDeleted = newParams.includeDeleted;
exportParams.includeHidden = newParams.includeHidden;
function updateExportParams(newParams: ExportParams) {
exportParams.value = {
...newParams,
};
}
</script>
<template>
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Workflow/WorkflowActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { useConfirmDialog } from "@/composables/confirmDialog";
import { Toast } from "@/composables/toast";
import { useUserStore } from "@/stores/userStore";
import type { ColorVariant } from "../Common";
import AsyncButton from "@/components/Common/AsyncButton.vue";
library.add(faCaretDown, faExternalLinkAlt, faEye, faFileExport, farStar, faStar, faTrash);
Expand All @@ -41,7 +43,7 @@ type BaseAction = {
target?: "_blank";
size: "sm" | "md" | "lg";
component: "async" | "button";
variant: "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark" | "link";
variant: ColorVariant | "link";
onClick?: (e?: MouseEvent | KeyboardEvent) => void;
};
Expand Down

0 comments on commit f96ca10

Please sign in to comment.