fix: workflow, workflowstep, project 수정

main
jschoi 9 months ago
parent c254117106
commit efc6d0651e

2
components.d.ts vendored

@ -25,7 +25,7 @@ declare module 'vue' {
IconModifyBtn: typeof import('./src/components/atoms/button/IconModifyBtn.vue')['default'] IconModifyBtn: typeof import('./src/components/atoms/button/IconModifyBtn.vue')['default']
IconSettingBtn: typeof import('./src/components/atoms/button/IconSettingBtn.vue')['default'] IconSettingBtn: typeof import('./src/components/atoms/button/IconSettingBtn.vue')['default']
LayoutComponent: typeof import('./src/components/common/LayoutComponent.vue')['default'] LayoutComponent: typeof import('./src/components/common/LayoutComponent.vue')['default']
ListComponent: typeof import('./src/components/home/ListComponent.vue')['default'] ListComponent: typeof import('./src/components/templates/Datasets/ListComponent.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SidebarHeader: typeof import('./src/components/common/SidebarHeader.vue')['default'] SidebarHeader: typeof import('./src/components/common/SidebarHeader.vue')['default']

@ -74,8 +74,8 @@ const nowLocalIso = (): string => {
async function submit() { async function submit() {
errorMsg.value = ""; errorMsg.value = "";
const name = form.value.name.trim();
const name = form.value.name.trim();
if (!name) { if (!name) {
errorMsg.value = "Workflow Name은 필수입니다."; errorMsg.value = "Workflow Name은 필수입니다.";
return; return;
@ -85,7 +85,6 @@ async function submit() {
const authObj = const authObj =
(typeof storage?.getAuth === "function" ? storage.getAuth() : null) ?? (typeof storage?.getAuth === "function" ? storage.getAuth() : null) ??
JSON.parse(localStorage.getItem("autoflow-auth") || "{}"); JSON.parse(localStorage.getItem("autoflow-auth") || "{}");
const regUserId = const regUserId =
authObj?.userInfo?.username ?? authObj?.userInfo?.username ??
authObj?.userinfo?.username ?? authObj?.userinfo?.username ??
@ -98,36 +97,58 @@ async function submit() {
return; return;
} }
if (!projectId.value) {
errorMsg.value = "프로젝트가 선택되지 않았습니다.";
return;
}
const now = nowLocalIso(); const now = nowLocalIso();
const payload: Workflow = {
workflowName: name,
workflowDescription: form.value.description?.trim() || "",
uploadYn: "Y",
regUserId,
regDt: now,
modDt: now,
projectId: projectId.value,
};
try { try {
saving.value = true; saving.value = true;
if (isEdit.value) { if (isEdit.value) {
// : id ( deviceKey id ) // ===== =====
const rawId = props.editData?.id ?? props.editData?.deviceKey; const rawId = props.editData?.id ?? props.editData?.deviceKey;
const id = Number(rawId); const id = Number(rawId);
if (!id) { if (!id) {
errorMsg.value = "수정할 ID가 없습니다."; errorMsg.value = "수정할 ID가 없습니다.";
return; return;
} }
const { data } = await WorkflowService.update(id, payload); //
const viewRes = await WorkflowService.view(id);
const current = (viewRes?.data ?? viewRes) || {};
const updatePayload: any = {
id,
workflowName: name,
workflowDescription: form.value.description?.trim() || "",
uploadYn: current.uploadYn ?? "Y",
// (null )
regUserId: current.regUserId ?? regUserId,
regDt: current.regDt ?? now,
projectId: current.projectId ?? projectId.value,
//
modDt: now,
};
const { data } = await WorkflowService.update(id, updatePayload);
emit("saved", data); emit("saved", data);
emit("close-modal"); emit("close-modal");
} else { } else {
// // ===== =====
const { data } = await WorkflowService.add(payload); const createPayload: any = {
workflowName: name,
workflowDescription: form.value.description?.trim() || "",
uploadYn: "Y",
regUserId, //
regDt: now, //
projectId: projectId.value,
// modDt ( )
};
const { data } = await WorkflowService.add(createPayload);
emit("saved", data); emit("saved", data);
emit("close-modal"); emit("close-modal");
} }

@ -5,12 +5,9 @@ import { storeToRefs } from "pinia";
import { useAutoflowStore } from "@/stores/autoflowStore"; import { useAutoflowStore } from "@/stores/autoflowStore";
import type { AxiosError } from "axios"; import type { AxiosError } from "axios";
import { WorkflowStepService } from "@/components/service/management/workflowStepService"; import { WorkflowStepService } from "@/components/service/management/workflowStepService";
import { WorkflowService } from "@/components/service/management/workflowService"; //
const props = defineProps<{ const props = defineProps<{ editData: any; mode: "create" | "edit" }>();
editData: any;
mode: "create" | "edit";
}>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "close-modal"): void; (e: "close-modal"): void;
(e: "saved", value: any): void; (e: "saved", value: any): void;
@ -22,21 +19,71 @@ const { projectId } = storeToRefs(useAutoflowStore());
const saving = ref(false); const saving = ref(false);
const errorMsg = ref(""); const errorMsg = ref("");
// ( UI: stepName, status) // ===== =====
const workflowsLoading = ref(false);
const workflowOptions = ref<Array<{ title: string; value: number }>>([]);
const selectedWorkflowId = ref<number | null>(null);
async function fetchWorkflows() {
try {
workflowsLoading.value = true;
// 1) /api/workflows () or 2) search (content)
const res =
(await (WorkflowService as any).list?.()) ??
(await (WorkflowService as any).search?.({ page: 0, size: 1000 }));
const raw = res?.data ?? res;
const list = Array.isArray(raw?.content)
? raw.content
: Array.isArray(raw)
? raw
: [];
const filtered = projectId.value
? list.filter((w: any) => Number(w.projectId) === Number(projectId.value))
: list;
workflowOptions.value = filtered.map((w: any) => ({
title:
(w.workflowName || w.name || `Workflow #${w.id}`) +
(w.version ? ` (v${w.version})` : ""),
value: Number(w.id),
}));
//
if (isEdit.value && selectedWorkflowId.value == null) {
const wid =
props.editData?.workflowStepId ??
props.editData?.workflowId ??
props.editData?.workflow?.id ??
null;
if (wid != null) selectedWorkflowId.value = Number(wid);
}
} catch (e) {
console.error("[Dialog] 워크플로우 목록 조회 실패:", e);
workflowOptions.value = [];
} finally {
workflowsLoading.value = false;
}
}
// ===== =====
type StepStatus = "Running" | "Success" | "Fail"; type StepStatus = "Running" | "Success" | "Fail";
const form = ref({ const form = ref({ stepName: "", status: "Running" as StepStatus });
stepName: "",
status: "Running" as StepStatus,
});
function hydrateFormFromEdit(data: any) { function hydrateFormFromEdit(data: any) {
if (!data) return; if (!data) return;
form.value.stepName = data?.stepName ?? data?.name ?? ""; form.value.stepName = data?.stepName ?? data?.name ?? "";
form.value.status = (data?.status as StepStatus) ?? "Running"; form.value.status = (data?.status as StepStatus) ?? "Running";
// ( )
const wid =
data?.workflowStepId ?? data?.workflowId ?? data?.workflow?.id ?? null;
selectedWorkflowId.value = wid != null ? Number(wid) : null;
} }
onMounted(() => { onMounted(() => {
if (isEdit.value) hydrateFormFromEdit(props.editData); if (isEdit.value) hydrateFormFromEdit(props.editData);
fetchWorkflows();
}); });
watch( watch(
() => props.editData, () => props.editData,
@ -44,10 +91,11 @@ watch(
if (isEdit.value) hydrateFormFromEdit(v); if (isEdit.value) hydrateFormFromEdit(v);
}, },
); );
watch(projectId, () => fetchWorkflows());
const nowLocalIso = (): string => { const nowLocalIso = (): string => {
const t = new Date(Date.now() - new Date().getTimezoneOffset() * 60000); const t = new Date(Date.now() - new Date().getTimezoneOffset() * 60000);
return t.toISOString().slice(0, 23); // 'YYYY-MM-DDTHH:mm:ss.SSS' return t.toISOString().slice(0, 23);
}; };
const regUserId = (() => { const regUserId = (() => {
@ -55,7 +103,6 @@ const regUserId = (() => {
const authObj = const authObj =
(typeof storage?.getAuth === "function" ? storage.getAuth() : null) ?? (typeof storage?.getAuth === "function" ? storage.getAuth() : null) ??
JSON.parse(localStorage.getItem("autoflow-auth") || "{}"); JSON.parse(localStorage.getItem("autoflow-auth") || "{}");
return ( return (
authObj?.userInfo?.username ?? authObj?.userInfo?.username ??
authObj?.userinfo?.username ?? authObj?.userinfo?.username ??
@ -71,62 +118,42 @@ const regUserId = (() => {
async function submit() { async function submit() {
errorMsg.value = ""; errorMsg.value = "";
// //
const stepName = form.value.stepName.trim(); const stepName = form.value.stepName.trim();
if (!stepName) { if (!stepName) return (errorMsg.value = "Step Name은 필수입니다.");
errorMsg.value = "Step Name은 필수입니다."; if (!regUserId)
return; return (errorMsg.value = "로그인 사용자 정보를 찾을 수 없습니다.");
} if (!projectId.value)
if (!regUserId) { return (errorMsg.value = "프로젝트가 선택되지 않았습니다.");
errorMsg.value = "로그인 사용자 정보를 찾을 수 없습니다."; if (!selectedWorkflowId.value)
return; return (errorMsg.value = "Workflow를 선택해주세요."); //
}
if (!projectId.value) { // (NOT NULL )
errorMsg.value = "프로젝트가 선택되지 않았습니다."; const payload: any = {
return;
}
// payload
const now = nowLocalIso();
const payload = {
stepName, stepName,
status: form.value.status, // not null status: form.value.status,
regUserId, // not null regUserId,
regDt: now, // not null ( ) regDt: nowLocalIso(),
version: 1, // not null () version: 1,
projectId: projectId.value, // not null projectId: projectId.value,
workflowStepId: selectedWorkflowId.value, // 500
// (pipelineId = /)
// pipelineId: undefined,
// startTime: undefined,
// endTime: undefined,
// logPath: undefined,
}; };
try { try {
saving.value = true; saving.value = true;
if (isEdit.value) { if (isEdit.value) {
// : id ( deviceKey id )
const rawId = props.editData?.id ?? props.editData?.deviceKey; const rawId = props.editData?.id ?? props.editData?.deviceKey;
const id = Number(rawId); const id = Number(rawId);
if (!id) return (errorMsg.value = "수정할 ID가 없습니다.");
if (!id) { const { data } = await WorkflowStepService.update(id, payload);
errorMsg.value = "수정할 ID가 없습니다.";
return;
}
const { data } = await WorkflowStepService.update(id, payload as any);
emit("saved", data); emit("saved", data);
emit("close-modal");
} else { } else {
const { data } = await WorkflowStepService.add(payload as any); const { data } = await WorkflowStepService.add(payload);
emit("saved", data); emit("saved", data);
emit("close-modal");
} }
emit("close-modal");
} catch (e) { } catch (e) {
const err = e as AxiosError; console.error("워크플로우 스텝 저장 실패:", e as AxiosError);
console.error("워크플로우 스텝 저장 실패:", err);
errorMsg.value = "저장에 실패했습니다. 잠시 후 다시 시도하세요."; errorMsg.value = "저장에 실패했습니다. 잠시 후 다시 시도하세요.";
} finally { } finally {
saving.value = false; saving.value = false;
@ -142,7 +169,6 @@ onBeforeUnmount(() => window.removeEventListener("keydown", onEsc));
<template> <template>
<v-card> <v-card>
<!-- 타이틀: 동일 스타일 -->
<v-card-title <v-card-title
class="text-white font-weight-bold text-h6" class="text-white font-weight-bold text-h6"
style="background-color: #1976d2" style="background-color: #1976d2"
@ -150,17 +176,18 @@ onBeforeUnmount(() => window.removeEventListener("keydown", onEsc));
{{ isEdit ? "Edit Workflow Step" : "Create Workflow Step" }} {{ isEdit ? "Edit Workflow Step" : "Create Workflow Step" }}
</v-card-title> </v-card-title>
<!-- 영역 -->
<v-card-text class="pa-6"> <v-card-text class="pa-6">
<div class="text-subtitle-1 font-weight-medium mb-4"> <div class="text-subtitle-1 font-weight-medium mb-4">
Workflow Step Information Workflow Step Information
</div> </div>
<v-form @submit.prevent="submit"> <v-form @submit.prevent="submit">
<!-- 워크플로우 드롭다운 -->
<div class="mb-5"> <div class="mb-5">
<label class="text-subtitle-2 font-weight-medium mb-1 d-block"> <label class="text-subtitle-2 font-weight-medium mb-1 d-block"
Step Name >Step Name</label
</label> >
<v-text-field <v-text-field
v-model="form.stepName" v-model="form.stepName"
variant="outlined" variant="outlined"
@ -170,11 +197,28 @@ onBeforeUnmount(() => window.removeEventListener("keydown", onEsc));
required required
/> />
</div> </div>
<div class="mb-5">
<label class="text-subtitle-2 font-weight-medium mb-1 d-block"
>Workflow</label
>
<v-select
v-model="selectedWorkflowId"
:items="workflowOptions"
item-title="title"
item-value="value"
variant="outlined"
:loading="workflowsLoading"
:disabled="saving || workflowsLoading"
dense
hide-details
placeholder="워크플로우를 선택하세요"
/>
</div>
<div class="mb-5"> <div class="mb-5">
<label class="text-subtitle-2 font-weight-medium mb-1 d-block"> <label class="text-subtitle-2 font-weight-medium mb-1 d-block"
Status >Status</label
</label> >
<v-select <v-select
v-model="form.status" v-model="form.status"
:items="['Running', 'Success', 'Fail']" :items="['Running', 'Success', 'Fail']"
@ -189,19 +233,17 @@ onBeforeUnmount(() => window.removeEventListener("keydown", onEsc));
</v-form> </v-form>
</v-card-text> </v-card-text>
<!-- 액션 영역: 동일 버튼 배치/텍스트 -->
<v-card-actions class="justify-end" style="padding: 16px 24px"> <v-card-actions class="justify-end" style="padding: 16px 24px">
<v-btn color="success" :loading="saving" @click="submit"> <v-btn color="success" :loading="saving" @click="submit">{{
{{ isEdit ? "Update" : "Save" }} isEdit ? "Update" : "Save"
</v-btn> }}</v-btn>
<v-btn <v-btn
text text
class="white--text" class="white--text"
:disabled="saving" :disabled="saving"
@click="$emit('close-modal')" @click="$emit('close-modal')"
>Close</v-btn
> >
Close
</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</template> </template>

@ -10,7 +10,6 @@ export const WorkflowService = {
getAll: () => { getAll: () => {
return request.get("/api/workflows", {}); return request.get("/api/workflows", {});
}, },
delete: (id: Number) => { delete: (id: Number) => {
return request.delete(`/api/workflows/${id}`, {}); return request.delete(`/api/workflows/${id}`, {});
}, },

@ -1,8 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from "vue"; import { onMounted, ref, computed } from "vue";
import Plotly from "plotly.js-dist-min"; import Plotly from "plotly.js-dist-min";
import { WorkflowService } from "@/components/service/management/workflowService";
const pieChartRef = ref<HTMLElement | null>(null); const pieChartRef = ref<HTMLElement | null>(null);
const workflows = ref<any[]>([]);
const recentLimit = 10;
onMounted(() => { onMounted(() => {
if (pieChartRef.value) { if (pieChartRef.value) {
@ -105,6 +108,43 @@ const getSelectedAllData = () => {
? data.value.results.map(({ deviceKey }) => ({ deviceKey })) ? data.value.results.map(({ deviceKey }) => ({ deviceKey }))
: []; : [];
}; };
const getLatestTimestamp = (wf: any): string =>
wf?.modDttm || wf?.modDt || wf?.regDttm || wf?.regDt || "";
// "YYYY-MM-DD HH:mm"
const formatToYmdHm = (isoString: string): string => {
if (!isoString) return "-";
const dateObj = new Date(isoString);
const pad2 = (n: number) => String(n).padStart(2, "0");
return `${dateObj.getFullYear()}-${pad2(dateObj.getMonth() + 1)}-${pad2(dateObj.getDate())} ${pad2(dateObj.getHours())}:${pad2(dateObj.getMinutes())}`;
};
// ( + )
const recentWorkflowList = computed(() => {
return (workflows.value ?? [])
.map((wf: any) => ({
id: wf?.id,
title: wf?.workflowName ?? "Untitled",
timestamp: getLatestTimestamp(wf),
}))
.filter((item: { timestamp: string }) => item.timestamp) //
.sort(
(a, b) =>
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
)
.slice(0, recentLimit);
});
onMounted(async () => {
try {
const res = await WorkflowService.getAll();
workflows.value = Array.isArray(res?.data) ? res.data : [];
} catch (err) {
console.error("GET /api/workflows failed:", err);
workflows.value = [];
}
});
</script> </script>
<template> <template>
@ -138,15 +178,23 @@ const getSelectedAllData = () => {
</div> </div>
<div style="overflow-y: auto; max-height: 300px; padding: 8px 16px"> <div style="overflow-y: auto; max-height: 300px; padding: 8px 16px">
<v-list density="comfortable" nav> <v-list density="comfortable" nav>
<v-list-item v-for="(item, idx) in dummyWorkflow" :key="idx"> <v-list-item v-for="item in recentWorkflowList" :key="item.id">
<template #title> <template #title>
<div class="d-flex justify-space-between align-center w-100"> <div class="d-flex justify-space-between align-center w-100">
<span class="text-body-2 font-weight-medium">{{ <span class="text-body-2 font-weight-medium">{{
item.title item.title
}}</span> }}</span>
<span class="text-caption text-grey-lighten-1">{{ <span class="text-caption text-grey-lighten-1">
item.date {{ formatToYmdHm(item.timestamp) }}
}}</span> </span>
</div>
</template>
</v-list-item>
<v-list-item v-if="recentWorkflowList.length === 0">
<template #title>
<div class="text-caption text-grey">
최근 등록/수정된 워크플로우가 없습니다.
</div> </div>
</template> </template>
</v-list-item> </v-list-item>

@ -65,14 +65,15 @@ const data = ref({
const toRow = (s: any, no: number) => ({ const toRow = (s: any, no: number) => ({
no, no,
stepName: s.stepName ?? "-", stepName: s.stepName,
type: s.stepType ?? "-", type: s.stepType,
dataset: s.datasetName ?? "-", dataset: s.datasetName,
script: s.scriptName ?? "-", script: s.scriptName,
hyperParameters: s.hyperParams ?? "-", hyperParameters: s.hyperParams,
resource: s.resource ?? "-", resource: s.resource,
status: (s.status ?? "").toLowerCase() === "success" ? "success" : "warning", status: String(s.status).toLowerCase() === "success" ? "success" : "warning",
workflow: s.workflowName ?? s.pipelineId ?? "-", workflow: s.workflowName,
workflowId: s.workflowStepId,
deviceKey: s.id, deviceKey: s.id,
}); });
@ -266,14 +267,14 @@ const getSelectedAllData = () => {
? data.value.results.map((item: any) => ({ deviceKey: item.deviceKey })) ? data.value.results.map((item: any) => ({ deviceKey: item.deviceKey }))
: []; : [];
}; };
const closeDetail = () => {
openView.value = false;
};
const openDetailModal = (selectedItem: any) => { const openDetailModal = (selectedItem: any) => {
data.value.selectedData = selectedItem; data.value.selectedData = selectedItem;
openView.value = true; openView.value = true;
}; };
const closeDetail = () => {
openView.value = false;
};
const openCreateModal = () => { const openCreateModal = () => {
data.value.selectedData = null; data.value.selectedData = null;
data.value.modalMode = "create"; data.value.modalMode = "create";
@ -285,6 +286,7 @@ const openModifyModal = (item: any) => {
id: item.deviceKey, id: item.deviceKey,
stepName: item.stepName, stepName: item.stepName,
status: item.status, status: item.status,
workflowStepId: item.workflowId,
}; };
data.value.modalMode = "edit"; data.value.modalMode = "edit";
data.value.isStepVisible = true; data.value.isStepVisible = true;
@ -512,7 +514,11 @@ onMounted(() => {
<!-- 상세 보기 --> <!-- 상세 보기 -->
<div class="w-100" v-else> <div class="w-100" v-else>
<ViewComponent @close="closeDetail" /> <ViewComponent
v-if="data.selectedData"
:id="data.selectedData.deviceKey"
@close="closeDetail"
/>
</div> </div>
<!-- 생성/수정 모달 --> <!-- 생성/수정 모달 -->

@ -1,3 +1,98 @@
<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> <template>
<v-container fluid class="h-100 pa-5 d-flex flex-column align-center"> <v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
<!-- 상단 타이틀 --> <!-- 상단 타이틀 -->
@ -17,22 +112,27 @@
<v-card-text class="py-4"> <v-card-text class="py-4">
<v-row align="center" class="mb-2"> <v-row align="center" class="mb-2">
<v-col cols="3" class="font-weight-bold">Workflow Step Name</v-col> <v-col cols="3" class="font-weight-bold">Workflow Step Name</v-col>
<v-col cols="3">Train Model</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" class="font-weight-bold">Workflow Name</v-col>
<v-col cols="3">sentiment-analysis</v-col> <v-col cols="3">{{ info.workflowName }}</v-col>
</v-row> </v-row>
<v-divider /> <v-divider />
<v-row align="center" class="mt-2"> <v-row align="center" class="mt-2">
<v-col cols="3" class="font-weight-bold">Created Date</v-col> <v-col cols="3" class="font-weight-bold">Created Date</v-col>
<v-col cols="3">2025-02-06</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" class="font-weight-bold">Created ID</v-col>
<v-col cols="3">ADMIN_001</v-col> <v-col cols="3">{{ info.createdId }}</v-col>
</v-row> </v-row>
</v-card-text> </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> </v-card>
<!-- Dataset --> <!-- Dataset -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2"> <!-- <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"> <v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Dataset</span> <span class="font-weight-bold">Dataset</span>
</v-card-title> </v-card-title>
@ -44,10 +144,10 @@
<v-col cols="3">v2.0</v-col> <v-col cols="3">v2.0</v-col>
</v-row> </v-row>
</v-card-text> </v-card-text>
</v-card> </v-card> -->
<!-- Training Script --> <!-- Training Script -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2"> <!-- <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"> <v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Training Script</span> <span class="font-weight-bold">Training Script</span>
</v-card-title> </v-card-title>
@ -64,10 +164,10 @@
</v-col> </v-col>
</v-row> </v-row>
</v-card-text> </v-card-text>
</v-card> </v-card> -->
<!-- Hyperparameters --> <!-- Hyperparameters -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2"> <!-- <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"> <v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Hyperparameters</span> <span class="font-weight-bold">Hyperparameters</span>
</v-card-title> </v-card-title>
@ -86,10 +186,10 @@
<v-col cols="3">20</v-col> <v-col cols="3">20</v-col>
</v-row> </v-row>
</v-card-text> </v-card-text>
</v-card> </v-card> -->
<!-- Resource & Scheduling --> <!-- Resource & Scheduling -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2"> <!-- <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"> <v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Resource & Scheduling</span> <span class="font-weight-bold">Resource & Scheduling</span>
</v-card-title> </v-card-title>
@ -106,10 +206,10 @@
<v-col cols="9">1 (NVIDIA A100)</v-col> <v-col cols="9">1 (NVIDIA A100)</v-col>
</v-row> </v-row>
</v-card-text> </v-card-text>
</v-card> </v-card> -->
<!-- Docker image --> <!-- Docker image -->
<v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-6" elevation="2"> <!-- <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"> <v-card-title class="grey lighten-4 py-2 px-4">
<span class="font-weight-bold">Docker image</span> <span class="font-weight-bold">Docker image</span>
</v-card-title> </v-card-title>
@ -118,18 +218,9 @@
kubeflownotebookswg/jupyter-pytorch-cuda-full:v1.9.2 kubeflownotebookswg/jupyter-pytorch-cuda-full:v1.9.2
</v-sheet> </v-sheet>
</v-card-text> </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-card> -->
</v-sheet>
</v-card>
</v-container> </v-container>
</template> </template>
<script setup lang="ts">
import { defineEmits } from "vue";
const emit = defineEmits<{
(e: "close"): void;
}>();
</script>
<style scoped></style> <style scoped></style>

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import ListComponent from "@/components/home/ListComponent.vue"; import ListComponent from "@/components/templates/home/ListComponent.vue";
</script> </script>
<template> <template>

@ -1,5 +1,5 @@
<script setup> <script setup>
import ListComponent from "@/components/templates/Project/ListComponent.vue"; import ListComponent from "@/components/templates/projects/ListComponent.vue";
</script> </script>
<template> <template>

@ -6,12 +6,6 @@ export const menuUtils = {
value: "home", value: "home",
icon: "mdi-monitor-multiple", icon: "mdi-monitor-multiple",
}, },
{
title: "Project",
path: "/project",
value: "project",
icon: "mdi-folder-cog-outline",
},
{ {
title: "Workflows", title: "Workflows",
path: "/workflows", path: "/workflows",

Loading…
Cancel
Save