GAPI Export to Google Sheet Invalid Argument Error - javascript

I'm trying to export details from out app into a google sheet and am getting an "Invalid argument" error. I'm trying to take the data from the page and also grab users' birthdays on export. We use firestore as a db.
exportStaff(shift) {
console.log(shift)
const exportHeaders = [
"Day",
"Event",
"Position",
"Start",
"End",
"First Name",
"Last Name",
"Phone",
"Email",
"Confirmed",
"DOB",
"Code",
];
const exportItems = [];
for (var key in this.orderedPlacedUsers2(shift.id)) {
function myDOB(staff) {
return fb.usersCollection.doc(staff).get()
.then(doc => {
console.log(doc.data().dob)
return doc.data().dob
})
}
exportItems.push([
shift.day,
shift.event,
shift.position.title,
shift.startTime,
shift.endTime,
this.orderedPlacedUsers2(shift.id)[key].firstName,
this.orderedPlacedUsers2(shift.id)[key].lastName,
this.orderedPlacedUsers2(shift.id)[key].phone,
this.orderedPlacedUsers2(shift.id)[key].email,
this.orderedPlacedUsers2(shift.id)[key].confirmed,
myDOB(this.orderedPlacedUsers2(shift.id)[key].userId),
`=REGEXEXTRACT(H2,"....$")`
])
}
this.$gapi.getGapiClient().then(gapi => {
const exportService = new ExportService(exportHeaders, Object.values(exportItems), gapi);
exportService.export();
});
},
All of the birthdays are logging correctly to the console, but no values show on the sheet.
Here is a screenshot of the error in the console.
How can I get the birthdays (DOB) to export properly?
Here is my exportService.js
export default class ExportService {
constructor(columns, data, gapi) {
this.columns = columns;
this.data = data;
this.gapi = gapi;
this.spreadsheetId = null;
}
export() {
this.gapi.auth2.getAuthInstance().signIn()
.then(() => {
this.createSpreadsheet();
});
}
createSpreadsheet() {
this.gapi.client.sheets.spreadsheets.create({
properties: {
title: 'New Report'
}
}).then((response) => {
this.spreadsheetId = response.result.spreadsheetId;
this.writeRows();
this.openSpreadsheet(response.result.spreadsheetUrl)
});
}
writeRows() {
this.data.unshift(this.columns);
this.gapi.client.sheets.spreadsheets.values.append({
spreadsheetId: this.spreadsheetId,
range: 'A1:F1',
valueInputOption: 'USER_ENTERED',
resource: {
values: this.data
}
}).then((response) => {
var result = response.result;
console.log(`${result.updates.updatedCells} cells appended.`)
});
}
openSpreadsheet(url) {
window.open(url, '_blank');
}
}

Related

how to optimize code like reduce code with same functionality

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.

Determining pr eliminating empty key:value from an object for multiple filtering purposes

