You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
autoflow-web-console/src/components/templates/stepconfig/ViewComponent.vue

227 lines
7.9 KiB

<script setup lang="ts">
import { defineProps, onMounted, watch, ref, computed } from "vue";
import { WorkflowStepService } from "@/components/service/management/workflowStepService";
import { WorkflowService } from "@/components/service/management/workflowService"; // ⬅️ 추가
const props = defineProps<{ id: number | string }>();
const emit = defineEmits<{ (e: "close"): void }>();
const loading = ref(false);
const detailRaw = ref<any | null>(null);
// ⬇️ 워크플로우 이름은 별도 상태로
const workflowName = ref<string>("-");
const formatIso = (s?: string) => (s ? s.replace("T", " ").slice(0, 19) : "-");
const mapToViewModel = (raw: any) => ({
stepName: raw?.stepName ?? raw?.name ?? "-",
// 여기 값은 임시, 실제 표시는 아래 computed에서 workflowName ref로 덮어씀
workflowName: raw?.workflowName ?? raw?.pipelineName ?? "-",
createdDate: formatIso(raw?.regDttm ?? raw?.regDt ?? raw?.createdAt),
createdId: raw?.regUserId ?? raw?.createdBy ?? "-",
});
const info = computed(() => ({
...mapToViewModel(detailRaw.value || {}),
workflowName: workflowName.value, // ⬅️ 최종 표시는 이 값
}));
// ⬇️ id → 워크플로우 이름 조회
async function resolveWorkflowName(raw: any) {
// 1) 응답에 이미 이름이 있으면 그걸 사용
const direct =
raw?.workflowName ||
raw?.pipelineName ||
raw?.workflow?.workflowName ||
raw?.workflow?.name;
if (direct) {
workflowName.value = direct;
return;
}
// 2) FK 후보에서 워크플로우 id 뽑기 (환경에 따라 필드명이 다를 수 있어 방어적으로)
const wfId =
raw?.workflowStepId ?? // 지금 콘솔에 보이는 필드
raw?.workflowId ??
raw?.workflow?.id ??
null;
if (!wfId) {
workflowName.value = "-";
return;
}
try {
const res = await WorkflowService.view(Number(wfId));
const w = res?.data ?? res;
workflowName.value = w?.workflowName || w?.name || `#${wfId}`;
} catch (e) {
console.warn("[ViewComponent] workflow fetch failed:", e);
workflowName.value = `#${wfId}`; // 최소한 id라도 보여주기
}
}
async function fetchDetail(id: number | string) {
const idNum = typeof id === "string" ? Number(id) : id;
if (!Number.isFinite(idNum as number)) return;
loading.value = true;
try {
const res = await WorkflowStepService.view(idNum as number);
const raw = res?.data ?? res;
detailRaw.value = raw;
// ⬇️ 여기서 이름 해석
await resolveWorkflowName(raw);
console.log("[ViewComponent] raw:", raw);
console.log("[ViewComponent] info:", info.value);
} catch (e) {
console.error("[ViewComponent] fetch detail error:", e);
} finally {
loading.value = false;
}
}
onMounted(() => fetchDetail(props.id));
watch(
() => props.id,
(now) => {
if (now !== undefined && now !== null && now !== "") fetchDetail(now);
},
);
</script>
<template>
<v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
<!-- 상단 타이틀 -->
<v-card flat class="bg-shades-transparent w-100 mb-6">
<v-card-item class="text-h5 font-weight-bold pt-0 pa-5 pl-0">
<div class="d-flex flex-row justify-start align-center">
<div class="text-primary">View Details</div>
</div>
</v-card-item>
</v-card>
<!-- Workflow Step Information -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Workflow Step Information</span>
</v-card-title>
<v-card-text class="py-4">
<v-row align="center" class="mb-2">
<v-col cols="3" class="font-weight-bold">Workflow Step Name</v-col>
<v-col cols="3">{{ info.stepName }}</v-col>
<v-col cols="3" class="font-weight-bold">Workflow Name</v-col>
<v-col cols="3">{{ info.workflowName }}</v-col>
</v-row>
<v-divider />
<v-row align="center" class="mt-2">
<v-col cols="3" class="font-weight-bold">Created Date</v-col>
<v-col cols="3">{{ info.createdDate }}</v-col>
<v-col cols="3" class="font-weight-bold">Created ID</v-col>
<v-col cols="3">{{ info.createdId }}</v-col>
</v-row>
</v-card-text>
<v-sheet class="d-flex justify-end mt-4">
<v-btn color="primary" @click="emit('close')">Back to List</v-btn>
</v-sheet>
</v-card>
<!-- Dataset -->
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Dataset</span>
</v-card-title>
<v-card-text class="py-4">
<v-row align="center">
<v-col cols="3" class="font-weight-bold">Dataset Name</v-col>
<v-col cols="3">야간 주행용 레이더 데이터셋 구성</v-col>
<v-col cols="3" class="font-weight-bold">Version</v-col>
<v-col cols="3">v2.0</v-col>
</v-row>
</v-card-text>
</v-card> -->
<!-- Training Script -->
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Training Script</span>
</v-card-title>
<v-card-text class="py-4">
<v-row align="center" class="mb-2">
<v-col cols="3" class="font-weight-bold">Script File</v-col>
<v-col cols="9">baseline_train.py</v-col>
</v-row>
<v-divider />
<v-row align="center" class="mt-2">
<v-col cols="3" class="font-weight-bold">Script File Path</v-col>
<v-col cols="9" style="word-break: break-all">
/mnt/nfs/model_code/baseline/baseline_train.py
</v-col>
</v-row>
</v-card-text>
</v-card> -->
<!-- Hyperparameters -->
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Hyperparameters</span>
</v-card-title>
<v-card-text class="py-4">
<v-row align="center" class="mb-2">
<v-col cols="3" class="font-weight-bold">Batch Size</v-col>
<v-col cols="3">64</v-col>
<v-col cols="3" class="font-weight-bold">Learning Rate</v-col>
<v-col cols="3">0.001</v-col>
</v-row>
<v-divider />
<v-row align="center" class="mt-2">
<v-col cols="3" class="font-weight-bold">Optimizer</v-col>
<v-col cols="3">Adam</v-col>
<v-col cols="3" class="font-weight-bold">Epochs</v-col>
<v-col cols="3">20</v-col>
</v-row>
</v-card-text>
</v-card> -->
<!-- Resource & Scheduling -->
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Resource & Scheduling</span>
</v-card-title>
<v-card-text class="py-4">
<v-row align="center" class="mb-2">
<v-col cols="3" class="font-weight-bold">CPU Cores</v-col>
<v-col cols="3">4</v-col>
<v-col cols="3" class="font-weight-bold">Memory</v-col>
<v-col cols="3">16Gi</v-col>
</v-row>
<v-divider />
<v-row align="center" class="mt-2">
<v-col cols="3" class="font-weight-bold">GPU</v-col>
<v-col cols="9">1 (NVIDIA A100)</v-col>
</v-row>
</v-card-text>
</v-card> -->
<!-- Docker image -->
<!-- <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2">
<v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Docker image</span>
</v-card-title>
<v-card-text class="py-4">
<v-sheet class="pa-2" elevation="2">
kubeflownotebookswg/jupyter-pytorch-cuda-full:v1.9.2
</v-sheet>
</v-card-text>
</v-card> -->
</v-container>
</template>
<style scoped></style>