Strapi: React: Cannot read property 'associations' of undefined - reactjs

Currently trying to upload an image and connect it to an existing entry.
The schema of the existing entry is
{
"name": "page rows",
"description": "",
"connection": "default",
"kind": "collectionType",
"collectionName": "page_rows",
"attributes": {
"row": {
"type": "json"
},
"images": {
"type": "media",
"multiple": true,
"required": false,
"allowedTypes": [
"images"
]
}
}
},
and I upload an image using
export const formatEntryUpload = (file, entryModel, entryID, entryField, entryPlugin = null) => {
const entryUpload = new FormData();
entryUpload.append('files', file);
entryUpload.append('ref', entryModel);
entryUpload.append('refId', entryID);
entryUpload.append('field', entryField);
if(entryPlugin) {
entryUpload.append('source', entryPlugin);
}
return entryUpload;
};
where I fill call the function by
formatEntryUpload ( file, "page_rows", id, "images", "users-permissions");
however when I do I get the following error.
[2021-02-07T21:01:35.334Z] error TypeError: Cannot read property 'associations' of undefined
at /srv/app/node_modules/strapi-connector-mongoose/lib/relations.js:250:43
at Array.forEach (<anonymous>)
at /srv/app/node_modules/strapi-connector-mongoose/lib/relations.js:235:20
at Array.reduce (<anonymous>)
at Function.update [as updateRelations] (/srv/app/node_modules/strapi-connector-mongoose/lib/relations.js:97:68)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async Object.add (/srv/app/node_modules/strapi-plugin-upload/services/Upload.js:253:17)
at async Promise.all (index 0)
at async Object.upload (/srv/app/node_modules/strapi-plugin-upload/services/Upload.js:105:12)
at async Object.upload (/srv/app/node_modules/strapi-plugin-upload/controllers/Upload.js:82:18)
at async /srv/app/node_modules/strapi/lib/middlewares/router/utils/routerChecker.js:70:22
at async module.exports (/srv/app/node_modules/strapi-plugin-users-permissions/config/policies/permissions.js:97:3)
at async /srv/app/node_modules/strapi-utils/lib/policy.js:52:5
[2021-02-07T21:01:35.334Z] debug POST /upload (564 ms) 500
The image is successfully uploaded however it is not associated with the entry. What do I need to change to associate the image with the entry?

change "page_rows" to "page_row"
it helped me
formatEntryUpload ( file, "page_rows", id, "images", "users-permissions") =>
formatEntryUpload ( file, "page_row", id, "images", "users-permissions");

Related

How to search for a specific data from a JSON file with array in Cypress?

