From d5a267fead373c66e3aab0c2f36c927afb87c13d Mon Sep 17 00:00:00 2001
From: log101
Date: Tue, 23 Jan 2024 21:39:07 +0300
Subject: [PATCH] feat: add file upload feat: add db connection
---
package-lock.json | 184 ++++++++++++++++++++++++++++++++
package.json | 2 +
src/pages/create-url.ts | 65 ++++++++++-
src/pages/create.astro | 6 +-
src/scripts/initMap.js | 2 +
src/scripts/initSelectionMap.js | 13 ++-
6 files changed, 262 insertions(+), 10 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 62b9e62..bc059aa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,9 +19,11 @@
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@vercel/blob": "^0.19.0",
+ "@vercel/postgres-kysely": "^0.7.1",
"astro": "^4.1.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
+ "kysely": "^0.27.2",
"lucide-react": "^0.309.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -1083,6 +1085,14 @@
"node-pre-gyp": "bin/node-pre-gyp"
}
},
+ "node_modules/@neondatabase/serverless": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.7.2.tgz",
+ "integrity": "sha512-wU3WA2uTyNO7wjPs3Mg0G01jztAxUxzd9/mskMmtPwPTjf7JKWi9AW5/puOGXLxmZ9PVgRFeBVRVYq5nBPhsCg==",
+ "dependencies": {
+ "@types/pg": "8.6.6"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1499,6 +1509,24 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
},
+ "node_modules/@types/node": {
+ "version": "20.11.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz",
+ "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/pg": {
+ "version": "8.6.6",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.6.tgz",
+ "integrity": "sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
"node_modules/@types/prop-types": {
"version": "15.7.11",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
@@ -1626,6 +1654,34 @@
"node": "*"
}
},
+ "node_modules/@vercel/postgres": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@vercel/postgres/-/postgres-0.7.1.tgz",
+ "integrity": "sha512-QTOQrzxkB+H37HrQ8n7uxuXQb9Q4/L8sibMuO98dNvkIv79iDmiy/jJ1rAcwn+D/6In3LnXAoH6S+XL6rpi8tQ==",
+ "dependencies": {
+ "@neondatabase/serverless": "0.7.2",
+ "bufferutil": "4.0.8",
+ "utf-8-validate": "6.0.3",
+ "ws": "8.14.2"
+ },
+ "engines": {
+ "node": ">=14.6"
+ }
+ },
+ "node_modules/@vercel/postgres-kysely": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@vercel/postgres-kysely/-/postgres-kysely-0.7.1.tgz",
+ "integrity": "sha512-HjWRWwreJTLfOP8Kio/naflXCqXY9mL7adn/Tv62XCjBwE6DNutU8LoDH072vt2A2Xqv0nmT794ORTidFLnvCg==",
+ "dependencies": {
+ "@vercel/postgres": "0.7.1"
+ },
+ "engines": {
+ "node": ">=14.6"
+ },
+ "peerDependencies": {
+ "kysely": "^0.24.2 || ^0.25.0 || ^0.26.0"
+ }
+ },
"node_modules/@vitejs/plugin-react": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz",
@@ -2222,6 +2278,18 @@
"ieee754": "^1.2.1"
}
},
+ "node_modules/bufferutil": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
+ "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-gyp-build": "^4.3.0"
+ },
+ "engines": {
+ "node": ">=6.14.2"
+ }
+ },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -3845,6 +3913,14 @@
"node": ">=6"
}
},
+ "node_modules/kysely": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.27.2.tgz",
+ "integrity": "sha512-DmRvEfiR/NLpgsTbSxma2ldekhsdcd65+MNiKXyd/qj7w7X5e3cLkXxcj+MypsRDjPhHQ/CD5u3Eq1sBYzX0bw==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/lilconfig": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
@@ -5364,6 +5440,34 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
},
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
+ "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -5585,6 +5689,41 @@
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@@ -7319,6 +7458,11 @@
"node": ">=14.0"
}
},
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
"node_modules/unherit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",
@@ -7473,6 +7617,18 @@
"browserslist": ">= 4.21.0"
}
},
+ "node_modules/utf-8-validate": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.3.tgz",
+ "integrity": "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-gyp-build": "^4.3.0"
+ },
+ "engines": {
+ "node": ">=6.14.2"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -8037,6 +8193,34 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
+ "node_modules/ws": {
+ "version": "8.14.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
+ "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/package.json b/package.json
index 9ee6b6d..6c59d86 100644
--- a/package.json
+++ b/package.json
@@ -21,9 +21,11 @@
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@vercel/blob": "^0.19.0",
+ "@vercel/postgres-kysely": "^0.7.1",
"astro": "^4.1.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
+ "kysely": "^0.27.2",
"lucide-react": "^0.309.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/src/pages/create-url.ts b/src/pages/create-url.ts
index b3ebe58..140a252 100644
--- a/src/pages/create-url.ts
+++ b/src/pages/create-url.ts
@@ -1,15 +1,70 @@
export const prerender = false
+import { put } from "@vercel/blob"
+import type { Generated } from "kysely"
import type { APIRoute } from "astro"
+import { createKysely } from "@vercel/postgres-kysely"
+
+interface ContentTable {
+ id: Generated
+ blob_url: string
+ loc: string
+ description: string
+}
+
+interface Database {
+ contents: ContentTable
+}
export const POST: APIRoute = async ({ request }) => {
const data = await request.formData()
- console.log(data)
+ const image = data.get("selected-photo") as File
+ const description = data.get("description")
+ const geolocation = data.get("geolocation")
- return new Response(
- JSON.stringify({
- message: "This was a POST!"
+ console.log(image, description, geolocation)
+
+ if (!image || !geolocation) {
+ return new Response(null, {
+ status: 400,
+ statusText: "Image and geolocation are required fields"
})
- )
+ }
+
+ const pos = geolocation.toString().split(",")
+
+ if (pos.length !== 2) {
+ return new Response(null, {
+ status: 400,
+ statusText: "Geolocation not correctly formatted"
+ })
+ }
+
+ const blob = await put(image.name, image, { access: "public", token: import.meta.env.BLOB_READ_WRITE_TOKEN })
+
+ const db = createKysely({ connectionString: import.meta.env.POSTGRES_URL })
+
+ const res = await db
+ .insertInto("contents")
+ .values({
+ blob_url: blob.url,
+ description: description?.toString() ?? "",
+ loc: `SRID=4326;POINT(${pos[0]} ${pos[1]})`
+ })
+ .returning("blob_url")
+ .executeTakeFirst()
+
+ if (res?.blob_url) {
+ return new Response(
+ JSON.stringify({
+ message: "Succesfully added content"
+ })
+ )
+ } else {
+ return new Response(null, {
+ status: 500,
+ statusText: "Error while saving data"
+ })
+ }
}
diff --git a/src/pages/create.astro b/src/pages/create.astro
index 3c9161b..e92bf60 100644
--- a/src/pages/create.astro
+++ b/src/pages/create.astro
@@ -72,6 +72,7 @@ import { Textarea } from '@/components/ui/textarea';
>
+
@@ -81,7 +82,10 @@ import { Textarea } from '@/components/ui/textarea';
3. Fotoğraf Açıklaması
-
+
Bir açıklama girin, yüklediğiniz içeriğin üzerine bu metin
görünecek.
diff --git a/src/scripts/initMap.js b/src/scripts/initMap.js
index 24824c1..0f2aa29 100644
--- a/src/scripts/initMap.js
+++ b/src/scripts/initMap.js
@@ -43,6 +43,8 @@ L.Control.GoToCurrentLocation = L.Control.extend({
locationButton.classList.add('custom-map-control-button');
+ locationButton.name = 'select-location-button'
+
locationButton.addEventListener('click', () => {
map.setView(currentLocationMarker.getLatLng(), 18);
});
diff --git a/src/scripts/initSelectionMap.js b/src/scripts/initSelectionMap.js
index 9c74a8e..ed414fb 100644
--- a/src/scripts/initSelectionMap.js
+++ b/src/scripts/initSelectionMap.js
@@ -36,10 +36,14 @@ L.Control.GoToCurrentLocation = L.Control.extend({
locationButton.classList.add('custom-map-control-button');
- locationButton.addEventListener('click', (e) => {
- map.setView(currentLocationMarker.getLatLng(), 18);
- e.stopPropagation()
- });
+ locationButton.type = 'button'
+
+ locationButton.addEventListener('click', (ev) => {
+ if (currentLocationMarker) {
+ map.setView(currentLocationMarker.getLatLng(), 12);
+ }
+ L.DomEvent.stopPropagation(ev)
+ })
return locationButton;
},
@@ -115,5 +119,6 @@ map.on('click', (e) => {
const pos = targetLocationMarker.getLatLng()
document.getElementById('coordinates').innerText = `${pos.lat}. Enlem, ${pos.lng}. Boylam`
+ document.getElementById('geolocation-input').value = `${pos.lat},${pos.lng}`
document.getElementById('location-selected-confirmation').innerText = "Konum seçildi, bir sonraki adıma geçebilirsiniz."
})