React Native If Exist in Firebase - reactjs

My firebase structure:
Hello, i am trying;
One person opening a announcement with own userid. After another person get in this announcement's inside. If second person wants to send a notification to first person, he uses first person's userid's table in firebase and he put own userid's to first persons userid's table. If first person wants to see, who sends notification to him, he looks to own user id's table and he sees other peoples userids (other people are sended notification to him).. Now one person can send lots of time notification, i want to one person can send just one time for this reason i am trying to control it.
if (firebase.database().ref(`/bavuruistek/${userid}`).child(katilan) === null ) {
firebase.database().ref(`/bavuruistek/${userid}`)
.push({
katilan, istek })
.then(() => {
dispatch({ type: STUDENT_REQUEST_SUCCESS });
Actions.pop();
});
}
if (firebase.database().ref(`/bavuruistek/${userid}`).child(katilan) !== null) {
console.log(firebase.database().ref(`/bavuruistek/${userid}/${katilan}`));
Alert.alert(
'Mesaj',
'Daha önce başvurunuz yapılmış!',
[
{ text: 'Tamam', onPress: () => null }
]
);
}

firebase.database().ref(`/basvuruistek/${userid}`).on('value', (snapshot) => {
const { currentUser } = firebase.auth();
const notes = snapshot.val();
Object.keys(notes).forEach(key => {
if (notes[key].katilan !== currentUser.uid) {
this.setState({ click: true });
} if (notes[key].katilan === currentUser.uid) {
this.setState({ click: false });
}
});
});