I appreciate if someone help me in my question.
I need to validate a web page with 3 search fields. Also, I have a json file where I mocked it from the API.
So, I'm trying to type for a specific terminal and check if it works and it is not working. Instead of to show only the terminal number, the list is showing all the data.
I did the same validation with the API service and it worked as expected.
This is my code in Cypress
context('Search validation', () => {
beforeEach(() => {
cy.intercept(
'GET',
'**/mc-extratos/**',
{fixture: 'financeiro/carta-cancelamento'}
).as('verCartas')
cy.visit('/carta-de-cancelamento')
cy.get('[data-cy="consultarCartas"]')
.as('Buscar') // nome do botão
.click()
cy.wait('#verCartas')
})
it('Search by Terminal', () => {
cy.get('#nroTerminal')
.type('05009867')
cy.get('#Buscar').click()
cy.wait('#verCartas')
})
And this is the part of my JSON file.
{"status":
{
"value":"0",
"description":"Requisição efetuada com sucesso."
},
"data": [
{
"id": 0,
"ec": 11111111,
"ecComercio": 900212,
"ecName": "Estabelecimento 01",
"cardMask": "515590XXXXXX0001",
"nsu": "000150297",
"authorization": "011064",
"plan": "0212-parcelado lojista 12x",
"transactionDate": "2022-03-18T00:00:00Z",
"transactionValue": 212,
"cancelDate": "2022-03-28T16:20:23Z",
"cancelValue": 2,
"cancelCode": "00-Transac?o aceita",
"availableValue": 210,
"terminal": "05009867",
"product": "01-MASTERCARD",
"microFilm": null,
"channel": 990888,
"channelName": "Web Manual",
"user": "SISTEMA",
"currency": 986,
"currencyName": "Real",
"filter": null
},
{
"id": 264063,
"ec": 22222222,
"ecComercio": 831416,
"ecName": "Estabelecimento 02",
"cardMask": "515590XXXXXX0001",
"nsu": "852736414",
"authorization": "053768",
"plan": "0203-parcelado lojista 3x",
"transactionDate": "2022-03-03T00:00:00Z",
"transactionValue": 303,
"cancelDate": "2022-03-01T10:44:15Z",
"cancelValue": 303,
"cancelCode": "00-Transac?o aceita",
"availableValue": 0,
"terminal": "D5003826",
"product": "01-MASTERCARD",
"microFilm": "WS",
"channel": 990113,
"channelName": "WEB Service",
"user": "HOST",
"currency": 986,
"currencyName": "Real",
"filter": null
}
]
}
This is the web page where I have to write test in Cypress
You can use the yielded response body from the .wait() command.
cy.wait('#verCartas').then((res) => {
// parse response body and destructure the data array.
const { data } = JSON.parse(res.body)
// iterate through data array
data.forEach((element, index, array) => {
// Any validations you need to run using the data
// You'll probably want to identify the parent container element and select it using `.eq(index)`.
cy.get('.some-parent-container').eq(index).within(() => {
// code
});
});
});
It may be that reusing cy.get('[data-cy="consultarCartas"]') via the alias #Buscar is the problem.
Try using cy.get('[data-cy="consultarCartas"]') directly after setting the filter
it('Search by Terminal', () => {
cy.get('#nroTerminal')
.type('05009867')
cy.get('[data-cy="consultarCartas"]').click()
cy.wait('#verCartas')
cy.contains('tr', 'TERM')
.should('have.length', 1) // confirm filter worked
})

React + fetch: adding extra characters and backslashes to my url

I have this code in React 17
useEffect(() => {
getLocalJson('../json/login/login.json', props.headers)
.then(resp => {
setFields(resp);
});
}, [props.headers]);
And the getLocalJson method is in a different file:
export const getLocalJson = async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
}
However the call to load the local JSON file from the public folder is:
Request URL: http://localhost:3000/json/login/%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5Clogin.json
Ths is the JSON
[
{
"order": 0,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "TITLE"
}
},
{
"order": 1,
"required": true,
"systemName": "username",
"friendlyName": "Username",
"errorMsg": "Invalid username",
"dataType": {
"type": "TEXT"
}
},
{
"order": 2,
"required": true,
"systemName": "password",
"friendlyName": "Password",
"errorMsg": "Invalid password",
"dataType": {
"type": "PASSWORD"
}
},
{
"order": 3,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "BUTTON",
"submit": true
}
}
]
And it makes the call over and over and over
This exact code works on my ubuntu dev box, but is failing as abovw on my windows box
I think there is some issue with the way you are passing down the headers, look into the documentation to have a better idea.
Put your function in the body of your component where you're using useEffect and wrap it with useCallback like this:
const getLocalJson = useCallback( async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
},[])

Next-Auth | When user object have too many items then session request is without data

