So in below code if i pass ancillaryProductInd as boolean code works, but when I pass it as a string, it does not work. In my understanding the below code should only work when I pass "false" string value and throw error on boolean. Any idea what is the issue here ?
main.ts
request
var rxInfos = [{
"ancillaryProductInd": "false",
"indexID": "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}]
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach((rxInfo) => {
const subQuestion = {
question: []
};
if (rxInfo.ancillaryProductInd !== undefined && rxInfo.ancillaryProductInd === "false") {
subQuestion.question = data;
subQuestionArray.push(subQuestion);
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [{
some data
}]);
Your example code works as expected with a string value "false" and doesnt run the if block when a boolean is used. See my example:
var rxInfos = [
{
ancillaryProductInd: "false",
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
},
{
ancillaryProductInd: false,
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}
];
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach(rxInfo => {
const subQuestion = {
question: []
};
if (
rxInfo.ancillaryProductInd !== undefined &&
rxInfo.ancillaryProductInd === "false"
) {
console.log("no error");
subQuestion.question = data;
subQuestionArray.push(subQuestion);
} else {
console.log("throw error");
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [
{
test: ""
}
]);
Related
I've got this object as example:
const obj = {
group: {
data: {
data: [
{
id: null,
value: 'someValue',
data: 'someData'
}
]
}
}
};
My goal is to get a value by propery name.
In this case I would like to get
the value of the data propery, but the last appearance of it.
Meaning the expected output is:
someData
However, I'm using this recursive function to retreive it:
const findVal = (obj, propertyToExtract) => {
if (obj && obj[propertyToExtract]) return obj[propertyToExtract];
for (let key in obj) {
if (typeof obj[key] === 'object') {
const value = findVal(obj[key], propertyToExtract);
if (value) return value;
}
}
return false;
};
Which gives me the first appearance of data, meaning:
data: [
{
value: 'someValue',
data: 'someData'
}
]
How can I get the wanted result?
one way can be to recursively flat the object and just get the wanted index (here data)
const obj = {
group: {
data: {
data: [
{
id: null,
value: 'someValue',
data: 'someData'
}
]
}
}
};
function deepFlat(obj) {
let flatObj = {};
flat(obj,flatObj);
console.log(flatObj);
return flatObj;
}
function flat(toFlat, flatObj) {
Object.entries(toFlat).forEach(elem => {
if (elem[1] && typeof elem[1] === 'object') {
flat(elem[1], flatObj);
} else {
flatObj[elem[0]] = elem[1];
}
});
}
let result = deepFlat(obj);
console.log(result['data']);
let response = {};
var filters = {
topfeaturedandotherfields: req.body.topfeaturedandotherfields,
};
if (req.body.minprice && req.body.maxprice && req.body.brandName) {
var filters = {
$and: [
{ brandName: { $in: req.body.brandName } },
{ topfeaturedandotherfields: req.body.topfeaturedandotherfields },
{ salePrice: { $gte: req.body.minprice, $lte: req.body.maxprice } },
],
};
var result = await productService.getAllProductofhomepage(
filters,
req.body.ordername,
req.body.orderby
);
} else {
if (req.body.minprice && req.body.maxprice) {
var filters = {
$and: [
{ topfeaturedandotherfields: req.body.topfeaturedandotherfields },
{ salePrice: { $gte: req.body.minprice, $lte: req.body.maxprice } },
],
};
var result = await productService.getAllProductofhomepage(
filters,
req.body.ordername,
req.body.orderby
);
}
if (req.body.brandName) {
var filters = {
$and: [
{ brandName: { $in: req.body.brandName } },
{ topfeaturedandotherfields: req.body.topfeaturedandotherfields },
],
};
var result = await productService.getAllProductofhomepage(
filters,
req.body.ordername,
req.body.orderby
);
}
}
if (req.body.limit == true)
var result = await productService.getAllProductofhomepagewithlimit(filters);
else if (req.body.minprice || req.body.maxprice || req.body.brandName) {
} else {
var result = await productService.getAllProductofhomepage(
filters,
req.body.ordername,
req.body.orderby
);
}
if (result.length > 0) {
response = {
message: "Home page products successfully retrieved",
error: false,
data: result,
};
} else {
response = {
message: "Faild to get products",
error: true,
data: {},
};
}
res.status(200).json(response);
This code is used to filter like to see top feature and bestseller or min and max price and the brand name also in this code sort by order name which could be price or brand name or category also in ascending and descending order so now you can see this code is like if and else but I want to optimize and reduce code
You can make this query quite a lot nicer by just dynamically building the query condition instead of breaking the logic into if/else blocks:
export async function login(req: Request, res: Response): Promise<void> {
const response = {};
let filters = {
topfeaturedandotherfields: req.body.topfeaturedandotherfields,
};
if (req.body.minprice || req.body.maxprice) {
const saleCond = { };
if (req.body.minprice) {
saleCond.$gte = req.body.minprice;
}
if (req.body.maxprice) {
saleCond.$lte = req.body.maxprice;
}
filters.salePrice = saleCond
}
if (req.body.brandName) {
filters.brandName = {$in: req.body.brandName}
}
let result = [];
if (req.body.limit == true) {
result = await productService.getAllProductofhomepagewithlimit(filters)
} else {
result = await productService.getAllProductofhomepage(filters, req.body.ordername, req.body.orderby);
}
res.status(200).json({
message: result.length ? 'Home page products successfully retrieved' : 'Failed to get products',
error: result.length === 0,
data: result,
});
}
Not only is this much clearer we only removed a redundant DB call that was made in the process.
So the goal is to have included only those endpoints (and its methods e.g. get, post...) which are defined in the configuration file.
Example structure object that holds all the endpoints.
et swaggerApis = {
header: {
propertyHeader: "valueHeader"
},
blocks: [
{
tags: ["Tenant & User"],
paths: {
"/tenants": {
post: {
property: "value"
},
get: {
property: "value"
}
},
"/tenants/{id}": {
post: {
property: "value"
},
get: {
property: "value"
},
delete: {
property: "value"
}
}
}
}
]
};
Example of the configuration file that holds only those endpoints and its methods we want to have included in the final object.
const CONFIG = {
api: {
include: {
"/tenants/{id}": ["get"]
}
}
};
So far here is my second version of the JavaScript code that works but introduces a high cyclometric complexity and is hard to read. I'm pretty new to JavaScript and looking a way not just to improve this code.
function includeEnpointsByConfig(data) {
for (let blockItem of data.blocks) {
for (let path in blockItem.paths) { //console.log(blockItem.paths[path])
let result = setMethodsOfEndpoint(path, blockItem.paths[path]);
if (result === 'undefined') {
delete blockItem.paths[path] // if the config does not contain, remove
} else {
blockItem.paths[path] = result;
}
}
}
return data;
}
function setMethodsOfEndpoint(path, value) {
let newMethods = {};
for (let confPath in CONFIG.api.include) {
if (path === confPath) { // match endpoint in config and swaggerApis object
if (CONFIG.api.include[confPath].length > 0) { // if array in config is not empty , filter
for (let c of CONFIG.api.include[confPath]) { //console.log(c); // get
for (let v in value) {// properties of object tenants/{id} => {get{}, post{}}
if (v === c) {
newMethods = { ...newMethods, [v]: value[v] };
}
}
}
} else {// if array in config is empty , return param "value" from setMethodsOfEndpoint so we will include all methods of endpoint
return value;
}
} else {
return 'undefined'
}
}
if (Object.keys(newMethods).length !==0) { // if in the config is in the array (nothing that match with swaggerEndpoints e.g. typo get --> gte)
return newMethods
} else {
return value;
}
}
console.log(includeEnpointsByConfig(swaggerApis));
Code can be found also here
https://codesandbox.io/s/blazing-worker-1emzl?file=/src/index2.js
I believe there is a way to do it much easier, cleaner and more effective.
Thank you
With some creative usage of Array.prototype.forEach(), Object.keys() and Object.entries():
swaggerApis.blocks.forEach(block => {
Object.entries(block.paths).forEach(([path, methods]) => {
if (!CONFIG.api.include[path]) {
delete block.paths[path];
} else {
Object.keys(methods).forEach(method => {
if (!CONFIG.api.include[path].includes(method)) {
delete methods[method];
}
});
}
});
});
Complete snippet:
const swaggerApis = {
header: {
propertyHeader: "valueHeader"
},
blocks: [
{
tags: ["Tenant & User"],
paths: {
"/tenants": {
post: {
property: "value"
},
get: {
property: "value"
}
},
"/tenants/{id}": {
post: {
property: "value"
},
get: {
property: "value"
},
delete: {
property: "value"
}
}
}
}
]
};
const CONFIG = {
api: {
include: {
"/tenants/{id}": ["get"]
}
}
};
swaggerApis.blocks.forEach(block => {
Object.entries(block.paths).forEach(([path, methods]) => {
if (!CONFIG.api.include[path]) {
delete block.paths[path];
} else {
Object.keys(methods).forEach(method => {
if (!CONFIG.api.include[path].includes(method)) {
delete methods[method];
}
});
}
});
});
console.log(swaggerApis);
Object.keys(data).forEach((key) => {
bannerData[key] = data[key][0];
console.log(key);
if (key == "timestamp") {
labels.push(data[key]);
console.log("wtf");
console.log(labels);
} else {
datasets.push(data[key]);
}
});
generates
exhaust_humidity
exhaust_temperature
intake_humidity
intake_temperature
lights
relay
room_humidity
room_temperature
soil_moisture_1
soil_moisture_2
soil_moisture_3
soil_moisture_4
soil_moisture_5
soil_moisture_6
soil_moisture_7
soil_moisture_8
timestamp
the console.log("wtf"); is never called, because the last key never registers as equal to "timestamp".
Not sure what I'm missing.
const data = {
not_timestamp: 1,
timestamp: 2,
}
const bannerData = {}
const datasets = []
const labels = []
Object.keys(data).forEach((key) => {
bannerData[key] = data[key][0];
console.log(key);
if (key == "timestamp") {
labels.push(data[key]);
console.log("wtf");
console.log(labels);
} else {
datasets.push(data[key]);
}
});
Works fine. If I had to guess, labels is undefined in your script, causing it to error before "wtf" is printed.
I am running a loop through my array to check if calendar and tpoint have values. In my else statement of my if-statement I am attempting to get the key's name with var notSelected = (obj.prop.subProp).val() !== '';.
I know I am off with my method.. I am just unsure how to get the key name.
So, with my example, since the values in tpoint are empty, I am wanting the var notSelected to equal tpoint.
Anyone know how I can do this?
var packageContents = {
'packages': [
{
'price': '23',
'name': 'Bronze Bundle Package',
'calendar': {
'type': '2year',
'color': 'Brushed Nickel',
},
'tpoint': {
'type': '',
'touches': '',
'years': '',
}
}
]
};
var bundleSet = null;
var bundleSet = null;
packageContents.packages.forEach(function (obj) {
for (var prop in obj) {
if (prop === 'calendar' || prop === 'tpoint') {
for (var subProp in obj[prop]) {
if (obj[prop][subProp] !== '') {
bundleSet = true;
} else {
bundleSet = false;
var notSelected = (obj.prop.subProp).val() !== '';
console.log(notSelected);
}
}
}
}
console.log(bundleSet);
});
What about something like this:
function hasEmptyProps(prop) {
return Object.values(prop).some(x => x === '');
}
const result = packageContents.packages.map(x => {
if (hasEmptyProps(x.calendar)) {
return 'calendar';
} else if (hasEmptyProps(x.tpoint)) {
return 'tpoint'
} else {
return '';
}
})
console.log(result)
Would return ["tpoint"] (or an array of "calendar", "", or "tpoint")