Skip to content

Commit

Permalink
Merge pull request #28 from canopas/implement-uploading-to-s3-functio…
Browse files Browse the repository at this point in the history
…nality

Feat: Implement upload and delete fuctionality to s3 for images and videos
  • Loading branch information
cp-dharti-r authored Jul 8, 2024
2 parents 59c64cc + c10b3fb commit 7e2a0d0
Show file tree
Hide file tree
Showing 25 changed files with 294 additions and 402 deletions.
3 changes: 3 additions & 0 deletions admin/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ NEXT_PUBLIC_CRYPTO_SECRET="A Random Key to Encrypt/Decrypt Password"
NEXT_PUBLIC_AWS_REGION="Your AWS Account Region"
NEXT_PUBLIC_AWS_ACCESS_KEY_ID="Your AWS Account Access Key"
NEXT_PUBLIC_AWS_SECRET_ACCESS_KEY="Your AWS Account Secret Access Key"
NEXT_PUBLIC_AWS_BUCKET_NAME="Your s3 Bucket Name"
NEXT_PUBLIC_ACCESS_KEY_ID="Your s3 Bucket User Access Key"
NEXT_PUBLIC_SECRET_ACCESS_KEY="Your s3 Bucket User Secret Key"
NEXT_PUBLIC_MAIL_SENDER="Your Mail Sender Email Id"
NEXT_PUBLIC_SUPABASE_STORAGE_URL="Your Supabase Storage URL"
NEXT_PUBLIC_SUPABASE_USER="Your Supabase User Email for Auth"
Expand Down
92 changes: 45 additions & 47 deletions admin/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,53 +128,53 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
</Link>
</div>