My app has a feature where users can filter results based on "blood group" and "city", and areas. Results will be retrieved from DB using Axios for Vuejs through "URL" query strings. Example url is: http://example.com/api/results?blood=a+&city=london
It should work in a way that when a user select just blood group from select menu: the url would exclude the city parameter. But from my current code, I can't get it stripped of, as a result, the database query returns no results on the basis that cityreturns null value.
Here's what I have in my Vue component:
<script>
export default {
props: ['user'],
data() {
return {
auth_user: this.user,
results: {},
blood_groups: "",
cities: "",
districts: "",
areas: "",
donorUrl: "/api/donors",
requestedBlood: "",
requestedCity: "",
requestedDist: "",
requestedArea: "",
params: {}
};
},
created() {
this.fetchDonors();
this.fetchCities();
},
methods: {
fetchDonors() {
let url = "/api/donors";
axios.get(url).then(response => {
this.results = response.data.data;
this.blood_groups = [...new Set(response.data.data.map(x=> x.blood_group))];
});
},
fetchCities() {
let url = "/api/location_type/cities";
axios.get(url).then(response => {
this.cities = response.data.cities
})
},
selected_blood_group(event) {
this.requestedBlood = event.target.value;
this.get();
},
get_city(event) {
this.requestedCity = event.target.value;
this.get();
},
get() {
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
axios.get('/api/donors', request).then(response => {
this.results = response.data.data
})
}
},
};
</script>
My query is how can I remove or check if any of the following properties contains empty value, so that I do not include them in axios params?
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
You can try below code.
Create a new object(called testParams) and add that object in params.suppose requestedCity is selected(not only but any variable is selected ). Then you can do like below.
if(requestedCity.length!=0)
{
testParams["city"]=requestedCity; // OTHERWISE DON'T ADD IN testParams object
}
Finally while making request through axios add testParams in params object like below.
axios.get('/yourUrl/',{
params:{
testParams //here vue will automatically sets 'testParams':testParams
}
})
I got it working with the following approach:
let request = {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
for(let k in request)
if(!request[k]) delete request[k];
axios.get('/api/donors', {
params: request
}).then(response => {
this.results = response.data.data
})

GraphQL + Mongoose: How to change property of mongoose retrieved data

I'm writing a GraphQL query that will return mongoose data:
export const getInventory = () => {
let query = {
deletedAt: null
};
let stocks = await StockModel.find(query)
.sort({ material: 1 });
// Now separate each inventory item per material
let inventory = {};
stocks.map(stock => {
if (inventory[stock.material]) {
inventory[stock.material].quantity += stock.quantity;
} else {
let clone = Object.assign({}, stock);
clone.lot = null;
clone.expirationDateTime = null;
clone.partNumber = null;
clone.manufacturer = null;
inventory[stock.material] = clone;
}
});
let list = Object.keys(inventory).map(key => {
return inventory[key];
});
return list;
};
Here is my inventory GraphQL query:
const inventory = {
type: new GraphQLList(StockType),
description: "Get all inventory",
resolve(root, args, context) {
return getInventory();
}
};
When running the following query:
{
viewer {
inventory() {
id
quantity
lot
}
}
}
I'm getting the following GraphQL error:
{
"errors": [
{
"message": "Expected value of type \"Stock\" but got: [object Object].",
"locations": [
{
"line": 3,
"column": 5
}
],
"stack": "Expected value of type \"Stock\" but got: [object Object].\n\nGraphQL request (3:5)\n2: viewer {\n3: inventory {\n ^\n4: id\n\n at invalidReturnTypeError (/dev/node_modules/graphql/execution/execute.js:766:10)\n at completeObjectValue (/dev/node_modules/graphql/execution/execute.js:758:13)\n at completeValue (/dev/node_modules/graphql/execution/execute.js:660:12)\n at completeValueWithLocatedError (/dev/node_modules/graphql/execution/execute.js:580:21)\n at completeValueCatchingError (/dev/node_modules/graphql/execution/execute.js:556:21)\n at /dev/node_modules/graphql/execution/execute.js:684:25\n at Array.forEach (<anonymous>)\n at forEach (/dev/node_modules/iterall/index.js:83:25)\n at completeListValue (/dev/node_modules/graphql/execution/execute.js:680:24)\n at completeValue (/dev/node_modules/graphql/execution/execute.js:643:12)\n at /dev/node_modules/graphql/execution/execute.js:617:14\n at process._tickCallback (internal/process/next_tick.js:68:7)",
"path": [
"viewer",
"inventory",
0
]
}
}
How can I solve the error?

method is returning id but not saving other data points

My method works when I put values in new Farm () but not when I run it through postman in JSON which is also displayed below. I do not think I am parsing the JSON incorrectly. Any suggestions would be appreciated ?
export interface IDataFlowService {
handle(request: IDataFlowRequest): Promise<IDataFlowResponse>;
}
export class DataFlowService implements IDataFlowService {
current_env = process.env.NODE_ENV;
async handle(request: IDataFlowRequest): Promise<IDataFlowResponse> {
let response: IDataFlowResponse;
try {
switch (request.requestType) {
case "SaveFarms":
response = await this.SaveFarms(request);
break;
default:
winston.error(`Request failed for request type: ${request.requestType}`);
break;
}
return response;
} catch (e) {
winston.error(`handle method failed for request: ${request}`, e);
response = {
success: false,
error: {
'message': e.message,
}
};
return response;
}
}
private async SaveFarms(request: IDataFlowRequest): Promise<IDataFlowResponse> {
const response: IDataFlowResponse = {
success: true ,
farmIds: [],
names: []
};
for (const farm of request.farms) {
const newFarm: IFarmModel = new Farm();
Promise.all([newFarm.save()]);
response.farmIds.push(newFarm.farmId) ;
response.names.push(newFarm.name) ;
}
return response;
}
}
here is post: http://localhost:5000/api/dataflow
{
"requestType":"SaveFarms",
"farms": [
{
"name" : "Bronx"
}
]
}
as you can see I get a response but the names field is coming back null/empty:
{
"success": true,
"farmIds": [
"fH1WjllXR"
],
"names": [
null
]
}
You forget set name for newFarm object:
const newFarm: IFarmModel = new Farm();
newFarm.name = farm.name; // I think so

Data Binding with Smart table from json file

i want to bind the json file to a smart table. How to use the loop function for the iteration.. please help
It only shows the design of smart table.
didn't binding the data from json
this is the json file
[
{
"year": 2013,
"id": "",
"doctor": "Dr. Smith",
"illness": "Flu",
"apptdate": "3/12/2013",
"details":"Patient had flu for 5 days. No medicines prescribed"
}
]
i used to retrieve data using
#Injectable()
export class SmartTablesService {
constructor(private http: Http) {
}
smartTableData = [];
loadData() {
console.log('loadData');
this.http.get('http://192.168.0.100:8000/medical')
.subscribe((data) => {
setTimeout(() => {
var contactData = [];
$.each(data.json(), function (key, value) {
var tempData = value.source;
contactData.push(tempData);
});
this.smartTableData = contactData;
}, 1000);
});
}
getData(): Promise<any> {
console.log("Promise");
this.loadData();
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(this.smartTableData);
resolve(this.smartTableData);
}, 3000);
});
}
}
constructor(private http: Http) { }
getComments() {
return this.http.get('http://192.168.0.100:8000/article' )
.map((res: Response) => res.json())
.catch((error:any) => Observable.throw(error));
}
}*/
this is the component part
#Component({
selector: 'new',
template: '<ng2-smart-table [settings]="settings" [source]="source"></ng2-smart-table>'
})
export class NewComponent {
query: string = '';
settings = {
noDataMessage: 'Loading...',
columns: {
year: {
title: 'YEAR',
type: 'string'
},
id: {
title: 'ID',
type: 'string'
},
doctor: {
title: 'DOCTOR',
type: 'string'
},
illness: {
title: 'ILLNESS',
type: 'string'
},
apptdate: {
title: 'APPTDATE',
type: 'string'
},
details: {
title: 'DETAILS',
type: 'string'
}
}
};
// data
source: LocalDataSource = new LocalDataSource();
constructor(protected service: SmartTablesService){
this.service.getData().then((data) => {
this.source.load(data);
});
}
}
please anyone anyone know how to bind it ..help
simply change the subscribe part in the service page to
var tempData = value;
so .subscriber looks like
.subscribe((data) => {
setTimeout(() => {
var contactData = [];
$.each(data.json(), function (key, value) {
var tempData = value; contactData.push(tempData);
});
this.smartTableData = contactData;
}, 1000);
});
}
it works..!

Categories