In product page, I want to get all images path that are in a specific folder and send those to client side, so I can use them in client side by passing the paths to Image component of next js. I tried this when I was developing my app via running npm run dev and it was successful. Then I pushed the changes to my GitHub repository and vercel built my app again. Now, when I go to the product page, I get an error from the server. I tried some ways to fix this problem, but I couldn't fix that. For example, I tried changing my entered path in readdir, but the problem didn't fix. Here are my codes:
const getPagePhotosAndReview = async (productName) => {
const root = process.cwd();
let notFound = false;
const allDatas = await fs
.readdir(root + `/public/about-${productName}`, { encoding: "utf8" })
.then((files) => {
const allDatas = { pageImages: [], review: null };
files.forEach((value) => {
const image = value.split(".")[0];
const imageInfos = {
src: `/about-${productName}/${value}`,
alt: productName,
};
if (Number(image)) {
allDatas.pageImages.push(imageInfos);
}
});
return allDatas;
})
.catch((reason) => (notFound = true));
if (notFound) return 404;
await fs
.readFile(root + `/public/about-${productName}/review.txt`, {
encoding: "utf-8",
})
.then((value) => {
allDatas.review = value;
})
.catch((reason) => {
allDatas.review = null;
});
return allDatas;
};
export async function getServerSideProps(context) {
if (context.params.product.length > 3) {
return { notFound: true };
}
if (context.params.product.length < 3) {
const filters = {
kinds: originKinds[context.params.product[0]] || " ",
};
if (context.params.product[1]) filters.brands = context.params.product[1];
const products = getFilteredProducts(filters, true);
if (products.datas.length === 0) {
return {
notFound: true,
};
}
return {
props: {
products: { ...products },
},
};
}
if (context.params.product.length === 3) {
const filters = {
path: context.resolvedUrl,
};
const product = getFilteredProducts(filters, false);
if (product.length === 0) {
return {
notFound: true,
};
}
const splitedPath = product[0].path.split("/");
const pagePhotosAndReview = await getPagePhotosAndReview(
splitedPath[splitedPath.length - 1]
);
if (pagePhotosAndReview === 404) return { notFound: true };
product[0] = {
...product[0],
...pagePhotosAndReview,
};
product[0].addressArray = [
textOfPaths[context.params.product[0]],
textOfPaths[context.params.product[1]],
];
return {
props: {
product: product[0],
},
};
}
}
This is the base code and I tried some ways but couldn't fix the problem. So to fix this problem, I want to ask: how can I get the name of all images in a specific directory and then use those images in client side? And errors that I get: if I go to a page directly and without going to the home of the website, I get internal server error with code of 500 and when I go to a page of my website, and then I go to my product page, I get
Application error: a client-side exception has occurred (see the browser console for more information).
And I should say that I know I should remove public from paths when I want to load an image from public folder. I did it but I still get error.
Related
I recently started writing Discordbots and just can't seem to get anywhere pushing the slash commands. I already have a handler file (pushSlash.js) but for some reason the commands are never loaded or I get an error in the console (mostly simply this: chalk.blue is not a function). My bot also doesn't get the badge that it supports slash commands.
Can anyone help me further?
Here is my code (pushSlash.js):
module.exports = (client) => {
const fs = require('fs');
const { PermissionsBitField } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const { REST } = require('#discordjs/rest');
const AsciiTable = require('ascii-table');
const table = new AsciiTable().setHeading('Slash Commands', 'Stats').setBorder('|', '=', "0", "0");
const TOKEN = process.env.BOT_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
const rest = new REST({ version: '9' }).setToken(TOKEN);
import( 'chalk').then(chalk => {
const slashCommands = [];
fs.readdirSync('/home/container/src/slashCommands/').forEach(async dir => {
const files = fs.readdirSync(`/home/container/src/slashCommands/${dir}/`).filter(file => file.endsWith('.js'));
for(const file of files) {
const slashCommand = require(`/home/container/src/slashCommands/${dir}/${file}`);
slashCommands.push({
name: slashCommand.name,
description: slashCommand.description,
options: slashCommand.options ? slashCommand.options : null,
default_permission: slashCommand.default_permission ? slashCommand.default_permission : null,
default_member_permissions: slashCommand.default_member_permissions ? PermissionsBitField.resolve(slashCommand.default_member_permissions).toString() : null
});
if(slashCommand.name) {
client.slashCommands.set(slashCommand.name, slashCommand);
table.addRow(file.split('.js')[0], '✅');
} else {
table.addRow(file.split('.js')[0], '⛔');
}
}
});
console.log(chalk.blue(table.toString()));
(async () => {
try {
await rest.put(
process.env.GUILD_ID ?
Routes.applicationGuildCommands(CLIENT_ID, process.env.GUILD_ID) :
Routes.applicationCommands(CLIENT_ID),
{ body: slashCommands }
);
console.log(chalk.green('Successfully registered application commands.'));
} catch (error) {
console.log(error);
}
})();
});
};
I've already tried everything possible, but since I'm relatively new to discord.js, I don't know that much yet either.
Actually everything should work and exactly 2 different commands should be loaded, but I only get error messages or the handler was loaded on console but nothing is displayed on Discord.
first download chalk#4.1.2 with
npm install chalk#4.1.2
and import chalk normally.
const chalk = require('chalk')
There your code modified version:
module.exports = (client) => {
const fs = require('fs');
const { PermissionsBitField } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const { REST } = require('#discordjs/rest');
const AsciiTable = require('ascii-table');
const table = new AsciiTable().setHeading('Slash Commands', 'Stats').setBorder('|', '=', "0", "0");
const TOKEN = process.env.BOT_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
const rest = new REST({ version: '9' }).setToken(TOKEN);
// Imported chalk normally
const chalk = require('chalk')
// removed `import( 'chalk').then(chalk => {})`
const slashCommands = [];
fs.readdirSync('/home/container/src/slashCommands/').forEach(async dir => {
const files = fs.readdirSync(`/home/container/src/slashCommands/${dir}/`).filter(file => file.endsWith('.js'));
for(const file of files) {
const slashCommand = require(`/home/container/src/slashCommands/${dir}/${file}`);
slashCommands.push({
name: slashCommand.name,
description: slashCommand.description,
options: slashCommand.options ? slashCommand.options : null,
default_permission: slashCommand.default_permission ? slashCommand.default_permission : null,
default_member_permissions: slashCommand.default_member_permissions ? PermissionsBitField.resolve(slashCommand.default_member_permissions).toString() : null
});
if(slashCommand.name) {
client.slashCommands.set(slashCommand.name, slashCommand);
table.addRow(file.split('.js')[0], '✅');
} else {
table.addRow(file.split('.js')[0], '⛔');
}
}
});
console.log(chalk.blue(table.toString()));
(async () => {
try {
await rest.put(
process.env.GUILD_ID ?
Routes.applicationGuildCommands(CLIENT_ID, process.env.GUILD_ID) :
Routes.applicationCommands(CLIENT_ID),
{ body: slashCommands }
);
console.log(chalk.green('Successfully registered application commands.'));
} catch (error) {
console.log(error);
}
})();
};
I have a website built by Next.js and we deployed it on Vercel.
We localize our website in 5 different languages, and as I found the solution with rewrites for localizing the urls as well.
We have a custom page: customer-stories, and would like to localize these:
customer_stories: {
hu: '/esettanulmanyok',
en: '/customer-stories',
de: '/kundengeschichte',
sk: '/pribehy-zakaznikov',
cs: '/pribehy-zakazniku',
},
So in the next config file:
Inside rewrites:
{
source: '/hu/esettanulmanyok/:id*/',
destination: '/hu/customer-stories/:id*/',
locale: false,
},
{
source: '/de/kundengeschichte/:id*/',
destination: '/de/customer-stories/:id*/',
locale: false,
},
{
source: '/cs/pribehy-zakazniku/:id*/',
destination: '/cs/customer-stories/:id*/',
locale: false,
},
{
source: '/sk/pribehy-zakaznikov/:id*/',
destination: '/sk/customer-stories/:id*/',
locale: false,
},
Which is working perfectly on localhost:
http://localhost:3000/hu/esettanulmanyok/
And a dynamic id page:
http://localhost:3000/hu/esettanulmanyok/newtestwithreference/
They work as expected, but on the released site it is different:
The same url is 404: https://barion-builderio.vercel.app/hu/esettanulmanyok/
The same dynamic url is working: https://barion-builderio.vercel.app/hu/esettanulmanyok/newtestwithreference/
What is very interested, because the main page is using pagination with getInitialProps:
When I go the original page without rewrites: https://barion-builderio.vercel.app/hu/customer-stories/
And after that, I paginate on the website:
And click on the next page:
The url is changing to the correct one, but if I try to refresh on the page, again 404:
So the dynamic [id] site is working well with rewrites, but the list page with getinitialprops not working for the first time, only with the original url, and after that if the user uses the pagination the rewrites will working. On the page we use shallow routing for not loading the site again.
I don't know why is it working properly on localhost and not on the server:
Here is the full (important part) code of my customer-stories.js:
imports...
const articlesPerPage = 4
const CustomerStories = ({
stories,
texts,
tophero,
bottomhero,
enumlocalization,
page,
navbar,
footer,
subfooter,
}) => {
const { locale, pathname } = useRouter()
const [currentPage, setCurrentPage] = useState(page)
const [filteredData, setFilteredData] = useState(stories)
const router = useRouter()
const handlePageReset = () => {
console.log('reset futott')
setCurrentPage(0)
handlePaginationClick(0)
}
const {
country,
industry,
solution,
handleIndustry,
handleCountry,
handleSolution,
} = useCustomerStoriesContext()
//FILTERING ON THE SITE
useDidMountEffect(async () => {
const queryArray = {}
if (solution && solution.key != null) {
queryArray = {
...queryArray,
'data.solution.$elemMatch.solution.type': solution.key.type,
}
}
if (industry && industry.key != null) {
queryArray = {
...queryArray,
'data.industry.type.$eq': industry.key.type,
}
}
if (country && country.key != null) {
queryArray = {
...queryArray,
'data.country.type.$eq': country.key.type,
}
}
const result = await builder.getAll('barion-userstory-data', {
options: {
noTargeting: true,
query: queryArray,
page: 0,
},
omit: 'data.blocks',
})
handlePageReset()
setFilteredData((prev) => result)
}, [country, industry, solution])
const handlePaginationClick = (page) => {
//setCurrentPage(page)
router.push(
{
pathname: LOCALIZED_URLS['customer_stories'][locale],
query: page != 0 ? { page: page != 0 ? page : '' } : {},
},
undefined,
{ shallow: false }
)
}
return (
<>
<Head>
<meta name="robots" content="noindex" />
</Head>
<div>
PAGE LIST CONTENT CUSTOMER-STORIES
</div>
</>
)
}
CustomerStories.getInitialProps = async ({
req,
res,
asPath,
query,
locale,
}) => {
if (locale == 'default') {
return {
props: {
plugins: null,
texts: null,
enumlocalization: null,
integrationready: null,
},
}
}
... FETCH DATA
const page = Number(query.page) || 0
let stories = await builder.getAll('barion-userstory-data', {
options: {
noTargeting: true,
// sort: { //TODO ADD SORTING ALPHABETICALLY
// 'data.title': 1,
// },
offset: page * articlesPerPage,
},
limit: articlesPerPage * 3,
omit: 'data.blocks',
})
...
return {
stories,
tophero,
bottomhero,
texts: texts?.data.texts[locale],
enumlocalization: enumlocalization.data,
page,
navbar,
footer,
subfooter,
}
}
export default CustomerStories
I have the following synchronism problem. Given that I know that the React useState hook is asynchronous, I run into the following: I'm downloading some images from Amazon S3, I manage to save it correctly in my hook: defaultSelfiePicture and depending on the weight of the image (or so I think) sometimes I get the images loaded correctly and sometimes not. I have tried to force state changes after I finish saving the object in my hook but it never renders the image, only if I change component and come back is when it is shown in the cases that it takes longer to load.
const [defaultSelfiePictures, setDefaultSelfiePictures] = useState([])
useEffect(() => {
if (savedUser.docs !== undefined) {
loadAllPictures()
}
}, [savedUser.docs.length])
const loadAllPictures = () => {
let p1 = loadUrlDefaultFrontPictures()
let p2 = loadUrlDefaultBackPictures()
let p3 = loadUrlDefaultSelfiePictures()
Promise.all([p1, p2, p3]).then(result => {
console.log('end all promises')
setTimestamp(Date.now())
})
}
const loadUrlDefaultSelfiePictures = async () => {
if (savedUser.docs.length > 0) {
let readedPictures = []
for (let i = 0; i < savedUser.docs.length; i++) {
if (
savedUser.docs[i].type === 'SELFIE'
//&& savedUser.docs[i].side === 'FRONT'
) {
if (
savedUser.docs[i].s3Href !== null &&
savedUser.docs[i].s3Href !== undefined
) {
const paramsKeyArray =
savedUser.docs[i].s3Href.split('')
let paramsKey = paramsKeyArray.pop()
let params = {
Bucket: process.env.REACT_APP_S3_BUCKET,
Key: paramsKey
}
await s3.getSignedUrl('getObject', params, function (err, url) {
readedPictures.push({
idKycDoc: savedUser.docs[i].idKycDoc,
name: 'selfie.jpeg',
type: savedUser.docs[i].type,
url: url
})
})
} else {
let urlPicture = savedUser.docs[i].localHref
let response = await axios.get(`${URL_IMG}${urlPicture}`, {
responseType: 'blob'
})
function readAsDataURL(data) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(data)
reader.onloadend = () => {
resolve(reader.result)
}
})
}
const base64Data = await readAsDataURL(response.data)
readedPictures.push({
idKycDoc: savedUser.docs[i].idKycDoc,
name: 'selfie.jpeg',
type: savedUser.docs[i].type,
url: `data:image/jpeg;base64,${base64Data.slice(21)}`
})
}
}
}
setDefaultSelfiePictures(readedPictures)
}
}
And I obtain this :
I can see that the hook has content, but that content is not updated until the next rendering of the component, also if I try to make any changes when I detect that the .length has changed it tells me that it is 0...
And right after the next render I get this:
I have hosted a peer to peer meeting react app on netlify. I have used Peerjs for my video purpose. Everything is working as expected except the video. For some networks the video of the the remote person is working and for some others it is not working. I looked up and found out that it may be a STUN/TURN issue. I then implemented all the STUN/TURN servers in my code. However the video is still not getting setup in some cases. In some cases it is working fine, in others the video is not showing up. Herewith, I am attaching th code for the video and the link to the site.
import React,{useEffect,useState} from 'react';
import {io} from "socket.io-client";
import {useParams} from 'react-router-dom';
import {Grid} from "#material-ui/core";
import Peer from 'peerjs';
var connectionOptions = {
"force new connection" : true,
"reconnectionAttempts": "Infinity",
"timeout" : 10000,
"transports" : ["websocket"]
};
const Videobox = ({isVideoMute,isAudioMute}) => {
var myPeer = new Peer(
{
config: {'iceServers': [
{urls:'stun:stun01.sipphone.com'},
{urls:'stun:stun.ekiga.net'},
{urls:'stun:stun.fwdnet.net'},
{urls:'stun:stun.ideasip.com'},
{urls:'stun:stun.iptel.org'},
{urls:'stun:stun.rixtelecom.se'},
{urls:'stun:stun.schlund.de'},
{urls:'stun:stun.l.google.com:19302'},
{urls:'stun:stun1.l.google.com:19302'},
{urls:'stun:stun2.l.google.com:19302'},
{urls:'stun:stun3.l.google.com:19302'},
{urls:'stun:stun4.l.google.com:19302'},
{urls:'stun:stunserver.org'},
{urls:'stun:stun.softjoys.com'},
{urls:'stun:stun.voiparound.com'},
{urls:'stun:stun.voipbuster.com'},
{urls:'stun:stun.voipstunt.com'},
{urls:'stun:stun.voxgratia.org'},
{urls:'stun:stun.xten.com'},
{
urls: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: 'webrtc#live.com'
},
{
urls: 'turn:192.158.29.39:3478?transport=udp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
},
{
urls: 'turn:192.158.29.39:3478?transport=tcp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
}
]} /* Sample servers, please use appropriate ones */
}
);
const peers = {}
const [socket, setSocket] = useState()
const {id:videoId} = useParams();
const videoGrid = document.getElementById('video-grid')
useEffect(()=> {
const s=io("https://weconnectbackend.herokuapp.com",connectionOptions);
setSocket(s);
return () => {
s.disconnect();
}
},[])
// let myVideoStream;
const [myVideoStream, setmyVideoStream] = useState()
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
//setUnmuteButton();
} else {
//setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
const playStop = () => {
//console.log('object')
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
//setPlayVideo()
} else {
//setStopVideo()
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
useEffect(() => {
if(myVideoStream)
playStop()
}, [isVideoMute])
useEffect(() => {
if(myVideoStream)
muteUnmute()
}, [isAudioMute])
useEffect(() => {
if(socket== null)
return;
myPeer.on('open',id=>{
socket.emit('join-room',videoId,id);
})
const myVideo = document.createElement('video')
myVideo.muted = true
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
// myVideoStream = stream;
window.localStream=stream;
setmyVideoStream(stream);
console.log(myVideoStream,"myvideostream");
addVideoStream(myVideo, stream)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected',userId =>{
connectToNewUser(userId, stream)
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
})
}, [socket,videoId])
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
return (
<div id="video-grid" className="videoStyleFromDiv">
{/* <Video srcObject={srcObject}/> */}
</div>
)
}
export default Videobox
Website Link
The TURN servers you are using have been out of commission for a couple of years in the case of the ones taken from https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/
Copying credentials from random places is not how TURN works, you will need to run your own servers.
I have the following situation: when executing a change on select I am firing a function that goes to an API and performs a search. The result of this search is a JSON. After executing the search I am trying to get some specific ids, however in my component I am not able to access them.
I'm a beginner, I apologize for mistakes and lack of standards.
Here's my code where I run the #change on page:
<select v-if="users.items" v-model="usuarioId" #change="getById(usuarioId)">
<option value="" disabled selected>Escolha um Usuário</option>
<option v-for="user in users.items" :key="user.id" :value="user.id">{{user.nome}}</option>
</select>
GetById in Module:
import { usuarioSistemaService } from '../_services';
const state = {
all: {}
};
const actions = {
getById({ commit }, id){
commit('getByIdRequest', id);
usuarioSistemaService.getById(id)
.then(
usuarioSistemas => commit('getByIdSuccess', usuarioSistemas),
error => commit('getByIdFailure', error)
);
}
};
const mutations = {
getByIdRequest(state) {
state.all = { loading: true };
},
getByIdSuccess(state, usuarioSistemas) {
state.all = { items: usuarioSistemas };
},
getByIdFailure(state, error) {
state.all = { error };
}
};
export const usuarioSistemas = {
namespaced: true,
state,
actions,
mutations
};
GetById in Service:
function getById(id) {
const requestOptions = {
method: 'GET',
headers: authHeader()
};
return fetch(`${config.apiUrl}/usuariosistema/${id}`, requestOptions).then(handleResponse);
}
function handleResponse(response) {
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
if (response.status === 401) {
// auto logout if 401 response returned from api
logout();
location.reload(true);
}
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
}
With the result I want to insert data (usuarioSistema.sistemaId) into this array -> systemId:
<script>
import { mapState, mapActions } from 'vuex'
export default {
data () {
return {
usuarioId: '',
sistemaId: [],
}
}
}
I tried to create a javascript function in "methods:" for this, but the object always comes empty. I also tried to create something invisible on the page to feed this array, but it did not work.
Could you help me, please?
Thanks
You can access store data in a component via the computed object and Vuex's mapGetters helper function:
https://vuex.vuejs.org/guide/getters.html#the-mapgetters-helper
Assuming that you have already performed the API call, you can do it like this in your component:
computed: {
...mapGetters({
'usuarioSistemas': 'usuarioSistemas/all'
})
}
In the code, you should able to access it via this.usuarioSistemas (it is an alias for usuarioSistemas/all).