How to update page after fetch POST request - javascript

I am creating a simple chat room and am expecting the page to update when I enter a message into a text box and press enter.
The room is receiving messages from a URL, but I have to reload the page to see my new message whenever I post it.
How do I display these messages without having to reload the page?
fetch GET:
fetch('https://curriculum-api.codesmith.io/messages', { 'method': 'GET' })
.then(response => response.json())
.then(data => addText(data))
fetch POST:
textBox.addEventListener('keydown', (e) => {
if (e.code === 'Enter') {
const func = async function postReply() {
const currentDate = new Date()
const message = textBox.value;
textBox.value = ''
return await fetch('https://curriculum-api.codesmith.io/messages',
{
method: 'POST',
body: JSON.stringify({
'message': message,
'created_at': currentDate.toUTCString(),
'created_by': 'Nate & Dewey'
})
})
.then(response => response.json())
// .then(json => addText(json.message))
}
func()
// $('#result').load('https://curriculum-api.codesmith.io/messages');
}
})
addText() function (used by GET)
function addText(data) {
let messageNum = 0
let current = data[messageNum]
while (current) {
const text = document.createElement('div');
border.appendChild(text);
text.innerText = current.message + ' (' + current.created_by + ')'
messageNum++
current = data[messageNum]
}
}

Related

How can i run a function in every screen user is navigating to?

how can I run a function in the whole app? like if that function is triggered then even if a user is navigating to a different screen then also that function will do its work until that function work is done how can I do this in react native? I want to do this with my PostImageHandler once postimagehandler is triggered then that function will run and it won't stop until the image is uploaded also user can navigate through different screens during that process
const [loading1, setLoading1] = useState(false)
const [loading2, setLoading2] = useState(false)
const [photo, setPhoto] = useState(null)
const { postImage } = route.params;
const PostImageHandler = useCallback(async () => {
if (!postImage.cancelled) {
const response = await fetch(postImage);
const blob = await response.blob();
const filename = postImage.substring(postImage.lastIndexOf('/') + 1);
const ref = firebase.storage().ref().child(filename);
const snapshot = await ref.put(blob);
const url = await snapshot.ref.getDownloadURL();
setPhoto(url)
console.log(url)
}
}, [postImage])
useEffect(() => {
PostImageHandler();
}, [PostImageHandler])
const handleUpload = useCallback(() => {
if (postImage != null) {
AsyncStorage.getItem('user')
.then(data => {
setLoading2(true)
fetch('https://mybackend.com/addpost', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: JSON.parse(data).user.email,
post: postImage,
})
})
.then(res => res.json())
.then(data => {
if (data.message == 'Photo added successfully') {
alert('Photo added successfully')
setLoading2(false)
navigation.navigate('home')
} else {
alert('Something went wrong, please try again')
setLoading2(false)
}
})
})
} else {
alert('Please wait photo is processing')
}
}, [photo, navigation, setLoading2]);

Spotify API - Audio Player