I will try to explain my problem as best as possible for me.
I'm using Strapi as a backend and Nextjs as a frontend.
For the authentication I using NextAuth.
[...nextauth].js:
const options = {
providers: [
Providers.Credentials({
name: 'Credentials',
credentials: {
username: { label: "Email", type: "email", placeholder: "jsmith" },
password: { label: "Password", type: "password" }
},
authorize: async (credentials) => {
try {
const user = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/local`, {
identifier: credentials.username,
password: credentials.password,
});
if (user.data) {
return user.data
} else {
return null
}
} catch (error) {
const errorMessage = error.response.data.message[0].messages[0].message
throw new Error(errorMessage)
}
}
}),
],
database: process.env.NEXT_PUBLIC_DATABASE_URL,
session: {
jwt: true,
},
callbacks: {
jwt: async (token, user) => {
if (user) {
token.jwt = user.jwt;
token.user = user.user;
}
return Promise.resolve(token);
},
session: async (session, token) => {
session.jwt = token.jwt;
session.user = token.user;
return Promise.resolve(session);
},
},
pages: {
signIn: '/login',
error: '/login'
},
};
const Auth = (req, res) =>
NextAuth(req, res, options);
export default Auth;
When I send form with identifier and password I getting session response with user data and jwt.
Everything working well, but if user objects have few more objects assigned to him, then something goes wrong and the session is empty.
Example:
I creating in Strapi simple collection with just two fields - image field, and owner (relation to user). Every response with image contents few lines:
"photo": {
"_id": "60ca03fa20bd43033a53950e",
"name": "Zrzut ekranu 2021-06-16 o 14.59.48.png",
"alternativeText": "",
"caption": "",
"hash": "Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b",
"ext": ".png",
"mime": "image/png",
"size": 170.69,
"width": 668,
"height": 636,
"url": "/uploads/Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b.png",
"formats": {
"thumbnail": {
"name": "thumbnail_Zrzut ekranu 2021-06-16 o 14.59.48.png",
"hash": "thumbnail_Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b",
"ext": ".png",
"mime": "image/png",
"width": 164,
"height": 156,
"size": 14.92,
"path": null,
"url": "/uploads/thumbnail_Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b.png"
},
"small": {
"name": "small_Zrzut ekranu 2021-06-16 o 14.59.48.png",
"hash": "small_Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b",
"ext": ".png",
"mime": "image/png",
"width": 500,
"height": 476,
"size": 121.79,
"path": null,
"url": "/uploads/small_Zrzut_ekranu_2021_06_16_o_14_59_48_2bc223567b.png"
}
},
When I add 1 or 2 items with image and try to login to user who own that items then everything is fine, I can log in and receive full user object and jwt token.
But when I add 3 items there, session object is empty, and I can't log in. I do not receiving user object and jwt token.
With 3 items
With 2 items
When I using postman, even with 50 items response is good and include full user object and jwt token.
I think is because response is too large or something like that, but I have no clue how to deal with it.
I working on localhost (both - frontend and backend) on MacOS.
Is there anyone who can help me find a solution for that problem?
Kind Regards,
GP
The reason of above issue is that in api response is passed to many data, and next-auth store that all data in JWT, and JWT is stored in full in cookie, cookie is limited to 4096 bytes, and that simply brake that limit and response.
The simplest way to sort it out is to save only most important data in JWT.
You can do that in callback function.

Extracting images data from Promise (ReactJS and Axios)

How do I get access to data stored as a Promise[] in ES6 array? I am loading an array from the backend and each object has a url for the image. So in order to render the image I have to async/await fetch the images for each object. Instead of returning a Base64 image, I get I promise with the image embeded deep in the promise. I need a way to read the image data. See image below for return object structure.
Please note that i use axios in the background and NOT the Fetch API
Below are the functions and service methods used to load the list and then the images in 2 steps.
1.1 Axios service method
listAllItems() {
return axios.get(API_URL + "docman/items/list/all");
}
1.2 ReactJS main function
async componentDidMount() {
try {
const items = await DocmanService.listAllItems();
const itemsData = items.data;
const data = await itemsData.map(item => {
const image = this.loadImage(item.image);
return { ...item, image: image }
})
this.setState({ items: data });
} catch (e) {
console.log(e);
}
}
2.1 Axios images service method
loadImage = (url) => {
return axios.get(API_URL + url, { responseType: 'arraybuffer' });
}
2.2 ReactJS image loader function
async loadImage(imageUrl) {
try {
return await ImageService.loadImage(imageUrl)
} catch (e) {
return '';
}
}
3.1 Json list fetched from backend
[
{
"id": "1",
"uuid": "1c0a33af-4e78-4823-b84e-f3b5464db2af",
"identifier": "EN ISO 8402",
"title": "EN ISO 8402 Quality Management - Vocabulary",
"folder": "e347fef9-0a76-4e62-b7f2-c78e9f88355b",
"media": "FILE",
"path": "document/id/105",
"image": "image/id/106",
"format": "PDF",
"authors": "",
"publishers": "",
"created": "2020-09-22T14:56:31.316+00:00",
"published": null,
"version": "1994",
"status": null
},
{
"id": "2",
"uuid": "16a0e658-b444-4b60-bf18-ba2786d5fb00",
"identifier": "ISO 14001",
"title": "ISO 14001 Environmenatl Management Systems - Requirements with Guidance for Use",
"folder": "e347fef9-0a76-4e62-b7f2-c78e9f88355b",
"media": "FILE",
"path": "document/id/107",
"image": "image/id/108",
"format": "PDF",
"authors": "",
"publishers": "",
"created": "2020-09-22T14:56:31.659+00:00",
"published": null,
"version": "2004",
"status": null
},
-
-
]
try doing image.then((data) => { // console.log(data) })
When you setState you are setting the new state with a list of objects with an image value that is a promise. Shouldn't you update the state only when at least one of the promise resolved to a real image?
Couldn't you do something like
this.loadImage(item.image).then((imageData=>setState(appropriate State)))?

Axios send strange array to React

I geting the data back from my API in React from a post request and I get just the first object of the entire Array.prototype
My API for the upload:
router.post("/uploads", upload.any(), async (req, res) => {
try {
if (!req.files) {
res.send({
status: false,
message: "No file uploaded",
});
} else {
let data = req.files;
res.send({
status: true,
message: "Files are uploaded",
data: data,
});
}
} catch (error) {
res.status(500).send(err);
}
});
POSTMAN gives me back:
{
"status": true,
"message": "Files are uploaded",
"data": [
{
"fieldname": "uploads\n",
"originalname": "46335256.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "client/uploads/",
"filename": "46335256-2020-08-04.jpg",
"path": "client/uploads/46335256-2020-08-04.jpg",
"size": 19379
},
{
"fieldname": "uploads\n",
"originalname": "120360358.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "client/uploads/",
"filename": "120360358-2020-08-04.jpg",
"path": "client/uploads/120360358-2020-08-04.jpg",
"size": 78075
}
]
}
perfect!
this is my function in React to upload
const uploadFiles = () => {
uploadModalRef.current.style.display = "block"
uploadRef.current.innerHTML = "File(s) Uploading..."
for (let i = 0; i < validFiles.length; i++) {
const formData = new FormData()
formData.append("images", validFiles[i])
axios
.post("http://localhost:5000/api/db/uploads", formData, {
onUploadProgress: progressEvent => {
const uploadPercentage = Math.floor(
(progressEvent.loaded / progressEvent.total) * 100
)
...// code for graphic upload
},
})
.then(resp => {
console.log(resp.data.data)
resp.data.data.map(item => {
console.log(item)
})
})
.catch(() => {
... // code
}
}
and with this I get (from the console):
[{…}]
0:
destination: "client/uploads/"
encoding: "7bit"
fieldname: "images"
filename: "46335256-2020-08-04.jpg"
mimetype: "image/jpeg"
originalname: "46335256.jpg"
path: "client/uploads/46335256-2020-08-04.jpg"
size: 19379
__proto__: Object
length: 1
__proto__: Array(0)
is an array(if I map it works) but with just the first object.
How is it possible ??
I tried even with async/await but nothing changes
Where I'm mistaking?
Thanks!

Resources