I have an object store I need to export or download as a .csv file. I have done some searching and I can't seem to find information on this function. Responses that do not utilize IDB are welcome.
Some background: This is part of a project for work, and I dove into this project without prior knowledge of coding whatsoever. I am using a company issued chromebook, so (as far as I know) NPM installs are not available.
App Background: The project is a customer survey operated through a single terminal. That terminal being my chromebook with hopes to move to an ipad if I can successfully download user inputs to .csv file.
What I have so far:
(function leadIDB() {
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB|| window.msIndexedDB;
if (!window.indexedDB) {
alert('indexDB not supported in this browser');
}
let request = window.indexedDB.open("leadDB", 1),
db,
tx,
store,
index;
request.onupgradeneeded = function(e) {
let db = request.result,
store = db.createObjectStore("LeadStore", {keyPath: "leadID", autoIncrement: true});
index = store.createIndex("firstName", "firstName", {unique: false});
};
request.onerror = function(e) {
console.log("There was an error: " + e.target.errorCode);
};
request.onsuccess = function(e) {
db = request.result;
tx = db.transaction("LeadStore", "readwrite");
store = tx.objectStore("LeadStore");
index = store.index("firstName");
db.onerror = function(e) {
console.log("ERROR" + e.target.errorCode);
};
store.put(newLead);
let lead = store.getAll();
lead.onsuccess = function() {
console.log(lead.result);
console.log(lead.result.firstName);
};
tx.oncomplete = function() {
console.log('Item added to LeadDB');
db.close();
};
};
})();
You are on the right track. There are a few more things to do. First, you need to be able to continue processing once you have loaded the data from indexedDB into js memory. Next, you need to generate the CSV file in memory (as a gigantic string). Next, you need to convert the csv string into a File (which implements Blob). Finally, you want to trigger the download of the file.
There are a few ways to do the first step. I am going to use a promise, but you could do this with a callback or whatever you fancy.
function loadData() {
return new Promise((resolve, reject) => {
var openrequest = indexedDB.open(...);
openrequest.onupgradeneeded = ...;
openrequest.onerror = event => reject(event.target.error);
openrequest.onsuccess = event => {
var db = event.target.result;
var txn = db.transaction(...);
var store = txn.objectStore(...);
var loadrequest = store.getAll();
loadrequest.onerror = event => reject(event.target.error);
loadrequest.onsuccess = event => {
var data = event.target.result;
resolve(data);
};
};
});
}
// You could call the function like this for example:
async function foo() {
var data = await loadData();
console.log('loaded the data, loaded %d objects', data.length);
}
Next, you want to convert the data into a csv-formatted string.
// This is not perfect, just an example of getting you closer
function toCSV(data) {
var output = [];
for(var object of data) {
var row = [];
for(var prop in object) {
row.push(to_csv_value(object[prop]));
row.push(',');
}
row.push('\n');
output.push(row.join(''));
}
return output.join('');
}
function to_csv_value(value) {
var output = '"';
output += value.replace('"', '\\"');
return output + '"';
}
// and then to compose it for example:
async function foo() {
var data = await loadData();
var csvstring = toCSV(data);
}
Next, you want to create a file. You can use the Blob constructor to do this. Something like the following:
// Because File implements blob interface, we are effectively creating a file
// by creating a blob
function createCSVFileFromString(string) {
var csv_mime_type = 'text/csv';
return new Blob([string], {type: csv_mime_type});
}
// And again, to compose it:
async function foo() {
var data = await loadData();
var string = toCSV(data);
var blob = createCSVFileFromString(string);
}
The next step is to make the blob downloadable. This can typically be done using the object url strategy. Kind of like the following:
function downloadBlob(blob, filename) {
var anchor = document.createElement('a');
anchor.setAttribute('download', filename);
var url = URL.createObjectURL(blob);
anchor.setAttribute('href', url);
anchor.click();
URL.revokeObjectURL(url);
}
// And finally, to compose it all together
async function loadAndStartDownloadingData() {
var data = await loadData();
var csvstring = toCSV(data);
var blob = createCSVFileFromString(csvstring);
downloadBlob(blob, 'mydata.csv');
}
Then, somewhere in your application, let's say on click of button, you would do something like this. Im using non-async syntax here just for example of using promise in non-await, you want to always be careful to not hide errors.
var button = ...;
button.onclick = function(event) {
// Load the data and trigger the download, and send any problems to console
loadAndStartDownloadingData().catch(console.warn);
};
Note, this doesn't cover inserting the data, but I'm sure you can figure that out.
Related
I would like to validate and set a ID for a collection in firebase. Right now i am just trying to get an id number back from a collections query and send it to the function that needs it. Here is the function that needs the id#.
const data = lastCustIdGrab(); console.log(`Last number ${data}`);
This is the return sender. I can get the document Id in the console log but can't figure how to send it back.
exports.lastCustIdGrab = () => {
db.collection('Customers')
.orderBy('createdAt', 'desc')
.limit(1);
.get()
.then((data) => {
let DOC = data.docs[0];
let ID = DOC.id;
console.log("LOOOP ",ID);
return ID;
})}
This gets me the id in the LOOOP output but won't return it! I know i can return data as i have tested with the arbitrary code below and it works. The return sends it back to be console logged in the "last number" output properly.
exports.lastCustIdGrab = () => {
let ID = 12345;
return ID;
}
So I'm sure that i am just missing something simple. Thanks for the Help!
In the lastCustIdGrab function you need to return the promises chain, as follows:
exports.lastCustIdGrab = () => {
return db.collection('Customers') // <== See return
.orderBy('createdAt', 'desc')
.limit(1);
.get()
.then((data) => {
let DOC = data.docs[0];
let ID = DOC.id;
console.log("LOOOP ",ID);
return ID;
});
}
AND you should note that the lastCustIdGrab function is asynchronous and returns a Promise, which means that you need to do:
lastCustIdGrab()
.then(data => {
console.log(`Last number ${data}`);
});
.get() is asynchronous, and in your method you're not returning the promise. So even though the then() is executing, the value returned from the promise's resolve isn't being returned to lastCustIdGrab() invocation because the promise is never returned. So (switching it up to use async/await) try this:
exports.lastCustIdGrab = async () => {
let data = await db.collection('Customers')
.orderBy('createdAt', 'desc')
.limit(1)
.get();
let DOC = data.docs[0];
let ID = DOC.id;
return ID;
}
}
And in your invocation wait for the promise to resolve to ensure error handling and method completion:
const data = await lastCustIdGrab();
When calling db.schema.nodeTypeProperties() from within the Neo4J Broswer, the Code side tab returns the complete JSON schema in the Response drop-down. Is it possible to retrieve this JSON result in C# or Java using the Neo4J.Driver? I would like to deserialize the JSON text into C# classes.
Screen-cap of Response drop-down from db.schema.nodeTypeProperties()
I have explored the Neo4J.Driver IDriver, IAsyncSession and IResultCursor calls and cannot find a way to retrieve the JSON dataset.
I was able to get what I wanted by using apoc.export.json.all to stream in a JSON dataset of the entire database. I leveraged the examples at https://neo4j.com/docs/labs/apoc/current/export/json/#export-database-json. I apologize for what turned out to be the misdirection of my question. db.schema.nodeTypeProperties() was not going to get me what I really needed.
using Newtonsoft.Json.Linq;
public async void TestNeo4j()
{
// Set up the graph database driver and connect the session to the Neo4J database.
IDriver driver = GraphDatabase.Driver(Neo4JBoltURI, AuthTokens.Basic(Neo4JUser, Neo4JPassword));
IAsyncSession session = driver.AsyncSession();
IResultCursor cursor;
try
{
// Bring the JSON text in as a stream
string query = "CALL apoc.export.json.all(null,{stream:true,useTypes:true}) " +
"YIELD file, nodes, relationships, properties, data " +
"RETURN file, nodes, relationships, properties, data";
cursor = await session.RunAsync(query);
string sJsonData = await cursor.SingleAsync(record => record["data"].As<string>());
//Debug.Log(sJsonData);
//// Save the JSON to a file.
//string path = #"C:\Users\Public\Documents\Neo4JExportAll.json";
//if (File.Exists(path)) File.Delete(path);
//File.WriteAllText(path, sJsonData);
// Each line is a separate JSON statement describing a node or a relationship
// Iterate all statements
using (StringReader reader = new StringReader(sJsonData))
{
string line = string.Empty;
do
{
line = reader.ReadLine();
if (line != null)
{
// Deserialize the JSON line into JObject jo.
JObject jo = JObject.Parse(line);
// Dig into the JObject to get the data from the stream.
}
} while (line != null);
}
}
finally
{
await session.CloseAsync();
}
}
I have a node js server implementation and I would like to send some values to an Android (Java) client. The method of the node js server is as follows:
app.get('/GetValues*', function (request, response) {
// Request needs to be a GET
if (request.method == 'GET') {
var username = request.query.account;
var time_now = Date.now();
var db = database('./database.db');
var row_account = db.prepare('SELECT SCORE score, STARTED_STUDY_SERVER_MILLIS timestamp, DAYS_TOTAL days_total FROM ACCOUNTS WHERE NAME = ?').get(username);
var score = row_account.score;
var days_total = row_account.days_total;
var days_count = time_now - row_account.timestamp;
var minutes_count = time_now - row_account.timestamp;
var statement = db.prepare("UPDATE ACCOUNTS SET DAYS_COUNT = ?, MINUTES_COUNT = ? WHERE ID = ?");
statement.run(days_count,minutes_count,getAccountID(db, request.query.account));
var row_usage = db.prepare('SELECT DURATION_ENABLED duration_enabled, DURATION_DISABLED duration_disabled FROM USAGE WHERE NAME = ?').get(username);
var duration_enabled = row_usage.duration_enabled;
var duration_disabled = row_usage.duration_disabled;
}
});
I would like to send the values score (integer), days_total (integer), days_count (integer), minutes_count (long), duration_enabled (long), duration_disabled (long) to the client.
How can I send it to the client? I think response.send() only accepts strings. How can I parse the values in Java when received?
Since you need to send all those values at once, it's common to respond with a JSON in such a case. In express, you can send a JSON response using response.send() or response.json() like this:
app.get('/GetValues*', function (request, response) {
// ... your db operations here, then
response.json({
score: score,
days_total: days_total,
days_count: days_count,
minutes_count: minutes_count,
duration_enabled: duration_enabled,
duration_disabled: duration_disabled
});
});
This will send a response with Content-Type: application/json and a JSON string in the body looking like this:
{"score":12,"days_total":12,"days_count":12,"minutes_count":12,"duration_enabled":12,"duration_disabled":12}
Then you just parse it in your Java code.
By the way, this line
if (request.method == 'GET') {
is unnecessary. Registering a handler via app.get(), express will only handle GET requests anyway.
I am working on a news summarizer and one of its requirements is to display a list of article titles dynamically on a webpage using AJAX called from a database. I have been able to successfully configure the datastore(google app engine) and use the AJAX call to display article title. However, there is one big issue here. I am only able to call and show a single title. I want to run the AJAX call inside a loop so that I can display 10 news articles stored in datastore from 1 to 10 using the variable i of the loop as the unique reference.
The AJAX CODE :
function change(element) {
var xmlhttp;
var i = 1;
var param = "category=" + element + "&no=" + i; // This i is the key to my operation.
alert(param); //testing purpose
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
//alert('function()');
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var div = document.getElementById('content');
div.innerHTML = '';
for (i = 1; i <=10; i++) {
var a = document.createElement('a');
a.href = "#";
a.onclick = rem.bind(null, i);
a.innerHTML = '<h2 id="theading'+i+'">'
+ xmlhttp.responseText + '</h2>'; //the title will go here.
div.appendChild(a);
div.appendChild(document.createElement('br'));
}
}
}
xmlhttp.open("POST", "/display?" + param, true);
xmlhttp.send();
}
I also request to suggest JavaScript code and not jquery, as I am unfamiliar with it. These are my humble beginnings.
UPDATE
MY SERVLET CODE:
public class ArticleHandler extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
String category=req.getParameter("category");
String number=req.getParameter("no");
int i = Integer.parseInt(number);
List<EntityArticles> articles = RegisterClass.ofy().load().type(EntityArticles.class).filter("category ",category).list();
out.write(articles); // Is this the correct way to send this list articles ?
}
}
Is this the correct way to send the list ?
10 articles in responseText, you can render html in server code to responseText(loop in server code). And then in ajax sucess you call
var div = document.getElementById('content');
div.innerHTML = xmlhttp.responseText;
I have created a fiddel for you to understand check it. Ajax Example in fiddle
Are you doing post request or get request? I'm asking this because I saw method as "POST" and parameter passed as "GET" by putting it in url. Please correct that part too in your code.
loadXMLDoc=function()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","/ahmadfaizalbh/LaH8F/show/",true);
xmlhttp.send();
}
The best choice is to call the ajax one time and get 10 items.
But, if you have no alternative, you can modify the function a little:
function change(element, i){
var xmlhttp;
//var i=1;
var param = "category=" + element + "&no=" + i;
...
}
Call the function this way (10 times as you need):
for(i=1;int <= 10; i++){
change(element, i);
}
UPDATE
To make one time the ajax call, you can do:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
//append html node
//the object is xmlhttp.responseText. The loop will depend if this is json, html objects, string, etc
}
xmlhttp.open("POST", "/display?" + param, true);
xmlhttp.send();
To obtain 10 results you need (necessarily) to modify the server side script or servlet. If you cannot have access to modify the servlet, is impossible to get 10 items in a single ajax call.
I have two extjs treeStores, one is temp, another is working treeStore, which data interprets by treePanel. Code:
var treeStore = Ext.create('Ext.data.TreeStore',{
root: {
childrens:[],
expanded: true,
text: 'Services'
}
});
var tempStore = Ext.create('Ext.data.TreeStore',{
autoload: false,
proxy:{
type: 'ajax',
url: 'server.jsp',
reader: {
type:'json'
}
},
clearOnLoad: true,
listeners:{
load:{
fn: afterload
}
}
});
tempStore.load();
function afterload(store)
{
var rootTree = treeStore.getRootNode();
var copyChilds = Ext.clone(store.getRootNode().childNodes);
if(rootTree.hasChildNodes())
{
rootTree.removeAll(false);
}
for(var i=0;i<copyChilds.length;i++)
{
rootTree.appendChild(copyChilds[i]);
}
}
When tempStore.load method invoked, i'll send query on server, get data and then put it on another treeStore.p>
The tempStore reload every 3 seconds using TaskRunner:
var taskTree = {
run: reloadTree,
interval:3000 // 1 second
}
var runReloadTreePanel = Ext.create("Ext.util.TaskRunner");
I have checkbox, when i change the state of it into true the runner start works:
var checkbox = Ext.create('Ext.form.field.Checkbox',{
boxLabel: 'Refresh',
listeners :{
change: {
fn: changeCheckBoxState
}
}
});
function changeCheckBoxState(field,newValue,oldValue)
{
if(newValue)
{
runReloadTreePanel.start(taskTree);
}
else
{
runReloadTreePanel.stop(taskTree);
}
}
The problem:
After 2-3 minutes of start memory begin grows(3-4MB every 10seconds), because of method afterload content, which is copy data. Is it bug or i do something wrong?? Maybe the function removeAll(false) didn't remove all child data of treeStore root node? I used a lot of variants - clean dom model elements using Ext.select(..) + innerHtml, try to remove the records one by one using remove(..), but the memory grows.
My treepanel interprets all good, without unnecessary data.
Any ideas? Sorry if my english isn't good.(
i tried to change content of function load to this:
function load(store)
{
var childs = Ext.clone(store.getRootNode().childNodes);
Ext.select('div#treepanel-1032-body div table tbody tr[class^="x-grid-row"]').remove();
treepanel.setRootNode({
text: "Services",
expanded: true,
children: childs
});
I removed dom model object directly, removed from config properties of treepanel store, and set every 3 sec new root, but the memory grows, especially in IE. Any advices?