Error in uploading marks Expected string but received array - javascript

I have a school management project, and in the "UploadMarks" tab, when I click on the button to send the form with the students attendance, the error "Error in uploading marks Expected string but received array", I've heard that it's a problem with lib validator for validations, but I canĀ“t resolve this error.
uploadMarks:
const Validator = require('validator');
const isEmpty = require('./is-empty');
const validateFacultyUploadMarks = (data) => {
let errors = {}
data.subjectCode = !isEmpty(data.subjectCode) ? data.subjectCode : '';
data.exam = !isEmpty(data.exam) ? data.exam : '';
data.totalMarks = !isEmpty(data.totalMarks) ? data.totalMarks : '';
if (Validator.isEmpty(data.subjectCode)) {
errors.subjectCode = 'Subject Code field is required';
}
if (Validator.isEmpty(data.exam)) {
errors.exam = 'Exam field is required';
}
if (Validator.isEmpty(data.totalMarks)) {
errors.totalMarks = 'Total marks field is required';
}
return {
errors,
isValid: isEmpty(errors)
};
}
module.exports = validateFacultyUploadMarks
teacherController:
uploadMarks: async (req, res, next) => {
try {
const { errors, isValid } = validateFacultyUploadMarks(req.body);
// Check Validation
if (!isValid) {
return res.status(400).json(errors);
}
const {exam, totalMarks, marks, department, year } = req.body
const isAlready = await Mark.find({ exam, department})
if (isAlready.length !== 0) {
errors.exam = "You have already uploaded marks of given exam"
return res.status(400).json(errors);
}
for (var i = 0; i < marks.length; i++) {
const newMarks = await new Mark({
student: marks[i]._id,
exam,
department,
marks: marks[i].value,
totalMarks
})
await newMarks.save()
}
res.status(200).json({message:"Marks uploaded successfully"})
}
catch (err) {
console.log("Error in uploading marks",err.message)
}
},
is-Empty:
const isEmpty = value =>
value === undefined ||
value === null ||
(typeof value === 'object' && Object.keys(value).length === 0) ||
(typeof value === 'string' && value.trim().length === 0);
module.exports = isEmpty;

Related

Empty string handling in nodeJs or Javascript

I write below code for handling empty string and get the data
DB image
In this image we need to show data behalf of Program column. If Project column and Slug(from project) column have empty data then it will show Program's field 'CIL' and 'OSI'.
I was write below code
//this is database code
// file db.js
const findNews = async () =>
new Promise((resolve, reject) => {
const news = [];
if (!base) {
base = new Airtable().base(process.env.AIRTABLE_BASE);
}
base(tables.news)
.select({})
.eachPage(
(records, fetchNextPage) => {
records.forEach(record => {
const slugField = record.get('Slug (from Project)') || "";
news.push({
description: record.get('Description'),
date: record.get('Date') || "",
project: slugField[0] || "",
program: record.get('Program'),
link: record.get('External Link') || "",
});
});
fetchNextPage();
},
err => {
if (err) {
reject(new Error(err)); // Airtable returns an object here (vs an Error)
} else {
resolve(news);
}
}
);
});
Controllers code
async news(ctx) {
const { role, displayCatalog } = strapi.cache.users[ctx.state.user.email];
const allNews = strapi.cache.news.filter(fields => {
return (
(fields.program === null ||
fields.project === null ||
fields.link === null ||
fields.description === null ||
fields.date === null) &&
(fields !== null || fields !== undefined) &&
fields.program.includes(programFromRole(role))
);
});
const news = strapi.cache.news.filter(
neww => neww.program.includes(programFromRole(role)) && displayCatalog.includes(neww.project)
);
const newsData = news.concat(allNews);
return buildResponse(newsData);
},
This code runnable but in db.js file I used for sending empty string as "" but this approach is not good.
could you please help me out of problem?

How to skip undefined/missing values in key-value pairs