You are trying to use firebase.database().ref(`/bavuruistek/${userid}`).child(katilan) inside an if statement, which doesn't work because 1) .child() returns a Reference object. Trying something like this may help you achieve the intended outcome:
firebase.database().ref(`/bavuruistek/${userid}`).child(katilan).once('value').then(snapshot => {
if (snapshot.val() === null ) {
firebase.database().ref(`/bavuruistek/${userid}`)
.update({
katilan, istek
})
.then(() => {
dispatch({ type: STUDENT_REQUEST_SUCCESS });
Actions.pop();
});
} else {
console.log(snapshot.val());
Alert.alert(
'Mesaj',
'Daha önce başvurunuz yapılmış!',
[
{ text: 'Tamam', onPress: () => null }
]
);
}
}
The main difference is that I'm using .once, reading the resulting snapshot value, and using that as part of the if statement to check if it is null.

Related

Create and update inside map function

I'm trying to find the right way to create and consequently update inside a map function.
These are the steps I need:
Map function "reads" the array of elements ids
Create new record on "leads_status" table
Using the new record id (from "leads_status") "leads" table is updated using "leads_status.id" as foreign key related to "leads.id_ls"
This is the code I tried.
const [create, { isLoading: isLoadingCreate, error: errorCreate }] = useCreate();
const [record, setRecord] = React.useState(null);
leadsIDS.map((value, index) => {
create('leads_status', {
data: {
id_lead: value,
id_status: 5
}
}, {
onSuccess: ({ id }) => {
setRecord([id, value]);
},
onError: () => {
console.log();
}
});
update('leads', {
id: record[1],
data: {
id_ls: record[0]
}
}, {
enabled: !isLoadingCreate && record !== null
}, {
onSuccess: () => {
console.log(record);
},
onError: error => notify('Error', { type: 'warning' })
})
})
I tried also to put the "update" function inside the "create --> onSuccess" but also there the code is not working as I want.
In "leads_status" table records are always created for each element in "leadsIDS" array but in "leads" table only 1 records is updating.
Where am I wrong?
The useCreate and useUpdate hooks are designed for single actions. If you want to chain several actions, I suggest you use the useDataProvider hook, instead, which lets you manipulate Promises.
const dataProvider = useDataProvider();
const notify = useNotify();
try {
await Promise.all(leadsIDS.map(async (value, index) => {
const { data: leadStatus } = await dataProvider.create('leads_status', {
data: {
id_lead: value,
id_status: 5
}
});
await dataProvider.update('leads', {
id: value,
data: { id_ls: leadStatus.id }
});
}));
} catch (e) {
notify('Error', { type: 'warning' });
}

How to change "Request to join" button text to "Join Meeting" in iframe

I'm new to daily-co integration in react js. Can you please suggest how to change
"Request to Join" text to "Join Meeting". Thank in advance.
At present in Iframe all content is coming. Can any one please suggest how to change
the "Request to Join" text to "Join Meeting".
My Observations:
One api is calling at the time of page is loaded:
https://b.daily.co/call-ui/16c545a8520b661e39dc13c62b335ffea4cb3651/locales/en/translation.js
{ ....
"haircheck": {
....
"setup": {
"requestToJoin": "Request to join",
"title": "Are you ready to join?",
}
},
}
//React Class component:
import React from 'react';
import DailyIframe from '#daily-co/daily-js';
import Cookies from 'universal-cookie';
import axios from '../../util/axios';
import util from '../../util/util';
const cookies = new Cookies();
class VideoCallFrame2 extends React.Component {
constructor(props) {
super(props);
this.iframeRef = React.createRef();
this.state = {
authorizationToken: 'Bearer ------------',
roomName: '',
room: null,
token: null,
rooms: [],
roomUrlWithToken: null,
isVideoHidden: false,
joinedObject: null,
status: '',
askedQuestions: [],
};
}
componentDidMount() {
this.daily = DailyIframe.wrap(
this.iframeRef.current,
{
showLeaveButton: true,
});
this.setState({
...this.state,
roomUrlWithToken: this.props.meetingRoomUrl
});
this.startRoom();
let temp = this.daily.meetingState();
this.setState({ status: temp });
this.get_candidate_position();
}
get_candidate_position = (e) => {
this.setState({
positionDetails: response.data.candidate[0]
})
}
onHandleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
joinMeetingEvents = () => {
// Meeting related events
this.daily.on('loading', () => { console.log('Loading......') })
this.daily.on('loaded', () => { console.log('Loaded......') })
this.daily.on('joining-meeting', () => { console.log('Joining......') })
this.daily.on('joined-meeting', () => {
console.log('Joined......')
})
this.daily.on('app-message', (e) => {
console.log('app-messageapp-message app-message>>>>>>> ', e)
})
this.daily.on('left-meeting', (e) => {
console.log('Left Meeting......', e)
this.props.history.push('/thankyou')
})
this.daily.on('participant-joined', (e) => {
console.log('Partcipand Joined......', e);
this.setState({
...this.state,
isVideoHidden: true
})
if (this.state.joinedObject.user_id == '') {
}
})
this.daily.on('error', (e) => {
console.log('ERROR......', e)
})
}
leftMeeeting = () => {
this.daily.leave();
this.daily.destroy();
}
startRoom = async () => {
let res = await this.daily.join({
url: this.props.meetingRoomUrl
})
this.setState({
...this.state,
joinedObject: null
})
this.daily.on('loading', () => { console.log('Loading......') })
this.daily.on('loaded', () => { console.log('Loaded......') })
this.daily.on('joining-meeting', () => { console.log('joining-meeting......') })
this.daily.on('joined-meeting', () => {
console.log('Joined meeting......');
})
this.daily.on('joined-meeting', () => {
console.log('Joined meeting......');
})
this.daily.on('meeting-session-updated', () => {
console.log('meeting-session-updated......');
});
this.daily.on('access-state-updated', (evt) => {
console.log('access-state-updated......', evt);
if (evt.access.level == 'lobby') {
//Some code
}
});
this.daily.on('participant-joining', () => { console.log('participant-joining') })
this.daily.on('left-meeting', (e) => {
this.props.history.push('/thankyouPage');
});
this.daily.on("app-message", (e) => {
let Arr = this.state.askedQuestions;
if (
e &&
e.data &&
e.data.message &&
e.data.message.endInterview == "end") {
this.leftMeeeting();
}
});
this.daily.on('participant-joined', (e) => {
console.log('Partcipand Joined......', e);
setTimeout(() => {
this.daily.sendAppMessage({ message: { intervieweraskedQuestions: this.state.askedQuestions } }, '*');
}, 3000)
})
this.daily.on('error', (e) => {
console.log('ERROR......', e)
})
}
render() {
return (
<div className="" style={{ height: '450px' }}>
<iframe className="Video-Frame video-call-frame"
title="video call iframe"
ref={this.iframeRef}
allow="camera; microphone; fullscreen; display-capture"
></iframe>
</div>
)
}
}
export default VideoCallFrame2;
I work at Daily. :) "Request to join" is shown for private rooms with "knocking" enabled. We use this language because clicking the button will alert the room owner to let you in, so you do need to ask to join -- you can't just go straight in.
This can be turned off though. If you make the room public, it will say "Join meeting" instead of "Request to join" because anyone can join. Alternatively, you can make a meeting token for anyone trying to enter a private room so they don't need to ask to join. (In this case, the button text would also be updated to "Join meeting").
More generally, you can't update button text to something custom in the Daily Prebuilt UI, but you can build your on custom UI with our APIs. That's probably too much effort just to update one button, though. :)
I have not used daily.co before but I did a little digging and confirmed my suspicions: As far as I can tell, this is not possible.
In order to for a page to edit the contents of an iFrame, the frame must be on the same origin as its parent page, as per the Same Origin Policy.
Your page is on the origin http://localhost:3001, while the frame is on an origin owned by Daily, e.g. https://server.daily.co.
This policy exists for security reasons, an example is imagine some website https://attacker.com with a frame to https://bankaccount.com, without this policy the attacker could change a button on the frame from "Click to send all money to attacker" to "Click to receive your $1 million reward!"
The only method I have found that may be plausible after doing a couple searches for "origin", "host", etc. on docs.daily.co is this reference page for "Daily's Video Component System (VCS)", but from what I can tell this cannot solve the problem as this only allows you to add an overlay to the video call, not the frame itself.