I am relatively new to Javascript, I am practicing with a program that is able to pull data from Spotify API starting with Genre, then Playlists by Genre, Tracks, Track details, and an audio tag player to play a preview of the track.
I am able to do the Genre, Tracks, Track Details, but can't figure out the audio tag being linked to the track. The two issues, I have:
How to generate the audio tag based on user selection, and then reset it once a new selection is made
How to Get the Preview for the track based on user selection (for now I have the src for the audio tag as a random track.
const APIController = (function() {
const clientId = 'XX';
const clientSecret = 'XX';
//Fetch data from spotify api; private methods
const _getToken = async () => {
const result = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : 'Basic ' + btoa( clientId + ':' + clientSecret)
},
body: 'grant_type=client_credentials'
});
const spot = await result.json();
return spot.access_token;
}
const _getGenres = async (token) => {
const limit = 10;
const result = await fetch(`https://api.spotify.com/v1/browse/categories?country=CA&limit=${limit}`, {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const spot = await result.json();
return spot.categories.items;
}
const _getPlaylistByGenre = async (token, genreId) => {
const limit = 10;
const result = await fetch(`https://api.spotify.com/v1/browse/categories/${genreId}/playlists?limit=${limit}`, {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const spot = await result.json();
return spot.playlists.items;
}
const _getTracks = async (token, tracklist) => {
const limit = 30;
const result = await fetch(`${tracklist}?limit=${limit}`, {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const spot = await result.json();
return spot.items;
}
const _getTrack = async (token, trackdetail) => {
const result = await fetch(`${trackdetail}`, {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const spot = await result.json();
return spot;
}
const _getPreview = async (token, trackpreview) => {
const result = await fetch(`${trackpreview}`, {
method: 'GET',
headers: { 'Authorization' : 'Bearer ' + token}
});
const spot = await result.json();
return spot.preview;
}
return {
getToken() {
return _getToken();
},
getGenres(token) {
return _getGenres(token);
},
getPlaylistByGenre(token, genreId) {
return _getPlaylistByGenre(token, genreId);
},
getTracks(token, tracklist) {
return _getTracks(token, tracklist);
},
getTrack(token, trackdetail) {
return _getTrack(token, trackdetail);
},
getPreview(token, trackpreview) {
return _getPreview(token, trackpreview);
}
}
})();
// UI Module
const UIController = (function() {
//object to hold references to html selectors
const DOMElements = {
selectGenre: '#select_genre',
selectPlaylist: '#select_playlist',
buttonSubmit: '#btn_submit',
divSongDetail: '#song-detail',
hfToken: '#hidden_token',
divSonglist: '.song-list',
preview:'.songpreview'
}
//public methods
return {
//method to get input fields
inputField() {
return {
genre: document.querySelector(DOMElements.selectGenre),
playlist: document.querySelector(DOMElements.selectPlaylist),
tracks: document.querySelector(DOMElements.divSonglist),
submit: document.querySelector(DOMElements.buttonSubmit),
songDetail: document.querySelector(DOMElements.divSongDetail),
songPreview: document.querySelector(DOMElements.preview)
}
},
// need methods to create select list option
createGenre(text, value) {
const html = `<option value="${value}">${text}</option>`;
document.querySelector(DOMElements.selectGenre).insertAdjacentHTML('beforeend', html);
},
createPlaylist(text, value) {
const html = `<option value="${value}">${text}</option>`;
document.querySelector(DOMElements.selectPlaylist).insertAdjacentHTML('beforeend', html);
},
// need method to create a track list group item
createTrack(id, name) {
const html = `${name} `;
document.querySelector(DOMElements.divSonglist).insertAdjacentHTML('beforeend', html);
},
// need method to create the song detail
createTrackDetail(img, title, artist) {
const detailDiv = document.querySelector(DOMElements.divSongDetail);
// any time user clicks a new song, we need to clear out the song detail div
detailDiv.innerHTML = '';
const html =
`
<div class="songimg">
<img src="${img}" alt=""width="100px" height="100px">
</div>
<div class="songname"><span>
<label for="Genre" style="font-size:20px; color:black" class="form-label">${title}</label>
</span>
</div>
<div class="artistname"><span>
<label for="artist" style="color:blue" class="form-label">${rtist}</label>
</span></div>
`;
detailDiv.insertAdjacentHTML('beforeend', html)
},
createPreview() {
const html = `<audio class="preview" id="newplayer" controls onplay="playtrack()" onpause="pausetrack()" type="audio/mpeg" src="https://p.scdn.co/mp3-preview/ad57003c15e607c0d74c8a25ed7581c770b28a9a?cid=774b29d4f13844c495f206cafdad9c86" preload="auto"></audio>`;
document.querySelector(DOMElements.songPreview).insertAdjacentHTML('beforeend', html);
},
//method to reset fields
resetPreview() {
this.inputField().songPreview.innerHTML = '';
},
resetTrackDetail() {
this.inputField().songDetail.innerHTML = '';
},
resetTracks() {
this.inputField().tracks.innerHTML = '';
this.resetTrackDetail();
const spotpreview=document.getElementById("newplayer").classList;
spotpreview.remove("showme");
document.getElementsByTagName("body")[0].style="background-image:url('hands.jpeg');";
document.getElementsByTagName("body")[0].class="backgrd3";
},
resetPlaylist() {
this.inputField().playlist.innerHTML = '';
this.resetTracks();
},
storeToken(value) {
document.querySelector(DOMElements.hfToken).value = value;
},
getStoredToken() {
return {
token: document.querySelector(DOMElements.hfToken).value
}
}
}
})();
const APPController = (function(UICtrl, APICtrl) {
// get input field object ref
const DOMInputs = UICtrl.inputField();
// get genres on page load
const loadGenres = async () => {
//get the token
const token = await APICtrl.getToken();
//store the token onto the page
UICtrl.storeToken(token);
//get the genres
const genres = await APICtrl.getGenres(token);
//populate our genres select element
genres.forEach(element => UICtrl.createGenre(element.name, element.id));
}
// create genre change event listener
DOMInputs.genre.addEventListener('change', async () => {
//reset the playlist
UICtrl.resetPlaylist();
//get the token that's stored on the page
const token = UICtrl.getStoredToken().token;
// get the genre select field
const genreSelect = UICtrl.inputField().genre;
// get the genre id associated with the selected genre
const genreId = genreSelect.options[genreSelect.selectedIndex].value;
// ge the playlist based on a genre
const playlist = await APICtrl.getPlaylistByGenre(token, genreId);
// create a playlist list item for every playlist returned
playlist.forEach(p => UICtrl.createPlaylist(p.name, p.tracks.href));
});
// create submit button click event listener
DOMInputs.submit.addEventListener('click', async (e) => {
// prevent page reset
e.preventDefault();
// clear tracks
UICtrl.resetTracks();
//get the token
const token = UICtrl.getStoredToken().token;
// get the playlist field
const playlistSelect = UICtrl.inputField().playlist;
// get track endpoint based on the selected playlist
const tracksEndPoint = playlistSelect.options[playlistSelect.selectedIndex].value;
// get the list of tracks
const tracks = await APICtrl.getTracks(token, tracksEndPoint);
// create a track list item
tracks.forEach(el => UICtrl.createTrack(el.track.href, el.track.name))
});
// create song selection click event listener
DOMInputs.tracks.addEventListener('click', async (e) => {
// prevent page reset
e.preventDefault();
UICtrl.resetTrackDetail();
// get the token
const token = UICtrl.getStoredToken().token;
// get the track endpoint
const trackEndpoint = e.target.id;
//get the track object
const track = await APICtrl.getTrack(token, trackEndpoint);
// load the track details
UICtrl.createTrackDetail(track.album.images[2].url, track.name, track.artists[0].name);
});
// create song preview selection click event listener
DOMInputs.songPreview.addEventListener('click', async (e) => {
// prevent page reset
e.preventDefault();
UICtrl.resetPreview();
// get the token
const token = UICtrl.getStoredToken().token;
// get the playlist field
const previewsong = UICtrl.inputField().songPreview;
const previewEndPoint = previewsong.options[previewsong.selectedIndex].value;
// get the list of tracks
const tracks = await APICtrl.getTracks(token, previewEndPoint);
// create a track list item
tracks.forEach(el => UICtrl.createTrack(el.track.href, el.track.name))
});
return {
init() {
console.log('App is starting');
loadGenres();
}
}
})(UIController, APIController);
// will need to call a method to load the genres on page load
APPController.init();

Discord.js Display Reddit Post's Title

I have this code that gets a random post from the top of r/memes and I want it to display the random post's title that it picked.
if(msg.content === '-meme')
{
var Channel = msg.channel.name
if(Channel != "chill-bot-log" && Channel != "chill-shitpost") {
msg.channel.send(msg.author + ' ezt a parancsot nem használhatod ebben a csatornában');
console.info(msg.author + " megpróbálta loggolni a botot egy rossz csatornában.");
} else {
loadMemes(message);
}
function loadMemes() {
fetch('https://www.reddit.com/r/memes.json?limit=800&?sort=hot&t=all')
.then(res => res.json())
//.then(res => console.log(res))
.then(json => json.data.children.map(v => v.data.url))
.then(urls => postRandomMeme(urls));
}
function postRandomMeme(urls) {
const randomURL = urls[Math.floor(Math.random() * urls.length) + 1];
const redditUrl = `https://www.reddit.com${randomURL.reddit}`;
const embed = new Discord.RichEmbed({
image: {
url: randomURL
}
});
embed.setFooter('Subreddit : r/memes')
embed.setTitle(redditUrl)
msg.channel.send(embed);
}
}
function loadMemes() {
// Fetch JSON
return fetch('https://www.reddit.com/r/memes.json?limit=800&?sort=hot&t=all')
.then(res => res.json())
// Return the actual posts
.then(json => json.data.children);
}
function postRandomMeme(message) {
return loadMemes().then(posts => {
// Get a random post's title and URL
const {title, url} = posts[Math.floor(Math.random() * posts.length)].data;
// Create the embed
// For Discord.js v11 replace MessageEmbed with RichEmbed
const embed = new Discord.MessageEmbed({
title,
image: {url},
footer: {text: 'Subreddit : r/memes'}
});
// Send the embed
// For Discord.js v11/v12 use .send(embed)
return message.channel.send({embeds: [embed]});
})
}
// Usage:
postRandomMeme(msg)
// Log all errors
.catch(console.error);

Indexeddb cursor wait for response?

I have an application which contains a indexeddb database. It saves info for a while. If this info was not passed to the server, for example due to a network error, the "synced" is set to false. Now I want to create a function that is able to upload the items with status: "synced:false" to the server.
The idea is to iterate through the db and everytime there is an entry with false, upload it to the server and on succes update the value in the local (indexeddb) db.
The problem I'm having is that I can't see how I can let the cursor operation wait for the response of the server (REST API) and then do actions accordingly (update local value "synced:false" -> "synced:true". The update to the server goes well.
Here is a working Stackblitz that shows the full code on the Homepage:
https://stackblitz.com/edit/ionic-thu3eg
Output is in the console.
This is an example with the actual problem.
update() {
var callstring: string;
let nowTime = new Date().toISOString();
let nowTimes = dateFns.format(nowTime, 'YYYY-MM-DD HH:mm:ss');
var headers = new Headers();
headers.append("Accept", "application/json");
headers.append("Content-Type", "application/json");
let options = new RequestOptions({ headers: headers });
const dbPromise = openDb('testdb', 1);
dbPromise.then(async db => {
const tx = db.transaction('scans', 'readwrite');
tx.objectStore('scans').iterateCursor(async cursor => {
if (!cursor) return;
if (cursor.value.synced == 'false') {
console.log(cursor.value);
await new Promise((resolve, reject) => {
this.http.get('https://jsonplaceholder.typicode.com/posts/1')
.map(res => res.json())
.subscribe(res => {
console.log('response : ', res.id);
resolve(res)
return callstring = res.id;
}, error => {
reject(error)
});
});
if (callstring == '1') {
console.log('do something : ', callstring);
cursor.value.synced = 'true';
cursor.value.time = nowTimes;
cursor.update(cursor.value);
} else {
console.log('sorry too late');
}
}
await cursor.continue();
});
await tx.complete.then(() => console.log('done cursoring'));
}).then(() => {
this.toastCtrl.create({
message: "DB updated",
duration: 2000,
position: 'top',
cssClass: "toast-mess"
}).present();
});
}
So if callstring = 1 then it should update the "false" value to "true" in the indexeddb.
How can I solve this ?
Thanks

Can't figure out why my app.get is being run twice?

I have a app.get which inside of it is quite a bit of logic. Which everything works great aside from some of the logic being called twice for some reason. I have noticed when I was saving something to by db that it would save two rows.
So I put a console.log in that area and sure enough it was logging it twice.
Any reason why this is happening?
app.get('/shopify/callback', (req, res) => {
const { shop, hmac, code, state } = req.query;
const stateCookie = cookie.parse(req.headers.cookie).state;
if (state !== stateCookie) {
return res.status(403).send('Request origin cannot be verified');
}
if (shop && hmac && code) {
// DONE: Validate request is from Shopify
const map = Object.assign({}, req.query);
delete map['signature'];
delete map['hmac'];
const message = querystring.stringify(map);
const providedHmac = Buffer.from(hmac, 'utf-8');
const generatedHash = Buffer.from(
crypto
.createHmac('sha256', config.oauth.client_secret)
.update(message)
.digest('hex'),
'utf-8'
);
let hashEquals = false;
try {
hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
} catch (e) {
hashEquals = false;
};
if (!hashEquals) {
return res.status(400).send('HMAC validation failed');
}
// DONE: Exchange temporary code for a permanent access token
const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
const accessTokenPayload = {
client_id: config.oauth.api_key,
client_secret: config.oauth.client_secret,
code,
};
request.post(accessTokenRequestUrl, { json: accessTokenPayload })
.then((accessTokenResponse) => {
const accessToken = accessTokenResponse.access_token;
// DONE: Use access token to make API call to 'shop' endpoint
const shopRequestUrl = 'https://' + shop + '/admin/shop.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
}
request.get(shopRequestUrl, { headers: shopRequestHeaders })
.then((shopResponse) => {
const response = JSON.parse(shopResponse);
const shopData = response.shop;
console.log('BEING CALLED TWICE...')
res.render('pages/brand_signup',{
shop: shopData.name
})
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
} else {
res.status(400).send('Required parameters missing');
}
});

Categories