I created a route here where in I am planning to post or update on this route via updateResortOwner:
router.route('/:userid').get(getOwnerResorts, resortOwner).post(protect, resortOwner, createOwnerResort)
router.route('/:userid/:id').get(getResortOwnerById).put(protect, resortOwner, updateResortOwner).delete(protect, resortOwner, deleteResortOwner)
On my controller I have this:
// #description Update a resort
// #route PUT /api/resorts/:userid
// #access Private/Admin
const updateResortOwner = expressAsyncHandler(async (req, res) => {
const {
name,
price_per_night,
description,
address,
city,
province,
zip_code,
latitude,
longitude,
phone,
website,
amenities,
image
} = req.body
const resort = await Resort.findById(req.params.id)
if(resort){
resort.name = name,
resort.price_per_night = price_per_night
resort.description = description
resort.address = address
resort.city = city
resort.province = province
resort.zip_code = zip_code
resort.latitude = latitude
resort.longitude = longitude
resort.phone = phone
resort.website = website
resort.amenities = amenities
resort.image = image
const updatedResort = await resort.save()
res.json(updatedResort)
} else{
res.status(404)
throw new Error('Resort not found!')
}
})
In order to make this work on my redux action:
export const updateResortOwner = (resort) => async (dispatch, getState) => {
try {
dispatch({ type: RESORT_OWNER_UPDATE_REQUEST })
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.post(`/api/resorts/${userInfo._id}/${resort._id}`, resort, config)
dispatch({
type: RESORT_OWNER_UPDATE_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: RESORT_OWNER_UPDATE_FAIL,
payload: error.response && error.response.data.message ?
error.response.data.message : error.message
})
}
}
And then on my submithandler on the frontend:
const submitHandler = (e) => {
e.preventDefault()
dispatch(updateResortOwner({
_id: resortId,
name,
price_per_night: pricePerNight,
description,
address,
city,
province,
zip_code: zipCode,
phone,
email,
website,
image,
amenities: {
tv,
reservation,
moderate_noise: moderateNoise,
free_wifi: freeWifi,
trendy,
credit_card: creditCard,
bar,
animals,
kids
}
}))
}
When I submit this its returning this error:
Not found - /api/resorts/5fe92b7a1ecf1a16e8ced784/5fe1798bebef0c2db08d4c76
Any idea what's happening here? How can I fix this?
Related
When I console.log phoneNumber in onSuccess, it shows an empty string instead of the correct value. phoneNumber is stale. When I type something in my editor which makes the app rerender, phoneNumber has the correct value. It seems the function in onSuccess sort of gets captured by the closure for some reason? I'm not sure why.
const verifyPhoneNumber = async (url: string, { arg: phoneNumber }) => {
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: phoneNumber,
}),
});
const json = await response.json();
return json;
} catch (e) {
console.log(e);
}
};
const SignUp = (props: Props) => {
const navigation = useNavigation();
const [phoneNumber, setPhoneNumber] = useState("");
const url = "https://jsonplaceholder.typicode.com/posts/";
// const url = "http://192.168.0.142:8000/user/auth/otp-code/";
const { trigger, isMutating } = useSWRMutation(url, verifyPhoneNumber, {
onSuccess: () => {
// The problem is here, phoneNumber is an empty string
console.log(phoneNumber)
navigation.navigate("VerifyCode", {
phoneNumber: phoneNumber,
});
},
onError: (error) => console.log(error),
});
const sendOTP = () => {
trigger(phoneNumber);
};
// phoneNumber shows the proper string
console.log(phoneNumber);
return (
<AppBox>
<InputFieldForAuth
inputIsInvalid={false}
value={phoneNumber}
onChangeText={(newText: string) => setPhoneNumber(newText)}
placeholder={`Enter your phone number here`}
/>
</HyperlinkText>
<Button
text="Continue"
onPress={sendOTP}
/>
</AppBox>
);
};
I even tried something like this to make the function get recreated with a new phoneNumber each render, and phoneNumber is still stale
const onSuccess = useCallback(() => {
console.log(phoneNumber);
navigation.navigate("VerifyCode", {
phoneNumber: phoneNumber,
});
}, [phoneNumber]);
const { trigger, isMutating } = useSWRMutation(url, verifyPhoneNumber, {
onSuccess: onSuccess,
onError: (error) => console.log(error),
});
A snack is attached at the bottom demonstrating the issue.
https://snack.expo.dev/#meg_hidey/uplifting-churros
I am getting my base64 urls and they are correct because if I send only one image its uploaded correctly to cloudinary but when sending multiple images Ii get an error 'ENAMETOOLONG' with error number 4064
here is my graphql resolver
createEvent: async (args: any, req: any) => {
if (!req.isAuth) {
throw new Error("Unauthenticated!!!!");
}
let imagesArr: any[] = [];
for (let i = 0; i < args.eventInput.images.length; i++) {
const result = await cloudinary.uploader.upload(
args.eventInput.images[i],
{
public_id: `${args.eventInput.title}${new Date(
args.eventInput.date
)}${i}`,
folder: "Eventers",
allowedFormats: ["jpeg", "png", "jpg"],
}
);
console.log(result.url, result.public_id);
imagesArr.push({ public_id: result.public_id, url: result.secure_url });
}
const event = new Event({
title: args.eventInput.title,
description: args.eventInput.description,
price: +args.eventInput.price,
date: new Date(args.eventInput.date),
category: args.eventInput.category,
brief: args.eventInput.brief,
tickets: +args.eventInput.tickets,
images: [...imagesArr],
author: req.userId,
});
let createdEvent;
try {
const result = await event.save();
createdEvent = transformEvent(result);
const author = await User.findById(req.userId);
if (!author) {
throw new Error("User not found.");
}
author.createdEvents.push(event);
await author.save();
return createdEvent;
} catch (error) {
console.log(error);
throw error;
}
},
here is the response i get when trying to submit multiple base64 urls
message: "Unexpected error value: { error: { errno: -4064, code: \"ENAMETOOLONG\", syscall: \"open\", path: \"C:\\\\Users\\\\user\\\\Desktop\\\\graphQl maximillian yt course\\\\bookingEvents\\\\backend\\\\data:image\\\\jpeg;base64,\\\\9j\\\\4AAQSkZJRgABAQAAAQABAAD\\\\2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj\\\\2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj\\\\wAARCAQIAkUDASIAAhEBAxEB\\\\8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL\\\\8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6\\\\8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL\\\\8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uP…"
and here is how i transform the images to base
const fileOnChangeHandler = async (e: ChangeEvent<HTMLInputElement>) => {
let files = Array.from(e.target.files!);
files.forEach((file: any) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = async () => {
setImageLinks((prevArr: any) => [...prevArr, reader.result]);
};
});
};
and here is how i send the data to the back end
export const fetchAsyncCreateEvents = createAsyncThunk(
"Events/fetchAsyncCreateEvents",
async (eventInput: Event) => {
const {
title,
category,
description,
brief,
price,
date,
tickets,
images,
} = eventInput;
const { data } = await axios.post<Event>(
API,
{
query: `
mutation{
createEvent(eventInput:{title:"${title}",category:"${category}",description:"""${description}""",brief:"${brief}",price:${price},date:"${date}",tickets:${tickets},images:"${images}"}){
author{
email
}
}
}
`,
},
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("token"),
},
}
);
return data;
}
);
I've tried alot of things like adding .replace(/(\r\n|\n|\r)/gm,"") to the for loop at each image array index but it didnt work
and here is one of the base 64 urls
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAQIAkUDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4"
I deleted more than half of the url so I could submit the question.
i solved the problem it was so simple the problem is i am sending the array of images base64 in a wrong way in graphql mutation
i was sending it with a quotation wrapping it and it turned out you have to use quotations only for strings and for arrays you should json.stringify
export const fetchAsyncCreateEvents = createAsyncThunk(
"Events/fetchAsyncCreateEvents",
async (eventInput: Event) => {
const {
title,
category,
description,
brief,
price,
date,
tickets,
images,
} = eventInput;
const { data } = await axios.post<Event>(
API,
{
query: `
mutation{
createEvent(eventInput:{title:"${title}",category:"${category}",description:"""${description}""",brief:"${brief}",price:${price},date:"${date}",tickets:${tickets},images:${JSON.stringify(images)}}){
author{
email
}
}
}
`,
},
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("token"),
},
}
);
return data;
}
);
I have a many to many relation prisma model. I wan to be able to delete a single item in my table but for whatever reason I am able to delete all the data but I cant delete a single item
Current working delete handle:
const student = await prisma.courseEnrollment.deleteMany({
where: {
id,
studentId: id,
}
})
const studentToDelete = await prisma.student.deleteMany({
where: {
id,
studentId: id,
}
})
But this is not what I want
I tried:
const student = await prisma.courseEnrollment.delete({
where: {
id,
studentId: id,
}
})
const studentToDelete = await prisma.student.delete({
where: {
id,
studentId: id,
}
})
Able to manually delete with this:
const student = await prisma.courseEnrollment.deleteMany({
where: {
studentId: 58
}
})
const studentToDelete = await prisma.student.delete({
where: {
id: 58
}
})
But I am getting Invalid prisma.student.delete() error when handling it on the client side.
handle delete function:
const handleDelete = async (id) => {
const response = await fetch('/api/student/delete/', {
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
console.log(data);
router.push("/");
};
<button onClick={() => handleDelete(student.id)}>Delete</button>
I'm I missing something?
I'm trying to create sign up form in react-native using Firebase.I've used Fetch Blob and Document Picker libraries for getting image and upload it to firebase. And I'm also trying to save the user's name, email, and password in realtime database. But unfortunately, the user data is not going to save in database except the image is uploaded in the firebase storage.
Here is my Firebase Auth Code
handleSignupOnPress = () => {
const {image, email, password} = this.state;
let validation = this.validateData();
console.warn(validation);
if (validation == true) {
this.toggleLoading();
firebaseService
.auth()
.createUserWithEmailAndPassword(email, password)
.then(() => {
// console.warn("User SignUp Successfully");
this.uploadImage(image);
})
.catch(error => {
this.toggleLoading();
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage);
// console.warn("ERROR => ", errorCode, errorMessage);
});
}
};
Here is image Upload Code
// First Uploading image and download Image URI then call saveUserToDB()...
uploadImage(uri, mime = 'image/jpeg') {
return new Promise((resolve, reject) => {
const uploadUri =
Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = '';
const imageRef = firebaseService
.storage()
.ref('images')
.child(uuid.v4());
fs.readFile(uploadUri, 'base64')
.then(data => {
return Blob.build(data, {type: `${mime};BASE64`});
})
.then(blob => {
uploadBlob = blob;
return imageRef.put(blob, {contentType: mime});
})
.then(() => {
uploadBlob.close();
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.setState(
{
imageURI: url,
},
() => {
alert('ImageURI ==> ', this.state.imageURI);
this.saveUserInfo();
},
);
});
return downnloadImageURI;
})
.then(url => {
resolve(url);
})
.catch(error => {
this.toggleLoading();
reject(error);
});
});
}
Here is code for saving user's data
saveUserInfo = () => {
const {userName, email, password, imageURI} = this.state;
const {navigate} = this.props.navigation;
const uid = firebaseService.auth().currentUser.uid;
const params = {
image: imageURI,
username: userName,
email: email,
password: password,
};
//firebaseService.database().ref('/Users').push(params)
firebaseService
.database()
.ref('/Users')
.child(uid)
.set(params)
.then(res => {
this.toggleLoading();
navigate('Login');
})
.catch(err => {
alert(err);
});
};
Here are screenshots of Firebase Console
Are the "Rules" in database given permission to "Write"
Go to the firebase console and open your project.
Go to the database and search for "Rules" tab.
Check the rules are set as below
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": true,
".write": true
}
}
I've solved this issue. The issue was in this piece of code.
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.setState(
{
imageURI: url,
},
() => {
alert('ImageURI ==> ', this.state.imageURI);
this.saveUserInfo();
},
);
setState was not working and calback was not fired.
And I've made it like this way
const downnloadImageURI = imageRef.getDownloadURL().then(url => {
this.saveUserInfo(url)
);}
I want to create a function that is about uploading photo to Firebase Storage with react-native-fetch-blob. I'm using Redux and you can find action functions below:
My problem is that uploadImage function is not running like asynchronous. Firebase function is running before uploadImage, so application give me an error.
I think i can't make a asynchronous function. How can i fix it ?
uploadImage() function:
const uploadImage = async (imageSource, whereToUpload) => {
let imageURL = '';
const mime = 'image/jpg';
const { Blob } = RNFetchBlob.polyfill;
const { fs } = RNFetchBlob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
console.log('URI =>', imageSource.uri);
let imgUri = imageSource.uri;
let uploadBlob = null;
const imageRef = firebase.storage().ref(whereToUpload + '/' + imageSource.fileName);
const uploadUri = Platform.OS === 'ios' ? imgUri.replace('file://', '') : imgUri;
await fs.readFile(uploadUri, 'base64')
.then((data) => Blob.build(data, { type: `${mime};BASE64` }))
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
// eslint-disable-next-line no-return-assign
return imageURL = imageRef.getDownloadURL();
})
.catch((error) => {
console.log(error);
});
return imageURL;
};
and the main action is:
export const addProjectGroup = (
myUser,
groupName,
groupDescription,
groupProfilePic,
) => dispatch => {
const groupProfileFinalPic = async () => {
let finalGroupPicture = { landscape: '' };
if (_.isEmpty(groupProfilePic.src)) {
await uploadImage(groupProfilePic, 'groupPictures').then((imageURL) => {
console.log('İŞLEM TAMAM!');
console.log('SELECTED IMAGE URL =>', imageURL);
finalGroupPicture.landscape = imageURL;
});
} else {
finalGroupPicture.landscape = groupProfilePic.src.landscape;
}
return finalGroupPicture;
};
console.log("final group profile pic =>", groupProfileFinalPic());
// Önce grubu yaratalım..
// eslint-disable-next-line prefer-destructuring
const key = firebase
.database()
.ref()
.child('groups')
.push().key;
firebase
.database()
.ref('/groups/' + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid,
},
groupName,
groupDescription,
groupProfilePic: groupProfileFinalPic(),
projects: '',
})
.then(() => {
console.log('Groups oluşturuldu.');
})
.catch(e => {
Alert.alert('Hata', 'Beklenmedik bir hata meydana geldi.');
console.log(e.message);
});
dispatch({
type: ADD_PROJECT_GROUP,
});
};
You are not awaiting groupProfileFinalPic(). This should be done before creating the action you want to dispatch.
groupProfileFinalPic().then(groupProfilePic => {
return firebase
.database()
.ref("/groups/" + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid
},
groupName,
groupDescription,
groupProfilePic,
projects: ""
})
.then(() => {
console.log("Groups oluşturuldu.");
})
.catch(e => {
Alert.alert("Hata", "Beklenmedik bir hata meydana geldi.");
console.log(e.message);
});
});
I have no clue what the last dispatch is for, you might want to do that in one of the callbacks. Your code is to verbose for an SO question, but I hope this helps anyways.
You are using both await and then on the same call. To use await, you can arrange it something like
const uploadImage = async (imageSource, whereToUpload) => {
...
try {
let data = await RNFS.fs.readFile(uploadUri, 'base64')
let uploadBlob = await Blob.build(data, { type: `${mime};BASE64` }))
...etc...
return finalResult
catch (e) {
// handle error
}
}