integartion of refresh URL
This commit is contained in:
parent
472e71d1a2
commit
af4f713395
|
|
@ -25,6 +25,16 @@ export interface ResolveFileUrlResponse {
|
||||||
success?: boolean
|
success?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RefreshFileUrlResponse {
|
||||||
|
message: string
|
||||||
|
data?: {
|
||||||
|
object_key?: string
|
||||||
|
url?: string
|
||||||
|
expires_in?: number
|
||||||
|
}
|
||||||
|
success?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface UploadMediaOptions {
|
export interface UploadMediaOptions {
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
|
|
@ -86,3 +96,8 @@ export const resolveFileUrl = (key: string) =>
|
||||||
params: { key },
|
params: { key },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const refreshFileUrl = (reference: string) =>
|
||||||
|
http.post<RefreshFileUrlResponse>("/files/refresh-url", {
|
||||||
|
reference,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import {
|
||||||
getTopLevelCourseModules,
|
getTopLevelCourseModules,
|
||||||
updateTopLevelCourseModule,
|
updateTopLevelCourseModule,
|
||||||
} from "../../api/courses.api";
|
} from "../../api/courses.api";
|
||||||
import { resolveFileUrl } from "../../api/files.api";
|
import { refreshFileUrl, resolveFileUrl } from "../../api/files.api";
|
||||||
import type {
|
import type {
|
||||||
ProgramCourseListItem,
|
ProgramCourseListItem,
|
||||||
TopLevelCourseModuleItem,
|
TopLevelCourseModuleItem,
|
||||||
|
|
@ -52,6 +52,17 @@ function isLikelyImageUrl(src: string): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSignedMinioUrl(src: string): boolean {
|
||||||
|
const value = src.trim();
|
||||||
|
if (!value.startsWith("http://") && !value.startsWith("https://")) return false;
|
||||||
|
try {
|
||||||
|
const url = new URL(value);
|
||||||
|
return url.searchParams.has("X-Amz-Signature");
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Default purple gradient with optional cover image; gradient stays if URL missing or image errors. */
|
/** Default purple gradient with optional cover image; gradient stays if URL missing or image errors. */
|
||||||
function ModuleCardTopMedia({ iconSrc }: { iconSrc: string }) {
|
function ModuleCardTopMedia({ iconSrc }: { iconSrc: string }) {
|
||||||
const [coverFailed, setCoverFailed] = useState(false);
|
const [coverFailed, setCoverFailed] = useState(false);
|
||||||
|
|
@ -201,10 +212,17 @@ export function CourseDetailPage() {
|
||||||
const refreshed = await Promise.all(
|
const refreshed = await Promise.all(
|
||||||
list.map(async (module) => {
|
list.map(async (module) => {
|
||||||
const icon = module.icon?.trim() ?? "";
|
const icon = module.icon?.trim() ?? "";
|
||||||
// If backend already returns a full MinIO/S3 URL (including presigned),
|
if (!icon) return module;
|
||||||
// use it directly. Only resolve raw object keys via /files/url.
|
|
||||||
if (!icon || isLikelyImageUrl(icon)) return module;
|
|
||||||
try {
|
try {
|
||||||
|
if (isSignedMinioUrl(icon)) {
|
||||||
|
const refreshedRes = await refreshFileUrl(icon);
|
||||||
|
const refreshedUrl = refreshedRes.data?.data?.url?.trim();
|
||||||
|
if (refreshedUrl) {
|
||||||
|
return { ...module, icon: refreshedUrl };
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
if (isLikelyImageUrl(icon)) return module;
|
||||||
const resolved = await resolveFileUrl(icon);
|
const resolved = await resolveFileUrl(icon);
|
||||||
const freshUrl = resolved.data?.data?.url?.trim();
|
const freshUrl = resolved.data?.data?.url?.trim();
|
||||||
if (!freshUrl) return module;
|
if (!freshUrl) return module;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user