Update an array relation belongs to many with Strapi controller

I use Strapi V4. I have a link collection and I want to update likes.
How update the relation array ? When I put new data old value are replace by the new one.
Example :
likes : [1]
if I update another time
likes:[2].
BUT I want this likes : [1,2]
I try this but It d'oesn't work. Thans for your replay
'use strict';
/**
* link controller
*/
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::link.link', ({ strapi }) => ({
// Method 2: Wrapping a core action (leaves core logic in place)
async find(ctx) {
const { data, meta } = await super.find(ctx);
const linkId = data.map((link) => link.id);
const allPosts = await strapi.entityService.findMany('api::link.link', {
fields: ["id"],
filters: { id: { $in: linkId } },
populate: {
likes: { count: true },
},
});
data.forEach(link => {
link.likes = allPosts.find(({ id }) => id === link.id)?.likes?.count || 0;
});
//update value with new array => need to be fix
await strapi.entityService.update("api::link.link", {
likes: [...allPosts.likes.map(({ id }) => id), ...likes],
});
return { data, meta };
},
}));
This part need to be fix. Can you help me ? Thanks
//update value with new array => need to be fix
await strapi.entityService.update("api::link.link", {
likes: [...allPosts.likes.map(({ id }) => id), ...likes],
});

React native: how do I wait for a state to be set, before I call another state related operation?

I am writing a chat app. Users can search for other users, and then press the "Message" button. Then I navigate to ChatScreen.js. If both users have been messaging each other, I set the chatId variable accordingly. If they have not messaged each other before I dont create chatId, until the ery first message has been sent. When the first message is sent, I first, create new chat, store its properties (user ids, chatId, etc) in my db and then I sent the first message. The problem is that I store chatId as a state variable, and when I create the chat I call setChatId(id). setChatId() is not synchronous call, so by the time when I need to send message with sendText(text, chatId); my chatId is undefined even though I have already created a chat and I have called setChatId.
How can I avoid this error? Ofc, I can check if chatId == undefined then calling sendText(text, id), otherwise calling sendText(text, chatId). Is there a better/neath way to avoid the undefined check?
Here is part of my code:
...
import {
createChat,
} from "./actions";
...
function ChatScreen(props) {
...
const [chatId, setChatId] = useState(props.route.params.chatId);
...
const setupChat = async () => {
try {
await createChat(user.id, setChatId);
props.fetchUserChats();
} catch (error) {
console.error("Error creating chat: ", error);
}
};
async function handleSend(messages) {
if (!chatId) {
// creating chat
await setupChat();
}
const text = messages[0].text ? messages[0].text : null;
const imageUrl = messages[0].image ? messages[0].image : null;
const videoUrl = messages[0].video ? messages[0].video : null;
const location = messages[0].location ? messages[0].location : null;
//assuming chatId is already setup but it is not
if (imageUrl) {
sendImage(imageUrl, chatId, setSendImageError);
} else if (location) {
sendLocation(location, chatId, setLocationError);
} else if (videoUrl) {
sendVideo(videoUrl, chatId, setSendImageError);
} else {
sendText(text, chatId);
}
}
...
}
My createChat function from actions.js file
export async function createChat(otherUid, setChatId) {
let chatId = firebase.auth().currentUser.uid + "_" + otherUid;
await firebase
.firestore()
.collection("Chats")
.doc(chatId)
.set({
users: [firebase.auth().currentUser.uid, otherUid],
lastMessage: "Send the first message",
lastMessageTimestamp: firebase.firestore.FieldValue.serverTimestamp(),
})
.then(() => {
console.log("doc ref for creatign new chat: ", chatId);
setChatId(chatId);
})
.catch((error) => {
console.error("Error creating chat: ", error);
});
}
Instead of using a state variable, I would advise you to use useRef(). This would be a good solution to your problem.Eg Define it this way
const chatId = useRef(null),
then set it this way chatId.current = yourChatId
and get it this way chatId.current. I hope this solves your problem