<div>
<Link
href="/categories"
onClick={() => setSidebarOpen(false)}
className={`group relative flex items-center gap-5 rounded-sm px-4 py-2 font-medium text-bodydark1 duration-300 ease-in-out hover:bg-graydark dark:hover:bg-meta-4 ${
pathname?.includes("categories") &&
"bg-graydark dark:bg-meta-4"
}`}
>
<svg
className="fill-white"
width="25"
height="30"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{role == "super-admin" ? (
<div>
<Link
href="/categories"
onClick={() => setSidebarOpen(false)}
className={`group relative flex items-center gap-5 rounded-sm px-4 py-2 font-medium text-bodydark1 duration-300 ease-in-out hover:bg-graydark dark:hover:bg-meta-4 ${
pathname?.includes("categories") &&
"bg-graydark dark:bg-meta-4"
}`}
>
<g clipPath="url(#clip0_130_9807)">
<path
d="M15.7501 0.55835H2.2501C1.29385 0.55835 0.506348 1.34585 0.506348 2.3021V7.53335C0.506348 8.4896 1.29385 9.2771 2.2501 9.2771H15.7501C16.7063 9.2771 17.4938 8.4896 17.4938 7.53335V2.3021C17.4938 1.34585 16.7063 0.55835 15.7501 0.55835ZM16.2563 7.53335C16.2563 7.8146 16.0313 8.0396 15.7501 8.0396H2.2501C1.96885 8.0396 1.74385 7.8146 1.74385 7.53335V2.3021C1.74385 2.02085 1.96885 1.79585 2.2501 1.79585H15.7501C16.0313 1.79585 16.2563 2.02085 16.2563 2.3021V7.53335Z"
fill=""
/>
<path
d="M6.13135 10.9646H2.2501C1.29385 10.9646 0.506348 11.7521 0.506348 12.7083V15.8021C0.506348 16.7583 1.29385 17.5458 2.2501 17.5458H6.13135C7.0876 17.5458 7.8751 16.7583 7.8751 15.8021V12.7083C7.90322 11.7521 7.11572 10.9646 6.13135 10.9646ZM6.6376 15.8021C6.6376 16.0833 6.4126 16.3083 6.13135 16.3083H2.2501C1.96885 16.3083 1.74385 16.0833 1.74385 15.8021V12.7083C1.74385 12.4271 1.96885 12.2021 2.2501 12.2021H6.13135C6.4126 12.2021 6.6376 12.4271 6.6376 12.7083V15.8021Z"
fill=""
/>
<path
d="M15.75 10.9646H11.8688C10.9125 10.9646 10.125 11.7521 10.125 12.7083V15.8021C10.125 16.7583 10.9125 17.5458 11.8688 17.5458H15.75C16.7063 17.5458 17.4938 16.7583 17.4938 15.8021V12.7083C17.4938 11.7521 16.7063 10.9646 15.75 10.9646ZM16.2562 15.8021C16.2562 16.0833 16.0312 16.3083 15.75 16.3083H11.8688C11.5875 16.3083 11.3625 16.0833 11.3625 15.8021V12.7083C11.3625 12.4271 11.5875 12.2021 11.8688 12.2021H15.75C16.0312 12.2021 16.2562 12.4271 16.2562 12.7083V15.8021Z"
fill=""
/>
</g>
<defs>
<clipPath id="clip0_130_9807">
<rect
width="18"
height="18"
fill="white"
transform="translate(0 0.052124)"
<svg
className="fill-white"
width="25"
height="30"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_130_9807)">
<path
d="M15.7501 0.55835H2.2501C1.29385 0.55835 0.506348 1.34585 0.506348 2.3021V7.53335C0.506348 8.4896 1.29385 9.2771 2.2501 9.2771H15.7501C16.7063 9.2771 17.4938 8.4896 17.4938 7.53335V2.3021C17.4938 1.34585 16.7063 0.55835 15.7501 0.55835ZM16.2563 7.53335C16.2563 7.8146 16.0313 8.0396 15.7501 8.0396H2.2501C1.96885 8.0396 1.74385 7.8146 1.74385 7.53335V2.3021C1.74385 2.02085 1.96885 1.79585 2.2501 1.79585H15.7501C16.0313 1.79585 16.2563 2.02085 16.2563 2.3021V7.53335Z"
fill=""
/>
</clipPath>
</defs>
</svg>
Categories
</Link>
</div>

{role != "super-admin" ? (
<path
d="M6.13135 10.9646H2.2501C1.29385 10.9646 0.506348 11.7521 0.506348 12.7083V15.8021C0.506348 16.7583 1.29385 17.5458 2.2501 17.5458H6.13135C7.0876 17.5458 7.8751 16.7583 7.8751 15.8021V12.7083C7.90322 11.7521 7.11572 10.9646 6.13135 10.9646ZM6.6376 15.8021C6.6376 16.0833 6.4126 16.3083 6.13135 16.3083H2.2501C1.96885 16.3083 1.74385 16.0833 1.74385 15.8021V12.7083C1.74385 12.4271 1.96885 12.2021 2.2501 12.2021H6.13135C6.4126 12.2021 6.6376 12.4271 6.6376 12.7083V15.8021Z"
fill=""
/>
<path
d="M15.75 10.9646H11.8688C10.9125 10.9646 10.125 11.7521 10.125 12.7083V15.8021C10.125 16.7583 10.9125 17.5458 11.8688 17.5458H15.75C16.7063 17.5458 17.4938 16.7583 17.4938 15.8021V12.7083C17.4938 11.7521 16.7063 10.9646 15.75 10.9646ZM16.2562 15.8021C16.2562 16.0833 16.0312 16.3083 15.75 16.3083H11.8688C11.5875 16.3083 11.3625 16.0833 11.3625 15.8021V12.7083C11.3625 12.4271 11.5875 12.2021 11.8688 12.2021H15.75C16.0312 12.2021 16.2562 12.4271 16.2562 12.7083V15.8021Z"
fill=""
/>
</g>
<defs>
<clipPath id="clip0_130_9807">
<rect
width="18"
height="18"
fill="white"
transform="translate(0 0.052124)"
/>
</clipPath>
</defs>
</svg>
Categories
</Link>
</div>
) : (
<div>
<Link
href="/pending-invitations"
Expand All @@ -196,8 +196,6 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
Your Invitations
</Link>
</div>
) : (
""
)}

{role === "admin" ? (
Expand Down
3 changes: 1 addition & 2 deletions admin/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
// reactStrictMode: true,
images: {
unoptimized: true,
domains: ["mbbmnygwewvjsxsjtzbo.supabase.co"],
},
};

Expand Down
2 changes: 2 additions & 0 deletions admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"lint": "next lint"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.606.0",
"@aws-sdk/s3-request-presigner": "^3.609.0",
"@react-email/render": "^0.0.14",
"@supabase/ssr": "^0.3.0",
"@supabase/supabase-js": "^2.43.4",
Expand Down
24 changes: 9 additions & 15 deletions admin/pages/categories/add/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getCookiesValue } from "@/utils/jwt-auth";
import {
changeFileExtensionToWebpExtension,
convertToWebP,
uploadFileTos3,
} from "@/utils/image";

const AddCategoryPage = () => {
Expand Down Expand Up @@ -51,21 +52,14 @@ const AddCategoryPage = () => {
const webpBlob = await convertToWebP(image);

const currentDate = new Date();
const { data: imgData, error: imgErr } = await supabase.storage
.from("categories")
.upload(
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(image.name),
webpBlob
);

if (imgErr) throw imgErr;

image_url =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/categories/" +
imgData.path;

image_url = await uploadFileTos3(
"categories",
webpBlob,
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(image.name)
);
}

const response = mySchema.safeParse({
Expand Down
30 changes: 10 additions & 20 deletions admin/pages/categories/edit/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import SingleImgPreview from "@/components/ImagePreview/SingleImage";
import {
changeFileExtensionToWebpExtension,
convertToWebP,
getFilenameFromURL,
deleteFileFroms3,
uploadFileTos3,
} from "@/utils/image";

const EditCategoryPage = () => {
Expand Down Expand Up @@ -75,27 +76,16 @@ const EditCategoryPage = () => {
const webpBlob = await convertToWebP(imageData);

const currentDate = new Date();
const { data: imgData, error: imgErr } = await supabase.storage
.from("categories")
.upload(
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(imageData.name),
webpBlob
);

if (imgErr) throw imgErr;
image_url = await uploadFileTos3(
"categories",
webpBlob,
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(imageData.name)
);

const { error } = await supabase.storage
.from("categories")
.remove([getFilenameFromURL(image)]);

if (error) throw error;

image_url =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/categories/" +
imgData.path;
await deleteFileFroms3(image);
}

const response = mySchema.safeParse({
Expand Down
8 changes: 2 additions & 6 deletions admin/pages/categories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Link from "next/link";
import Image from "next/image";
import supabase from "@/utils/supabase";
import PaginationPage from "@/components/pagination/PaginatedPage";
import { getFilenameFromURL } from "@/utils/image";
import { deleteFileFroms3 } from "@/utils/image";
import { getCookiesValue } from "@/utils/jwt-auth";

const CategoriesPage = () => {
Expand Down Expand Up @@ -75,11 +75,7 @@ const CategoriesPage = () => {

const deleteRecord = async (id: number, key: number) => {
try {
const { data, error } = await supabase.storage
.from("categories")
.remove([getFilenameFromURL(categoriesData[key].image)]);

if (error) throw error;
await deleteFileFroms3(categoriesData[key].image);

await supabase.from("categories").delete().eq("id", id).throwOnError();
setCategoriesData((prevCategories) =>
Expand Down
65 changes: 25 additions & 40 deletions admin/pages/dishes/add/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getCookiesValue } from "@/utils/jwt-auth";
import {
changeFileExtensionToWebpExtension,
convertToWebP,
uploadFileTos3,
} from "@/utils/image";

const AddDishPage = () => {
Expand Down Expand Up @@ -93,56 +94,40 @@ const AddDishPage = () => {
: z.null(),
});

const currentDate = new Date();

if (isImagesChecked && imagesData) {
for (var i = 0; i < imagesData.length; i++) {
const webpBlob = await convertToWebP(imagesData[i]);

const { data: imgData, error: imgErr } = await supabase.storage
.from("dishes")
.upload(
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(imagesData[i].name),
webpBlob
);
const currentDate = new Date();

if (imgErr) throw imgErr;
const webpBlob = await convertToWebP(imagesData[i]);

const image_url =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/dishes/" +
imgData.path;
const image_url = await uploadFileTos3(
"dishes",
webpBlob,
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(imagesData[i].name)
);

images.push(image_url);
}
} else if (videoData) {
const currentDate = new Date();
const { data: imgData, error: imgErr } = await supabase.storage
.from("dishes")
.upload(
currentDate.getTime() + "-" + thumbnailData.name,
thumbnailData
);

if (imgErr) throw imgErr;

thumbnail =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/dishes/" +
imgData.path;

const { data: videoStore, error: videoErr } = await supabase.storage
.from("dishes")
.upload(currentDate.getTime() + "-" + videoData.name, videoData);

if (videoErr) throw videoErr;

video =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/dishes/" +
videoStore.path;
const webpBlob = await convertToWebP(thumbnailData);

thumbnail = await uploadFileTos3(
"dishes",
webpBlob,
currentDate.getTime() +
"-" +
changeFileExtensionToWebpExtension(thumbnailData.name)
);

video = await uploadFileTos3(
"dishes",
videoData,
currentDate.getTime() + "-" + videoData.name
);
}

const response = mySchema.safeParse({
Expand Down
Loading

0 comments on commit 7e2a0d0

Please sign in to comment.