Sending the presigned url for activity media and venue artifacts
This commit is contained in:
@@ -186,23 +186,17 @@ export const handler = safeHandler(
|
||||
const uploadedActivityMedia: Array<{ mediaType?: string; mediaFileName: string }> = [];
|
||||
|
||||
for (const file of files.filter(
|
||||
(f) => f.fieldName === 'activityImages' || f.fieldName === 'activityVideos',
|
||||
(f) => f.fieldName === 'images' || f.fieldName === 'videos'
|
||||
)) {
|
||||
const s3Key = `ActivityOnboarding/Activity_${activityPayload.activityXid}/Media/${Date.now()}_${file.fileName}`;
|
||||
|
||||
if (s3Key.length > 900) {
|
||||
throw new ApiError(400, 'Generated S3 key too long');
|
||||
}
|
||||
|
||||
await s3
|
||||
.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: s3Key,
|
||||
Body: file.buffer,
|
||||
ContentType: file.mimeType,
|
||||
ACL: 'private',
|
||||
})
|
||||
.promise();
|
||||
await s3.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: s3Key,
|
||||
Body: file.buffer,
|
||||
ContentType: file.mimeType,
|
||||
ACL: 'private',
|
||||
}).promise();
|
||||
|
||||
uploadedActivityMedia.push({
|
||||
mediaType: file.mimeType,
|
||||
@@ -210,6 +204,7 @@ export const handler = safeHandler(
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* 🔥 MERGE ACTIVITY MEDIA */
|
||||
const existingMedia = Array.isArray(activityPayload.media)
|
||||
? activityPayload.media
|
||||
@@ -218,44 +213,40 @@ export const handler = safeHandler(
|
||||
|
||||
/* 9️⃣ PROCESS VENUE MEDIA UPLOADS */
|
||||
// Group venue files by index: venueImages[0], venueImages[1], etc.
|
||||
const venueFilesMap: Map<number, Array<{ buffer: Buffer; mimeType: string; fileName: string }>> = new Map();
|
||||
const venueFilesMap = new Map<number, typeof files>();
|
||||
|
||||
for (const file of files) {
|
||||
// Match patterns like: venueImages[0], venueVideos[1], etc.
|
||||
const match = file.fieldName.match(/^venue(Images|Videos)\[(\d+)\]$/);
|
||||
if (match) {
|
||||
const venueIndex = parseInt(match[2], 10);
|
||||
if (!venueFilesMap.has(venueIndex)) {
|
||||
venueFilesMap.set(venueIndex, []);
|
||||
}
|
||||
venueFilesMap.get(venueIndex)!.push(file);
|
||||
const match = file.fieldName.match(/^venueFiles(\d+)$/);
|
||||
if (!match) continue;
|
||||
|
||||
const venueIndex = Number(match[1]);
|
||||
|
||||
if (!venueFilesMap.has(venueIndex)) {
|
||||
venueFilesMap.set(venueIndex, []);
|
||||
}
|
||||
|
||||
venueFilesMap.get(venueIndex)!.push(file);
|
||||
}
|
||||
|
||||
|
||||
// Upload venue files and attach to corresponding venues
|
||||
if (Array.isArray(activityPayload.venues)) {
|
||||
for (let i = 0; i < activityPayload.venues.length; i++) {
|
||||
const venue = activityPayload.venues[i];
|
||||
const venueFiles = venueFilesMap.get(i) || [];
|
||||
|
||||
const uploadedVenueMedia: Array<{ mediaType?: string; mediaFileName: string }> = [];
|
||||
const uploadedVenueMedia = [];
|
||||
|
||||
for (const file of venueFiles) {
|
||||
const s3Key = `ActivityOnboarding/Activity_${activityPayload.activityXid}/Venue_${i}/Media/${Date.now()}_${file.fileName}`;
|
||||
|
||||
if (s3Key.length > 900) {
|
||||
throw new ApiError(400, 'Generated S3 key too long for venue media');
|
||||
}
|
||||
|
||||
await s3
|
||||
.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: s3Key,
|
||||
Body: file.buffer,
|
||||
ContentType: file.mimeType,
|
||||
ACL: 'private',
|
||||
})
|
||||
.promise();
|
||||
await s3.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: s3Key,
|
||||
Body: file.buffer,
|
||||
ContentType: file.mimeType,
|
||||
ACL: 'private',
|
||||
}).promise();
|
||||
|
||||
uploadedVenueMedia.push({
|
||||
mediaType: file.mimeType,
|
||||
@@ -263,12 +254,11 @@ export const handler = safeHandler(
|
||||
});
|
||||
}
|
||||
|
||||
// Merge with existing venue media
|
||||
const existingVenueMedia = Array.isArray(venue.media) ? venue.media : [];
|
||||
venue.media = [...existingVenueMedia, ...uploadedVenueMedia];
|
||||
venue.media = [...(venue.media || []), ...uploadedVenueMedia];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 🔟 VALIDATION */
|
||||
let parsedDto: CreateActivityInput;
|
||||
|
||||
|
||||
@@ -1704,7 +1704,7 @@ export class HostService {
|
||||
}
|
||||
|
||||
async getAllDetailsOfActivityAndVenue(activityXid: number) {
|
||||
return await this.prisma.activities.findMany({
|
||||
const activity = await this.prisma.activities.findFirst({
|
||||
where: { id: activityXid, isActive: true },
|
||||
select: {
|
||||
id: true,
|
||||
@@ -1728,6 +1728,38 @@ export class HostService {
|
||||
activityTypeName: true,
|
||||
}
|
||||
},
|
||||
ActivitiesMedia: {
|
||||
where: {
|
||||
isActive: true
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
mediaType: true,
|
||||
mediaFileName: true,
|
||||
}
|
||||
},
|
||||
ActivityVenues: {
|
||||
where: {
|
||||
isActive: true
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
venueName: true,
|
||||
venueCapacity: true,
|
||||
availableSeats: true,
|
||||
isMinPeopleReqMandatory: true,
|
||||
minPeopleRequired: true,
|
||||
minReqfullfilledBeforeMins: true,
|
||||
venueDescription: true,
|
||||
ActivityVenueArtifacts: {
|
||||
select: {
|
||||
id: true,
|
||||
mediaType: true,
|
||||
mediaFileName: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ActivityPickUpDetails: {
|
||||
where: {
|
||||
isActive: true,
|
||||
@@ -1936,6 +1968,46 @@ export class HostService {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
if (!activity) {
|
||||
throw new ApiError(404, 'Activity not found');
|
||||
}
|
||||
|
||||
if (Array.isArray(activity.ActivitiesMedia)) {
|
||||
for (const media of activity.ActivitiesMedia) {
|
||||
if (!media?.mediaFileName) continue;
|
||||
|
||||
const filePath = media.mediaFileName;
|
||||
|
||||
// ✅ Robust S3 key extraction
|
||||
const key = filePath.startsWith('http')
|
||||
? new URL(filePath).pathname.replace(/^\/+/, '')
|
||||
: filePath;
|
||||
|
||||
(media as any).presignedUrl = await getPresignedUrl(bucket, key);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(activity.ActivityVenues)) {
|
||||
for (const venue of activity.ActivityVenues) {
|
||||
if (!Array.isArray(venue.ActivityVenueArtifacts)) continue;
|
||||
|
||||
for (const artifact of venue.ActivityVenueArtifacts) {
|
||||
if (!artifact?.mediaFileName) continue;
|
||||
|
||||
const filePath = artifact.mediaFileName;
|
||||
|
||||
// ✅ Robust S3 key extraction
|
||||
const key = filePath.startsWith('http')
|
||||
? new URL(filePath).pathname.replace(/^\/+/, '')
|
||||
: filePath;
|
||||
|
||||
(artifact as any).preSignedURL = await getPresignedUrl(bucket, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
async createActivity(
|
||||
|
||||
Reference in New Issue
Block a user