platform/lms-adm-fe release promotion snapshot
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
export type CurriculumWeek = {
|
||||
week: number;
|
||||
title: string;
|
||||
tags: string[];
|
||||
progress: number;
|
||||
state: string;
|
||||
topics: string[];
|
||||
duration: string;
|
||||
github: string;
|
||||
detail: {
|
||||
overview: string;
|
||||
learningSteps?: Array<{
|
||||
title: string;
|
||||
description: string;
|
||||
videoEnabled?: boolean;
|
||||
videoUrl?: string;
|
||||
concepts?: string[];
|
||||
}>;
|
||||
topicDetails: string[];
|
||||
topicVideoUrls?: string[];
|
||||
practiceContents?: Array<{
|
||||
title: string;
|
||||
description: string;
|
||||
}>;
|
||||
references?: CurriculumReference[];
|
||||
exampleCodes?: CurriculumReference[];
|
||||
deliverable: string;
|
||||
requiresSourceSubmission: boolean;
|
||||
};
|
||||
modules?: CurriculumModule[];
|
||||
visualizationPlatforms?: CurriculumVisualizationPlatform[];
|
||||
};
|
||||
|
||||
export type CurriculumModule = {
|
||||
id: string;
|
||||
sortOrder: number;
|
||||
category: string;
|
||||
name: string;
|
||||
folderName: string;
|
||||
templateRepositoryUrl?: string | null;
|
||||
dockerImage?: string | null;
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
export type CurriculumReference = {
|
||||
id: string;
|
||||
kind?: string;
|
||||
title: string;
|
||||
description?: string | null;
|
||||
fileName: string;
|
||||
contentType?: string | null;
|
||||
fileSizeBytes?: number | string | null;
|
||||
week?: number | string | null;
|
||||
weekNumber?: number | string | null;
|
||||
downloadUrl: string;
|
||||
createdAt?: string;
|
||||
};
|
||||
|
||||
export type CurriculumVisualizationPlatform = {
|
||||
key: string;
|
||||
type: string;
|
||||
displayName: string;
|
||||
description?: string | null;
|
||||
config?: unknown;
|
||||
};
|
||||
|
||||
export type CurriculumTagOption = {
|
||||
key: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export type InstructorCurriculumResponse = {
|
||||
course: {
|
||||
id: string;
|
||||
title: string;
|
||||
subtitle?: string | null;
|
||||
description?: string | null;
|
||||
organizationName: string;
|
||||
} | null;
|
||||
weeks: CurriculumWeek[];
|
||||
setting: {
|
||||
groupId?: string | null;
|
||||
activeWeek: number;
|
||||
activeLearningStep?: string | null;
|
||||
} | null;
|
||||
tagOptions?: CurriculumTagOption[];
|
||||
visualizationPlatforms?: CurriculumVisualizationPlatform[];
|
||||
};
|
||||
|
||||
const LMS_API_BASE_URL = (import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:4400/api').replace(/\/+$/, '');
|
||||
|
||||
export async function getInstructorCurriculum(accessToken: string, groupId?: string | null, courseId?: string | null): Promise<InstructorCurriculumResponse> {
|
||||
const params = new URLSearchParams();
|
||||
if (groupId) params.set('groupId', groupId);
|
||||
if (courseId) params.set('courseId', courseId);
|
||||
const query = params.toString() ? `?${params.toString()}` : '';
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum${query}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`커리큘럼을 불러오지 못했습니다. (${response.status})`);
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
|
||||
export async function updateInstructorCurriculum(
|
||||
accessToken: string,
|
||||
input: {
|
||||
courseId?: string | null;
|
||||
groupId?: string | null;
|
||||
activeWeek: number;
|
||||
activeLearningStep?: string | null;
|
||||
applyToStudents?: boolean;
|
||||
completed?: boolean;
|
||||
tagLabel?: string;
|
||||
title?: string;
|
||||
duration?: string;
|
||||
overview?: string;
|
||||
deliverable?: string;
|
||||
requiresSourceSubmission?: boolean;
|
||||
topics?: string[];
|
||||
learningSteps?: Array<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
videoEnabled?: boolean;
|
||||
videoUrl?: string;
|
||||
concepts?: string[];
|
||||
}>;
|
||||
topicDetails?: string[];
|
||||
topicVideoUrls?: string[];
|
||||
practiceContents?: Array<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
}>;
|
||||
disabledModuleIds?: string[];
|
||||
visualizationPlatformKeys?: string[];
|
||||
},
|
||||
): Promise<InstructorCurriculumResponse> {
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch((): null => null);
|
||||
const message =
|
||||
payload && typeof payload === 'object' && 'message' in payload
|
||||
? String(payload.message)
|
||||
: `커리큘럼을 적용하지 못했습니다. (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
|
||||
export async function deleteInstructorCurriculumWeek(
|
||||
accessToken: string,
|
||||
week: number,
|
||||
): Promise<InstructorCurriculumResponse> {
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum/weeks/${week}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch((): null => null);
|
||||
const message =
|
||||
payload && typeof payload === 'object' && 'message' in payload
|
||||
? String(payload.message)
|
||||
: `주차를 삭제하지 못했습니다. (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
|
||||
export async function uploadCurriculumReference(
|
||||
accessToken: string,
|
||||
input: {
|
||||
courseId?: string | null;
|
||||
week: number;
|
||||
title?: string;
|
||||
file: File;
|
||||
},
|
||||
): Promise<InstructorCurriculumResponse> {
|
||||
const formData = new FormData();
|
||||
formData.set('file', input.file);
|
||||
formData.set('courseId', input.courseId ?? '');
|
||||
formData.set('title', input.title?.trim() || input.file.name);
|
||||
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum/weeks/${input.week}/references`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch((): null => null);
|
||||
const message =
|
||||
payload && typeof payload === 'object' && 'message' in payload
|
||||
? String(payload.message)
|
||||
: `참고자료를 업로드하지 못했습니다. (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
|
||||
export async function uploadCurriculumExampleCode(
|
||||
accessToken: string,
|
||||
input: {
|
||||
courseId?: string | null;
|
||||
week: number;
|
||||
title?: string;
|
||||
file: File;
|
||||
},
|
||||
): Promise<InstructorCurriculumResponse> {
|
||||
const formData = new FormData();
|
||||
formData.set('file', input.file);
|
||||
formData.set('courseId', input.courseId ?? '');
|
||||
formData.set('title', input.title?.trim() || input.file.name);
|
||||
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum/weeks/${input.week}/example-codes`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch((): null => null);
|
||||
const message =
|
||||
payload && typeof payload === 'object' && 'message' in payload
|
||||
? String(payload.message)
|
||||
: `예제 코드를 업로드하지 못했습니다. (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
|
||||
export async function deleteCurriculumReference(
|
||||
accessToken: string,
|
||||
referenceId: string,
|
||||
courseId?: string | null,
|
||||
): Promise<InstructorCurriculumResponse> {
|
||||
const query = courseId ? `?courseId=${encodeURIComponent(courseId)}` : '';
|
||||
const response = await fetch(`${LMS_API_BASE_URL}/instructor/curriculum/references/${referenceId}${query}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch((): null => null);
|
||||
const message =
|
||||
payload && typeof payload === 'object' && 'message' in payload
|
||||
? String(payload.message)
|
||||
: `참고자료를 삭제하지 못했습니다. (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return response.json() as Promise<InstructorCurriculumResponse>;
|
||||
}
|
||||
Reference in New Issue
Block a user