I am working on a script where the objective is to read data from excel and parse it into XML. There is a need for mapping a few of the details under one node if it exists. Considering the below data, I am looking to map the spouse under the subscriber if member id of both of them matches.
expected output:
<Member>
<MemberDetail>
<FIRSTNAME>Kevin</FIRSTNAME>
<LASTNAME>Adams</LASTNAME>
<ID>1</ID>
<Dependent>
<FIRSTNAME>Kelly</FIRSTNAME>
<LASTNAME>Adams</LASTNAME>
<ID>1</ID>
</Dependent>
</MemberDetail>
</Member>
current output:
<Member>
<MemberDetail>
<FIRSTNAME>Kevin</FIRSTNAME>
<LASTNAME>Adams</LASTNAME>
<ID>1</ID>
</MemberDetail>
<MemberDetail>
<Dependent>
<FIRSTNAME>Kelly</FIRSTNAME>
<LASTNAME>Adams</LASTNAME>
<ID>1</ID>
</Dependent>
<MemberDetail>
</Member>
code:
const xlsxFile = require('read-excel-file/node');
const builder = require('xmlbuilder');
const fs = require('fs');
const doc = builder.create('Member');
const serializer = new (require('xmldom')).XMLSerializer;
xlsxFile('./data/file.xlsx', { sheet: 'Details' }).then((rows) => {
const typeColumn = rows[0].indexOf('MEMBER TYPE');
rows.forEach((row, rowIndex) => {
if (rowIndex !== 0) {
const detail = employeeList.ele('MemberDetail').att('for', 'subscriber')
if (row[typeColumn] == 'SUBSCRIBER') {
row.forEach((cellValue, cellIndex) => {
detail.ele(rows[0][cellIndex].split(" ").join(""))
.txt(cellValue ? cellValue.toString() : 'empty')
.up()
})
}
else {
const dependentDetail = detail.ele('Dependent').att('for', 'dependent')
row.forEach((cellValue, cellIndex) => {
dependentDetail.ele(rows[0][cellIndex].split(" ").join(""))
.txt(cellValue ? cellValue.toString() : 'empty')
.up()
})
}
}
})
fs.writeFile('./test.xml', serializer.serializeToString(doc), function (error) {
if (error) {
console.log('Error', error)
}
else {
console.log('Your file has been saved')
}
})
})
.catch(err => console.log(err))
[1]: https://i.stack.imgur.com/giOUj.png
My only suggestion would be to isolate the element that you are mapping 'MemberDetail' as a constant and add dependentDetail to that.
try this
const xlsxFile = require('read-excel-file/node');
const builder = require('xmlbuilder');
const fs = require('fs');
const doc = builder.create('Member');
const serializer = new (require('xmldom')).XMLSerializer;
xlsxFile('./data/file.xlsx', { sheet: 'Details' }).then((rows) => {
const typeColumn = rows[0].indexOf('MEMBER TYPE');
rows.forEach((row, rowIndex) => {
if (rowIndex !== 0) {
const detail = employeeList.ele('MemberDetail').att('for', 'subscriber')
row.forEach((cellValue, cellIndex) => {
if (row[typeColumn] == 'SUBSCRIBER') {
const subscriber = detail.ele(rows[0][cellIndex].split(" ").join(""))
.txt(cellValue ? cellValue.toString() : 'empty')
.up()
row.forEach((cellValue, cellIndex) => {
if (row[typeColumn] !== 'SUBSCRIBER') {
const dependentDetail = subscriber.ele('Dependent').att('for', 'dependent')
dependentDetail.ele(rows[0][cellIndex].split(" ").join(""))
.txt(cellValue ? cellValue.toString() : 'empty')
.up()
}
})
}})
fs.writeFile('./test.xml', serializer.serializeToString(doc), function (error) {
if (error) {
console.log('Error', error)
}
else {
console.log('Your file has been saved')
}
})
}})
.catch(err => console.log(err))})
Related
I'm trying to implement SSR in my project, but constantly getting this error/warn.
How can I know what is wrong with my code?
I have a lot of components in my project, dont know if I need to show you all of my code, but there is main TypeScript
import {Book} from '#/data/data'
const useBooksStore = () => {
const books = useState<Book[]>('books', () => [])
const savedBooks = useState<String[]>('savedBooks', () => [])
const isLoading = useState('isLoading', () => false)
const apiKey = 'AIzaSyBz-gCuGyQopm_Ey2QWPrMGghy0D0e1FYY'
const booksCookie = useCookie('savedBooks')
//loading the list of books on query
async function loadBooks(query: string) {
const response = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}&key=${apiKey}`)
if (response.ok) {
const result = await response.json()
if (result.items) {
books.value = books.value.filter(book => book.favourites === true)
result.items.forEach(item => {
const existingBook = books.value.find(book => book.id === item.id)
if (!existingBook) {
let data = constructBookData(item)
books.value.unshift(data)
}
})
} else {
books.value = books.value.filter(book => book.favourites === true)
throw new Error('Not Found')
}
}
}
//loading saved books from cookies
async function loadSavedBooks() {
if (booksCookie.value) {
savedBooks.value = booksCookie.value
}
let response, result
for (const savedBook of savedBooks.value) {
const existingBook = books.value.find(book => book.id === savedBook)
if (!existingBook) {
response = await fetch(`https://www.googleapis.com/books/v1/volumes/${savedBook}?key=${apiKey}`)
if (response.ok) {
result = await response.json()
if (!books.value.find(book => book.id === result.id)) {
let data = constructBookData(result)
data.favourites = true
books.value.push(data)
}
}
} else {
existingBook.favourites = true
}
}
}
//returns a new book object
function constructBookData(result): Book {
const data = {
id: result.id,
title: String(result.volumeInfo.title),
imgUrl: result.volumeInfo.imageLinks && result.volumeInfo.imageLinks.thumbnail,
shortDescr: result.volumeInfo.description,
price: result.saleInfo.saleability === "FOR_SALE" ? Math.floor(result.saleInfo.retailPrice.amount) : result.saleInfo.saleability.split('_').join(' '),
infoLink: result.volumeInfo.infoLink,
favourites: false
}
return data
}
//handling loading (needed for loading spinner to show)
async function handleLoading(callback) {
isLoading.value = true
try {
await callback()
} catch (err) {
throw err
} finally {
isLoading.value = false
}
}
//toggle favourite status of a book card
function toggleFavourite(bookId: string) {
const book = books.value.find(book => book.id === bookId)
book.favourites = !book.favourites
if (book.favourites && !savedBooks.value.find(book => book === bookId)) {
savedBooks.value.push(book.id)
} else {
savedBooks.value.splice(savedBooks.value.findIndex(book => book === bookId), 1)
}
booksCookie.value = JSON.stringify(savedBooks.value)
}
//returns a list of saved books
function getSavedBooks() {
if (books.value) {
return books.value.filter(book => book.favourites === true)
}
}
//returns loading status
function getLoading() {
return isLoading.value
}
return {
books,
loadBooks,
getSavedBooks,
toggleFavourite,
loadSavedBooks,
handleLoading,
getLoading
}
}
export default useBooksStore
My main question is how can I know whats wrong with my code to solve this problem?
I found an answer. The issue was in this code
<component :is="type === 'link' ? 'a' :
(type === 'button' && 'button')" :href='href' class="btn" #click="emit('click')" :class="class">
<slot/>
</component>
So I think dont use this type of component rendering, because it is not SSR friendly a guess) I rewrite it to this code
<a v-if="type === 'link'" :href="href" class="btn" #click="emit('click')">
<slot/>
</a>
<button v-else-if="type === 'button'" :href="href" class="btn" #click="emit('click')">
<slot/>
</button>
I am unable to create the following SQL query in Knex:
SELECT * FROM tasks WHERE (code = 'export') AND (status = 'failed' OR status = 'complete')
Using the code:
const queryResult = await this.db('tasks')
.select('*')
.where(async function () {
if ('code' in query) {
this.where('code', query.code)
}
if ('status' in query) {
if (isArray(query.status)) {
return query.status.map(status => this.orWhere('status', status))
} else {
this.andWhere('status', query.status)
}
}
})
.orderBy('created_at', 'DESC')
When supplying an array of multiple statuses it disregards the "code = export" value and selects everything.
Use modify.
const queryResult = await this.db('tasks')
.select('*')
.modify(function(queryBuilder) {
if ('code' in query) {
queryBuilder.where('code', query.code)
}
if ('status' in query) {
if (isArray(query.status)) {
query.status.map(status => queryBuilder.orWhere('status', status))
} else {
queryBuilder.andWhere('status', query.status)
}
}
})
.orderBy('created_at', 'DESC')
const query = knex('tasks');
if ('code' in query) {
query.where('code', query.code);
}
if ('status' in query) {
query.where(builder => {
const statuses = isArray(query.status) ? query.status : [query.status];
for (let status of statuses) {
builder.orWhere('status', status);
}
});
}
const result = await query;
I'm fetching data form a API and since I have to collect lots of data, I'm using the setTimeOut function to delay the requests by 3s each. But, when I try to run the code, the for loop only run once and finishes the program.
const fs = require('fs')
const { JSDOM } = require("jsdom")
const { window } = new JSDOM("")
const $ = require("jquery")(window)
const path = require('path')
const fetchArt = require('./utils/fetchArt.js')
const { data } = require('jquery')
const { resolve } = require('path')
let replacer = RegExp(' ', 'g')
let slash = RegExp('/', 'g')
const requestArtSongs = (artist) => {
return $.getJSON("https://www.vagalume.com.br/" + artist + "/index.js").then(
function (data) {
return data.artist.lyrics.item
}
)
}
const map = (lang) => {
switch (lang) {
case 1: return 'pt'
case 2: return 'en'
default: return lang
}
}
const requestMusic = (artist, song) => {
return $.getJSON(
"https://api.vagalume.com.br/search.php"
+ "?art=" + artist
+ "&mus=" + song
+ "&apikey={key}"
).then(function (data) {
return [data.mus[0].text, data.mus[0].lang]
})
}
const makeRequest = (art, songs) => {
songs.forEach((song, i) => {
delay(3000 * (i+1))
.then(() => makeSongRequest(art, song.desc))
})
}
const writeFile = (art, songName, mus) => {
gen = gens[0]
let music = {
artist: art,
song: {
name: songName,
text: mus[0],
lang: map(mus[1])
}
}
if (fs.existsSync(path.join(__dirname, 'Genders', gen, art))) {
fs.writeFile(path.join(__dirname, 'Genders', gen, art, `${songName.replace(slash, '')}.json`),
JSON.stringify(music, null, 4),
(err) => {
if (err) throw err
console.log('Song ' + songName + ' written!')
})
} else {
fs.mkdir(path.join(__dirname, 'Genders', gen, art), { recursive: true }, err => {
if (err) throw err
fs.writeFile(path.join(__dirname, 'Genders', gen, art, `${songName.replace(slash, '')}.json`),
JSON.stringify(music, null, 4),
(err) => {
if (err) throw err
console.log('Song ' + songName + ' written!')
})
})
}
}
const makeSongRequest = (art, songName) => {
requestMusic(art, songName)
.then(mus => {
writeFile(art, songName, mus)
})
}
const delay = t => new Promise (resolve => setTimeout(resolve, t))
const writeSongs = (artist) => {
art = artist.replace(replacer, '-').toLowerCase()
return new Promise(() => {
requestArtSongs(art)
.then((songs) => {
makeRequest(artist, songs)
})
})
}
const main = async () => {
let gens = ['Funk']
for (let gen of gens){
let arts = await fetchArt(gen)
for (let art of arts) {
await writeSongs(art)
}
}
}
main()
On my main function, I'm trying to fetch lyrics from the API. For each gender (in this case, only 'Funk') I get the artists that sing that gender. Then, for each artist I run the writeSongs function that does lots of stuff.
I'm using Node JS to do all the work.
I'm trying to delete all the users in my auth and database using firebase functions. Here's my code for that:
const admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "----"
});
export const listenToAdminCommands = functions.firestore.document('collection/{docUid}')
.onWrite((change, context) =>
{
const pass: string = '--';
// const before = change.before.exists? change.before.data() : null;
const after = change.after.exists? change.after.data() : null;
if(after !== null && after !== undefined) {
const adminCommandType: string = after['type'];
const adminCommandPass: string = after['pass'];
if(adminCommandType === 'deleteAll' && adminCommandPass === pass) {
adminDeleteAllUsers();
}
}
});
//Admin control
function adminDeleteAllUsers() {
deleteAllUsers(' ');
return null;
}
function deleteAllUsers(nextPageToken: any) {
admin.auth().listUsers(1000, nextPageToken)
.then((listUsersResult: any) => {
//go through each one and check last time signed in
listUsersResult.users.forEach((userRecord: any) => {
const user: any = userRecord.toJSON();
const userUid = user['uid'];
console.log('Deleting user for data delete uid = ', userUid);
admin.auth().deleteUser(userUid)
.then(() => {
console.log('Successfully deleted user', userUid);
})
.catch((error: any) => {
console.log('Error deleting user:', error);
});
db.collection('users').doc(userUid).delete();
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch((error: any) => {
console.log('Error listing users:', error);
});
}
When the function get executed, no user is deleted. It's like the function never worked. Am I missing something?
Update:
I'm not sure if this is the way to do it, but it's still not working. I tried to handle promises correctly, but I'm not sure if what I'm doing is correct or not.
export const listenToAdminCommands = functions.firestore.document('collection/{docUid}')
.onWrite((change, context) =>
{
const pass: string = '---';
// const before = change.before.exists? change.before.data() : null;
const after = change.after.exists? change.after.data() : null;
if(after !== null && after !== undefined) {
const adminCommandType: string = after['type'];
const adminCommandPass: string = after['pass'];
if(adminCommandType === 'deleteAll' && adminCommandPass === pass) {
return adminDeleteAllUsers();
}
return;
}
return;
});
//Admin control
function adminDeleteAllUsers() {
return deleteAllUsers(' ');
}
function deleteAllUsers(nextPageToken: any) {
return admin.auth().listUsers(1000, nextPageToken)
.then((listUsersResult: any) => {
//go through each one and check last time signed in
listUsersResult.users.forEach((userRecord: any) => {
const user: any = userRecord.toJSON();
const userUid = user['uid'];
console.log('Deleting user for data delete uid = ', userUid);
return admin.auth().deleteUser(userUid)
.then(() => {
console.log('Successfully deleted user', userUid);
return db.collection('users').doc(userUid).delete();
})
.catch((error: any) => {
console.log('Error deleting user:', error);
return;
});
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
return;
})
.catch((error: any) => {
console.log('Error listing users:', error);
return;
});
}
I am doing a comparison to validate QR Code using the data retrieved from Firestore. It should navigate to another page if the condition is satisfied. Based on my code, it kept on returning 'Invalid Code' and multiple stacked alerts even if the condition is true. Is there a simpler solution to compare? I just can't quite figure it out. Here's my code.
scan() {
this.scanner.scan().then((data) => {
let qrcode = data.text.length;
this.afs.firestore.collection('item1')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc1 => {
var data1 = doc1.data();
var itemName = data1.itemname;
var itemID = data1.itemid;
this.afs.firestore.collection('item2')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc2 => {
var data2 = doc2.data();
var itemName2 = data2.itemname2;
var itemID2 = data2.itemid2;
var description = data2.description;
if (doc1.exists) {
if (qrcode == 10 && itemName == itemName2 && itemID == itemID2) {
this.navCtrl.navigateForward('/nextPage');
} else {
return this.presentAlert('Error', 'Invalid Code')
}
} else if (description == null) {
return this.presentAlert('Error', 'Nothing found')
} else {
return this.presentAlert('Error', 'QR Not Found')
}
})
})
})
})
}, (err) => {
console.log('Error: ', err);
})
}
I think that your issue is because you have 2 nested "forEach" cycles and even is you routine has a valid condition there isn't a return statement and your cycles never been stopped(using break)
I adjusted your code to break the cycles
scan() {
this.scanner.scan().then((data) => {
let qrcode = data.text.length;
this.afs.firestore.collection('item1')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc1 => {
var data1 = doc1.data();
var itemName = data1.itemname;
var itemID = data1.itemid;
var check = this.afs.firestore.collection('item2')
. get()
.then((snapshot) => {
snapshot.docs.forEach(doc2 => {
var data2 = doc2.data();
var itemName2 = data2.itemname2;
var itemID2 = data2.itemid2;
var description = data2.description;
if (doc1.exists) {
if (qrcode == 10 && itemName == itemName2 && itemID == itemID2) {
return true
} else {
return this.presentAlert('Error', 'Invalid Code')
}
} else if (description == null) {
return this.presentAlert('Error', 'Nothing found')
} else {
return this.presentAlert('Error', 'QR Not Found')
}
})
})
if (check){
this.navCtrl.navigateForward('/nextPage');
break
}else{
return check
}
})
})
}, (err) => {
console.log('Error: ', err);
})
}