-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Image uploading #220
base: main
Are you sure you want to change the base?
Image uploading #220
Changes from all commits
b7ccb24
7764089
18fc101
54c9f55
7223add
f78bc18
8709332
1f182f4
0b6b9e8
e179b4a
7c851f8
b2afa35
be0b1d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterTable | ||
ALTER TABLE "users" ADD COLUMN "image_url" VARCHAR(400); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// import express, { Response } from 'express'; | ||
// import catchError from '../utils/catchError'; | ||
// import middleware from '../utils/middleware'; | ||
|
||
// const imageRouter = express.Router(); | ||
|
||
// imageRouter.post( | ||
// '/upload', | ||
// middleware.isUserLoggedIn, | ||
// catchError(async (request: RequestWithAuthentication, response: Response) => { | ||
// const userIsLoggedIn = typeof request.loggedUserId === 'number'; | ||
|
||
|
||
|
||
// return response.status(200)); | ||
// }), | ||
// ); | ||
|
||
// export default imageRouter; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { ErrorObj } from "../types"; | ||
|
||
// Require the cloudinary library | ||
const cloudinary = require('cloudinary').v2; | ||
|
||
export const URL = | ||
`https://res.cloudinary.com/${process.env.CLOUD_NAME}/image/upload/v1710605561/`; | ||
|
||
// Return "https" URLs by setting secure: true | ||
cloudinary.config({ | ||
secure: true, | ||
}); | ||
|
||
// Log the configuration | ||
console.log(cloudinary.config()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this necessary? Or was it just for development purposes? |
||
|
||
// Uploads an image file // | ||
const uploadImage = async (imagePath: File | string, publicId: string): Promise<string | ErrorObj> => { | ||
// Allow overwriting the asset with new versions | ||
const options = { | ||
public_id: publicId, | ||
overwrite: true, | ||
}; | ||
|
||
try { | ||
const result = await cloudinary.uploader.upload(imagePath, options); | ||
console.log(result); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is necessary anymore |
||
return result.public_id; | ||
} catch (error) { | ||
console.error(error); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
|
||
return { error: 'Sorry, we couldn\'t upload your image.'} | ||
} | ||
}; | ||
|
||
// Gets details of an uploaded image // | ||
// const getAssetInfo = async (publicId: number) => { | ||
// // Return colors in the response | ||
// const options = { | ||
// colors: true, | ||
// }; | ||
|
||
// try { | ||
// // Get details about the asset | ||
// const result = await cloudinary.api.resource(publicId, options); | ||
// console.log(result); | ||
// return result.colors; | ||
// } catch (error) { | ||
// console.error(error); | ||
// } | ||
// }; | ||
|
||
// Creates an HTML image tag with a transformation that | ||
// results in a circular thumbnail crop of the image | ||
// focused on the faces, applying an outline of the | ||
// first color, and setting a background of the second color. | ||
// const createImageTag = (publicId: number, ...colors: string[]) => { | ||
// // Set the effect color and background color | ||
// const [effectColor, backgroundColor] = colors; | ||
|
||
// // Create an image tag with transformations applied to the src URL | ||
// const imageTag = cloudinary.image(publicId, { | ||
// transformation: [ | ||
// { width: 250, height: 250, gravity: 'faces', crop: 'thumb' }, | ||
// { radius: 'max' }, | ||
// { effect: 'outline:10', color: effectColor }, | ||
// { background: backgroundColor }, | ||
// ], | ||
// }); | ||
|
||
// return imageTag; | ||
// }; | ||
|
||
export { uploadImage }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,20 +84,24 @@ export async function getTopics(numOfTopics: number): Promise<Topic[]> { | |
|
||
/** | ||
* Creates a new subscriber to receive notifications | ||
* @param id | ||
* @param id to use as subscriberId | ||
* @param username | ||
* @param firstName | ||
* @param lastName | ||
* @param imageURL (optional) to use as the user's avatar | ||
*/ | ||
export async function createSubscriber( | ||
id: string, | ||
username: string, | ||
firstName: string, | ||
lastName: string, | ||
imageURL?: string, | ||
) { | ||
try { | ||
await novu.subscribers.identify(id, { | ||
firstName, | ||
lastName, | ||
avatar: imageURL, | ||
data: { | ||
username, | ||
}, | ||
|
@@ -122,6 +126,63 @@ export async function getSubscriber(subscriberId: string) { | |
} | ||
} | ||
|
||
/** | ||
* Updates a subscriber's info | ||
* @param subscriberId | ||
*/ | ||
export async function updateSubcriber({ | ||
subscriberId, | ||
firstName, | ||
lastName, | ||
email, | ||
avatar, | ||
}: { | ||
subscriberId: string; | ||
firstName?: string; | ||
lastName?: string; | ||
email?: string; | ||
avatar?: string; | ||
}) { | ||
try { | ||
// If none of the values were updated ('' or undefined), return immediately | ||
if ([firstName, lastName, email, avatar].every((val) => !val)) return; | ||
|
||
// interface UpdateSubData { | ||
// firstName?: string; | ||
// lastName?: string; | ||
// email?: string; | ||
// imageUrl?: string; | ||
// } | ||
|
||
const subscriberInfo = { firstName, lastName, email, avatar }; | ||
console.log({ subscriberInfo }); | ||
|
||
const options = { | ||
method: 'PUT', | ||
headers: { Authorization: `ApiKey ${NOVU_API_KEY}` }, | ||
body: subscriberInfo as unknown as BodyInit, | ||
}; | ||
|
||
const res = await fetch(`https://api.novu.co/v1/subscribers/${subscriberId}`, options) | ||
.then((response) => response.json()) | ||
.then((response) => response.data) | ||
.catch((err) => { | ||
console.error(err); | ||
return { error: `Could not update subscriber ${subscriberId}.` }; | ||
}); | ||
|
||
// const res = await novu.subscribers.update(subscriberId, { | ||
// firstName, | ||
// lastName, | ||
// email, | ||
// avatar: imageUrl, | ||
// }); | ||
console.log('novu res', res); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You will have to explain to me one day how the entire notification system works. I don't understand exactly what updateSubscriber does. |
||
/** | ||
* Retrieves all subscribers. | ||
* @returns all subcribers or a custom error object if an error occurs | ||
|
@@ -202,6 +263,11 @@ export const triggers = { | |
username, | ||
}: JoinNeighborhoodArgs) { | ||
try { | ||
/* | ||
* Checks if there is an identical notification in the recent history. | ||
* Note that this implementation only checks the first page of results | ||
* and not ALL the admin's notifications. | ||
*/ | ||
const notifications = await getSubscriberNotifications(adminId); | ||
|
||
const identicalNotification = notifications.some( | ||
|
@@ -218,6 +284,9 @@ export const triggers = { | |
to: { | ||
subscriberId: adminId, | ||
}, | ||
actor: { | ||
subscriberId: userId, | ||
}, | ||
payload: { | ||
neighborhoodId, | ||
neighborhoodName, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to find the docs to this express-form-data package but I'm having no luck. I presume this middleware intercepts requests that contain multipart forms and parses them?