react-admin: changing a list from store without http requests

I am using react-admin and I need to control directly the store from one resource, in my case, the orders resource.
Everytime I run the GET_LISTit appends the new records in the list from the store, but, I would like to get a new list from the server and discard the old ones. Here`s where I retrieve the records:
dataProvider(GET_LIST, 'orders', {
filter: { updatedAt: filterDate }, // Get date from Filter.
sort: { field: 'updatedAt', order: 'DESC' },
pagination: { page: 1, perPage: 999 },
}).then(response => response.data)
So, I decided to manipulate the store directly and after some digging I saw this answer and this code from the source:
const dataReducer: Reducer<RecordSetWithDate> = (
previousState = initialState,
{ payload, meta }
) => {
if (meta && meta.optimistic) {
if (meta.fetch === UPDATE) {
const updatedRecord = {
...previousState[payload.id],
...payload.data,
};
return addRecords([updatedRecord], previousState);
}
if (meta.fetch === UPDATE_MANY) {
const updatedRecords = payload.ids.map(id => ({
...previousState[id],
...payload.data,
}));
return addRecords(updatedRecords, previousState);
}
if (meta.fetch === DELETE) {
return removeRecords([payload.id], previousState);
}
if (meta.fetch === DELETE_MANY) {
return removeRecords(payload.ids, previousState);
}
}
if (!meta || !meta.fetchResponse || meta.fetchStatus !== FETCH_END) {
return previousState;
}
switch (meta.fetchResponse) {
case GET_LIST:
case GET_MANY:
case GET_MANY_REFERENCE:
return addRecords(payload.data, previousState);
case GET_ONE:
case UPDATE:
case CREATE:
return addRecords([payload.data], previousState);
default:
return previousState;
}
};
So, based on that, I created a custom action to delete the old ids from my list and add the new ones retrieved from the data source:
import {GET_LIST, DELETE_MANY, FETCH_END } from 'react-admin';
export const UPDATE_ORDER_ADMIN = 'UPDATE_ORDER_ADMIN';
export const update_orders_admin = (data, oldIDS) => ({
type: UPDATE_ORDER_ADMIN,
payload: { data, ids: oldIDS },
meta: {
resource: 'orders',
optimistic: true,
fetch: DELETE_MANY,
fetchResponse: GET_LIST,
fetchStatus: FETCH_END,
},
});
And I am using this custom action after retrieve data from the backend:
dataProvider(GET_LIST, 'orders', {
filter: { updatedAt: filterDate }, // Get date from Filter.
sort: { field: 'updatedAt', order: 'DESC' },
pagination: { page: 1, perPage: 999 },
}).then(response => response.data)
.then(data => {
const ids = orders ? Object.keys(orders) : [];
update_orders_admin(data, ids);
this.setState({ isLoading: false })
return null;
});
However, the system is calling the DELETE action from backend, trying to delete the records from the database, while, what I would like is just delete these records from my view.
Any thoughts?
In your custom action you have the fetch set as DELETE_MANY which will do a loop over every id performing DELETE operation. Not sure if you implementation will work, but the current error is about that. You could try to remove the fetch ans see what happens, but I think without it he will not fetch records. If I'm not mistaken RA only adds new ids to data, however if data changed in the meantime I don't think it will replace the changed data for that you need to reimplement the data provider to change the update data behaviour which is similar to what you're trying.

Resources