I'm trying to build a citation generator from json in an API with data about images, stored in key-value pairs. I can get the data to return to the screen, but it always includes undefined in the citation. Sample manifest returns undefined as the creator since that isn't listed in this particular record. How can I keep any undefined value from being returned? I've tried changing the forEach to map, filtering at allMetadata by string length, using if !== undefined at insertCitation, and versions of those in different spots in the code.
EDIT: updated to provide full code, including print to page
(function () {
'use strict';
const buildCitation = {
buildMetadataObject: async function (collAlias, itemID) {
let response = await fetch('/iiif/info/' + collAlias + '/' + itemID + '/manifest.json');
let data = await response.json()
let allMetadata = data.metadata
let citationData = {};
allMetadata.forEach(function (kvpair) {
if (kvpair.value == undefined) {
return false;
} else if (kvpair.label === 'Title') {
citationData.itemTitle = kvpair.value;
} else if (kvpair.label === 'Creator') {
citationData.itemCreator = kvpair.value;
} else if (kvpair.label === 'Repository') {
citationData.itemRepository = kvpair.value;
} else if (kvpair.label === 'Collection Name') {
citationData.itemCollection = kvpair.value;
} else if (kvpair.label === 'Owning Institution') {
citationData.itemOwning = kvpair.value;
} else if (kvpair.label === 'Date') {
citationData.itemDate = kvpair.value;
} else if (kvpair.label === 'Storage Location') {
citationData.itemStorage = kvpair.value;
}
return true;
});
return citationData;
},
insertCitation: function (data) {
var testTitle = data.itemTitle;
console.log(testTitle);
const itemCite = `Citation: "${data.itemTitle}," ${data.itemDate}, ${data.itemCreator}, ${data.itemCollection}, ${data.itemOwning}, ${data.itemStorage}, ${data.itemRepository}.`;
const citationContainer = document.createElement('div');
citationContainer.id = 'citation';
citationContainer.innerHTML = itemCite;
// CHANGED to innerHTML instead of innerText because you may want to format it at some point as HTML code.
if (testTitle) {
document.querySelector('.ItemView-itemViewContainer').appendChild(citationContainer);
}
}
}
document.addEventListener('cdm-item-page:ready', async function (e) {
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
document.addEventListener('cdm-item-page:update', async function (e) {
document.getElementById('citation').remove();
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
})();
I've simplified your program. The undefined is coming from the fact that there is no item with label Date
const mappings = {
Date: 'itemDate',
Title: 'itemTitle',
Creator: 'itemCreator',
Repository: 'itemRepository',
'Storage Location': 'itemStorage',
'Owning Institution': 'itemOwning',
'Collection Name': 'itemCollection',
}
async function buildMetadataObject(collAlias, itemID) {
let response = await fetch('https://teva.contentdm.oclc.org/iiif/info/p15138coll25/1421/manifest.json');
let data = await response.json()
return data.metadata.reduce(
(acc, { label, value }) => ({ ...acc, [ mappings[label] ]: value }),
{}
)
}
function insertCitation(data) {
var testTitle = data.itemTitle;
const fieldBlackList = ['itemTitle'];
const itemCite = `Citation: "${data.itemTitle}," ${
Object.values(mappings).reduce((acc, cur) => {
if (fieldBlackList.includes(cur)) return acc;
const value = data[cur];
return value ? [...acc, value] : acc
}, []).join(', ')
}.`;
console.log(itemCite);
}
//MAIN PROGRAM
(async() => {
const citationData = await buildMetadataObject();
insertCitation(citationData);
})()

Axios post request not running in sequence

I am trying to make use of async series correctly but unable to figure how exactly i need to send the data into it for it to move forward with each post request in exactly the same way as it is getting data.
I have an excel file in which i am getting multiple statuses to mark against each ids that are present in the first column. Also there are statuses that need to be deleted and deleting part is not that difficult and i was able to do it without making use of async series but for posting new records I need to make use of async series. The records to be posted are under the columns 'Mark Status 1', 'Mark Status 1 Date', 'Mark Status 2' and so on. So i wrote a script to fetch the records using a for loop and send them off to a function and that function is responsible for modelling data for asyn series. Inside the markStatusCall function if i put a forEach loop and run the call the sequence of the statuses become wrong. It should be like 'Marks Status 1 value', 'Mark Status 2 value' and so on.
I am attaching my code here, please take a look below and to see the excel file here
const Excel = require("exceljs");
const axios = require("axios").default;
const https = require("https");
const _async = require("async");
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
});
const returnedId = "5dd7fa20dcfa9600152cc2de";
const deliveredId = "5dd7fa20dcfa9600152cc2d3";
const returnedByVendorId = "5de7c418362e13001212f238";
const returnedToVendor = "5eb2ebfe02987816aad14269";
const atSwyftWarehouse = "5dd7fa20dcfa9600152cc2d8";
const reAttempted = "5e6ea5d87aa7bb6d726b2bbc";
const requestToReattempt = "5ee134230138634c27a6e1da";
const dispatched = "5dd7fa20dcfa9600152cc2e2";
const parcelAssignedDelivery = "5dd7fa20dcfa9600152cc2e3";
const cancelledByVendor = "5de7c418362e13001212f238";
var workbook = new Excel.Workbook();
workbook.xlsx.readFile("./1.xlsx").then(async function () {
// use workbook
var worksheet = workbook.getWorksheet("Interim");
const parcelIds = [];
const status = [];
const date = [];
var data = [];
var finalData = [];
for (let i = 2; i <= 10; i++) {
worksheet.getRow(i).eachCell((cell, index) => {
if (cell.value !== "") {
worksheet.getColumn(index).eachCell((colCell, indexing) => {
if (indexing === 1) {
if (colCell.value === "Delete Status 1") {
deleteData(i, cell);
} else if (colCell.value === "Delete Status 2") {
deleteData(i, cell);
} else if (colCell.value === "Delete Status 3") {
deleteData(i, cell);
} else if (colCell.value === "Delete Status 4") {
deleteData(i, cell);
} else if (colCell.value === "Delete Status 5") {
deleteData(i, cell);
} else if (colCell.value === "Mark Status 1") {
markData(i, index, cell);
} else if (colCell.value === "Mark Status 2") {
markData(i, index, cell);
} else if (colCell.value === "Mark Status 3") {
markData(i, index, cell);
} else if (colCell.value === "Mark Status 4") {
markData(i, index, cell);
} else if (colCell.value === "Mark Status 5") {
markData(i, index, cell);
}
}
});
}
});
}
function markData(i, index, cell) {
let row = worksheet.getRow(i);
let date = row.getCell(index + 1).value;
let parcelId = row.getCell(1).value;
if (cell.value !== "" && date !== "") {
let statusId =
cell.value === "At Swyft Warehouse"
? atSwyftWarehouse
: cell.value === "Dispatched"
? dispatched
: cell.value === "Reattempted"
? reAttempted
: cell.value === "Delivered"
? deliveredId
: cell.value === "Cancelled"
? returnedId
: cell.value === "Request for Reattempt"
? requestToReattempt
: cell.value === "Parcel Assigned"
? parcelAssignedDelivery
: cell.value === "Cancelled by Vendor"
? cancelledByVendor
: deliveredId;
console.log(parcelId, statusId, date);
addStatus(parcelId, statusId, date);
}
}
// Need help from here
function addStatus(parcelId, statusId, date) {
let values = {
parcelId: parcelId,
statusRepositoryId: statusId,
createdAt: date,
updatedByScript: true,
};
data.push(values);
}
finalData.push(() => markStatusCall(data));
_async.series(finalData, (err, data) => {
if (err) {
console.log(err);
}
});
async function markStatusCall(values) {
console.log(values, "Came here");
values.forEach((data) => {
try {
let response = await instance.post(
"https://api.myDomain.com:3000/api/ParcelStatuses",
{
parcelId: data.parcelId,
statusRepositoryId: data.statusRepositoryId,
createdAt: data.createdAt,
updatedByScript: data.updatedByScript,
}
);
console.log("Updated");
} catch (err) {
console.log("here");
console.error(err);
}
})
}
Would something like this work:
async function markStatusCall(values) {
console.log(values, "markStatusCall begin");
function loop(values, index) {
console.log('loop at index', index);
const data = {
parcelId: data.parcelId,
statusRepositoryId: data.statusRepositoryId,
createdAt: data.createdAt,
updatedByScript: data.updatedByScript};
try {
let response = await instance.post("https://api.myDomain.com:3000/api/ParcelStatuses", data);
console.log("Updated");
if (index <= (values.length -1)) {
loop(index + 1);
} else {
return;
}
} catch (err) {
console.log("Error");
console.error(err);
}
}
await loop(values, 0);
}
The idea is that the loop waits for each POST request before moving onto the next item in the values array. (might be some typos in the code above).
See this example on codepen
Try doing something like this
function markStatusCall(values) {
let promises=[];
values.forEach((data) => {
const promise = instance.post(
"https://api.myDomain.com:3000/api/ParcelStatuses",
{
parcelId: data.parcelId,
statusRepositoryId: data.statusRepositoryId,
createdAt: data.createdAt,
updatedByScript: data.updatedByScript,
});
return promises.push(promise);
})
Promise.all(promises).then(() => {
console.log('success')
}).catch(error => {
console.error(error.message)
});
}
This can still not ensure your order but it's highly recommended to use promises than async-await
The order of response will follow your order only if the latency for all the responses are same

Nodejs - Express - Best practice to handle optional query-string parameters in API

I want to make a API which have 5 optional query parameters, I want to know if there is a better way to handle this, right now I check each one of them with if conditions, which is kind of dirty! is there any way that I can handle all scenarios without using lot's of if conditions?
let songName = req.query.songName
let singerName = req.query.singerName
let albumName = req.query.albumName
let publishDate = req.query.publishDate
if(songName && singerName && albumName && publishDate) {
const response = songs.filter(c => {
return c.songName === songName && c.singerName === singerName && c.albumName === albumName && c.publishDate === publishDate
}
res.send({
"Data" : response
})
}
if(songName && singerName && albumName && !publishDate) {
const response = songs.filter(c => {
return c.songName === songName && c.singerName === singerName && c.albumName === albumName
}
res.send({
"Data" : response
})
}
if(songName && singerName && !albumName && publishDate) {
const response = songs.filter(c => {
return c.songName === songName && c.singerName === singerName && c.publishDate === publishDate
}
res.send({
"Data" : response
})
}
if(songName && !singerName && albumName && publishDate) {
const response = songs.filter(c => {
return c.songName === songName && c.albumName === albumName && c.publishDate === publishDate
}
res.send({
"Data" : response
})
}
if(!songName && singerName && albumName && publishDate) {
const response = songs.filter(c => {
return c.singerName === singerName && c.albumName === albumName && c.publishDate === publishDate
}
res.send({
"Data" : response
})
}
.
.
.
You could use the ternary operator to do this all in one query. If the parameter is defined you check for equality and else you just return true. This could look like this:
const response = songs.filter(c => {
return (songName ? (c.songName === songName) : true) &&
(singerName ? (c.singerName === singerName) : true) &&
(albumName ? (c.albumName === albumName) : true);
});
res.send({
"Data": response
})
I may find Lodash to be useful for this one:
const response = songs.filter(song => {
return _.isEqual(req.query, _.pick(song, Object.keys(req.query)))
})
I suggest you to use Joi
It is very powerful library for javascript validations. You can make even conditional validations using it. See the complete docs.
I created basic schema for your scenario here.
// validation
const schema = Joi.object().keys({
songName: Joi.string()
singerName: Joi.string()
albumName: Joi.string()
publishDate: Joi.date()
});
const { error, value } = Joi.validate(req.query, schema, { abortEarly: false, allowUnknown: false });
if (error !== null) return res.send(400, { code: 400, message: "validation error", error: error.details });
It is easier to read and understand for other developers too. You can standardized the validations in the overall project.

Add data to firebase and redirect to other page simultaneously

I am creating a website with login/signUp feature with Firebase, the problem is that when User Creates a new Account I want to redirect him to the homepage and put his name in firebase database simultaneously. The User gets redirected to the homepage and I cannot add data to firebase database
Please Check my Code
signUp.addEventListener('click',() => {
const emailValue = emailField.value;
const passValue = passField.value;
if(emailValue === "" && passValue === "" || emailValue !== "" && passValue == "" || emailValue == "" && passValue !== "")
{
alert('Please fill all fields')
}
else {
const auth = firebase.auth();
const promise = auth.createUserWithEmailAndPassword(emailValue,passValue);
promise
.then(() => {
auth.signInWithEmailAndPassword(emailValue,passValue);
let userId = auth.currentUser.uid;
let dataRef = firebase.database().ref('users/' + userId);
dataRef.set({
name: nameField.value
});
console.log('User Signed In');
return './homepage.html';
})
.then((address) => {
window.location.href = address;
})
.catch(e => {
console.log(e.message);
})
}
});
Thanks In Advance :)
createUserWithEmailAndPassword returns an user object so there is no need to to re-validate credentials. Please try this:
signUp.addEventListener('click', () => {
const emailValue = emailField.value;
const passValue = passField.value;
if (emailValue === "" && passValue === "" || emailValue !== "" && passValue == "" || emailValue == "" && passValue !== "") {
alert('Please fill all fields')
} else {
firebase.auth().createUserWithEmailAndPassword(emailValue, passValue).then(function (user) {
const user_data = {
wo: 0
};
const promise = firebase.app().database().ref(`/users/${user.uid}`).set(user_data);
promise.then(() => {
setTimeout(1000);
window.location.href = './homepage.html';
});
}, function (error) {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorMessage);
});
}
});

Categories