I have an electron app with a form that will be used to get some information. I don't have an external server or url where I can sent the data, I need to get the form data and store them using dexie.js and vue that I'm using to intercept the click event on submit button. I'm not sure how I can save data, this because I need to get values from the form and then call dexie to store them, I'm using a vue method to manage the click, I was using the document.forms to get form elements name and value, but this is a bad approach. can anyone help me to find a way to achieve this?
//import Dexie from 'dexie';
const Dexie = require('dexie');
// Force debug mode to get async stacks from exceptions.
Dexie.debug = true; // In production, set to false to increase performance a little.
let db = new Dexie('clients');
db.version(1).stores({
websites: "++id,client_name,hosting_provider,website_domain,panel_user,panel_pwd,db_host,db_name,db_user,db_pwd,wp_user,wp_pwd"
});
$(document).ready(function(){
var myapp = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
saveData(){
//var form = document.getElementById('client-info') //document.forms;;
var form = $('#client-info').serialize();
console.log(form);
//var formData = new FormData(form);
//console.log(formData);
// $.each( form[0].elements, function(i, index){
// console.log( index );
// console.log( form[0].elements[i].name, form[0].elements[i].value );
// // or make a new one
// db.clients.add({
// form[0].elements[i].name: form[0].elements[i].value
// });
// });
//console.log(Dexie);
//console.log(db);
}
}
});
console.log(myapp);
});
NB: for now I've commented the code because it will not work, it don't save the data.
You might want to try adding the Dexie code to the main process, which acts as the backend in traditional web terms, and send the form via ipcRenderer to the main process (similar to what I proposed over here.
Related
I've started using workers for my sites. The purpose of workers on my sites:
mostly inject some code(html/js/css) in different locations of HTML page.
It can be some config data, or some legal text and etc.
So what I do now, is create a config in KV for each website and based on user country/language injecting above html/js and etc.
Below is a Store Class (Singleton pattern), that holds all the info from config, but doesn't work in workers, by doesn't work I mean, after first request, the data is persistent, and after some time it gets updated:
For example 1st request URL: /about
On Second request URL: /es/about/
By output console.log(event.request) will show /es/about , but Store.request outputs: /about/
any workaround for this, to force refresh of data, I thought becuase i don't do it in constructor, but by calling custom method should do the trick but, it doesn't.?
Below is some code example.
import { Store } from "#helpers/store";
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
});
//HTML Rewriter Class
class Head {
element(el) {
el.append(`
<script id="config">
var config = ${Store.export()};
</script>`, {
html: true
});
}
}
async function handleRequest(request) {
let store = await Store.make(request);
const response = await fetch(request);
let html = new HTMLRewriter();
html.on("head", new Head());
return html.transform(response);
}
//src/helpers/store.js
class Store {
constructor(){
this._request = null
this._config = {}
this._url = null
}
async make(request){
let config = {}
this._request = request;
const domain = this.url.hostname.replace(/www\./g, "");
const country = request.headers.get('cf-ipcountry')
const website = await WEBSITES.get(domain, "json"); //WEBSITES is KV namespace
const { license, lang } = website;
this._config = {
country,
domain,
license,
lang
};
return this;
}
export(){
return JSON.stringify(this._config)
}
get request(){
return this._request;
}
get url(){
if(!this._url){
this._url = new URL(this.request.url)
}
return this._url;
}
}
export default new Store()
A single instance of your Worker may handle multiple requests, including concurrent requests. In your code, you are using a singleton instance of Store to store metadata about the current request. But if multiple requests are handled concurrently, then the second request will overwrite the content of Store before the first request completes. This may cause the first request to render its HTML using metadata from the second request.
It seems like the use of a singleton pattern isn't what you want here. Based on the code, it looks like you really want to create a separate instance of Store for every request.
2 issues come to mind:
You are creating a new HTMLRewriter for each call to the worker. This will make for some concurrency issues. The instantiation of the rewriter should be done outside the handleRequst method. For example right after the import statement.
You are importing the Store class and never instantiating it but using its methods like they are static(which they aren't). This will also give you concurrency issues.
I am making a note taking app and it is in the early prototyping stages, so I just want to hack together something that will work for myself.
My text editor is built using Quill, and I'm using Vue to structure the whole application. Currently, I don't have a back end, so no server.js.
I would like my application to be able to save the information that I put in the editor, and reload the information whenever I rebuild the app.
I checked out the autosave option provided by Quill here
But I'm not sure what to do with $.post and where to post it.
Can I simply post it to a local .json file?
What is the best thing to save in my case? The example was logging changes, what am I supposed to do with changes?
I apologize beforehand for the lack of clarity in my question, as I don't know exactly what I should be asking to achieve what I want.
Any advice is appreciated.
So if I understood correctly, what you're asking is how to implement quilljs' auto save feature when you have no server. But, you've already answered your own questions.
A simple way to do it would be saving the document into a local json file. But I don't know if you can do that using js.
Another way of doing it, is to save the content to the browser's local storage and loading the data every time you load the app.
var Delta = Quill.import('delta');
var quill = new Quill('#editor-container', {
modules: {
toolbar: true
},
placeholder: 'Compose an epic...',
theme: 'snow'
});
// Store accumulated changes
var change = new Delta();
quill.on('text-change', function(delta) {
change = change.compose(delta);
});
// Save periodically
setInterval(function() {
if (change.length() > 0) {
console.log('Saving changes', change);
// Save the entire updated text to localStorage
const data = JSON.stringify(quill.getContents())
localStorage.setItem('storedText', data);
change = new Delta();
}
}, 5*1000);
// Check for unsaved data
window.onbeforeunload = function() {
if (change.length() > 0) {
return 'There are unsaved changes. Are you sure you want to leave?';
}
}
Then inside your vue component's mounted(), use the following to fetch the saved data:
const data = JSON.parse(localStorage.getItem('storedText'));
I have been trying to add data to my database without any luck.
In my code i have made a button when click, it will add data to my users database but it will not add it to the user but it just add the data outside like this:
is it because you cant add data when you have use the createUserWithEmailAndPassword() function?
Can anyone please show me how it is done?
btn.addEventListener("click", function()
{
firebase.auth().onAuthStateChanged(function(user)
{
if (user)
{
var massage = inputText.value;
var ref = database.ref("Users");
var data = {
display: massage
}
ref.push(data);
}
});
});
Whenever you call push() Firebase generates a new unique ID. So to add the new data to the existing node, you should not call push. Instead you need to find a reference to the existing node for that user.
The easiest (and by far most common) way to do this, is to store the user data under the UID of each user.
Users
kHD...NoS
username: "bob"
Also note that there's no reason to put this type of onAuthStateChange listener inside a button click handler. Just attach it from the top-level JavaScript and it will trigger whenever the user signs in or when their auth state changes in any other way.
Alternatively, if the code really must run in response to the button click, there's no real use for a auth state listener and you can just check firebase.auth().currentUser:
btn.addEventListener("click", function()
{
if (firebase.auth().currentUser)
{
var message = inputText.value;
var ref = database.ref("Users");
var data = {
display: massage
}
ref.child(firebase.auth().currentUser.uid).update(data);
}
}
Your code seems correct if you want to insert a new entry in Firebase database (just like your screenshot shows).
But, if you really want to sign up a new user, then you should be using firebase.auth().createUserWithEmailAndPassword() instead.
Finally, if you really want to update an existing node, see Frank response above ;-)
try this. you can change update to set. In your case something like
demo.update("users/KIK...fuA","display","my message");
//REVEALED METHOD TO ADD NODES WITH DATA TO REALTIME DATABASE
//eg, demo.update('mynode','myKey','myValue')
var demo = (function() {
var pub = {};
pub.update = function (node,key,value){
var ref = firebase.database().ref('/');
var obj = {};
obj[key] = value;
ref.child(node).update(obj)
.then(function() {
console.log('Update Ran Successfully');
});
}
//API
return pub;
}());
It is my first time developing a SPA, and I am not using JS frameworks like React, Vue or Angular. My project just uses the firebase sdk and jquery to access the DOM elements.
In my app, the users can be associated with projects. Since that, I have a user-projects and project-users paths to represent that relationship.
When a user logs in my app I request users/uid to get the user data. After that I have to fetch the projects associated with the user. I will take the ids of the associated projects to finally request the data of each project.
I'm trying to use promises as described here, but I get nothing in the console.
function loadUserProjects() {
// Authenticated user
var user = firebase.auth().currentUser;
// General reference to the real time db
var ref = firebase.database().ref();
// Request the user data
ref.child('users/'+user.uid).on('value').then(function(snapshot) {
var user_data = snapshot.val(); console.log(user_data);
// Global variable to store the id of the selected project
project_selected_key = user_data.project_selected;
// Get the list of associated projects
return ref.child('user-projects/'+user.uid).on('value').then(function(snapshot) {
console.log(snapshot);
return snapshot;
});
}).then(function (projectsSnapshot) {
console.log(projectsSnapshot);
// List associated projects
var project_options = '';
projectsSnapshot.forEach(function (e) {
project_options += '<option value="'+e.key+'">'+e.val()+'</option>';
});
if (! project_options) {
project_options = '<option disabled selected value>- Ningún proyecto -</option>';
}
$('#project_selected').html(project_options);
}, function(error) {
// Something went wrong.
console.error(error);
});
}
I know that I have to use one additional request, because at this point the <select>will be populated with truevalues (the additional request have to query the full data of each project). But I am not getting messages in the console.
Thanks in advance.
After that, I need to define different levels of privilege in each project, and associate a level when a project is assigned to a specific user. Initially I was very excited about the real time, but it seems that firebase is getting more complicated than I supposed.
A Firebase on() listener can respond to multiple events. A promise can only resolve once, that's why it's only available when you use Firebase's once() operation.
return ref.child('user-projects/'+user.uid).once('value');
In the Parse JavaScript guide, on the subject of Relational Data it is stated that
By default, when fetching an object, related Parse.Objects are not
fetched. These objects' values cannot be retrieved until they have
been fetched.
They also go on to state that when a relation field exists on a Parse.Object, one must use the relation's query().find() method. The example provided in the docs:
var user = Parse.User.current();
var relation = user.relation("likes");
relation.query().find({
success: function(list) {
// list contains the posts that the current user likes.
}
});
I understand how this is a good thing, in terms of SDK design, because it prevents one from potentially grabbing hundreds of related records unnecessarily. Only get the data you need at the moment.
But, in my case, I know that there will never be a time when I'll have more than say ten related records that would be fetched. And I want those records to be fetched every time, because they will be rendered in a view.
Is there a cleaner way to encapsulate this functionality by extending Parse.Object?
Have you tried using include("likes")?
I'm not as familiar with he JavaScript API as the ObjC API.. so in the example below I'm not sure if "objectId" is the actual key name you need to use...
var user = Parse.User.current();
var query = new Parse.Query(Parse.User);
query.equalTo(objectId, user.objectId);
query.include("likes")
query.find({
success: function(user) {
// Do stuff
}
});
In general, you want to think about reverse your relationship. I'm not sure it is a good idea be adding custom value to the User object. Think about creating a Like type and have it point to the user instead.
Example from Parse docs:
https://parse.com/docs/js_guide#queries-relational
var query = new Parse.Query(Comment);
// Retrieve the most recent ones
query.descending("createdAt");
// Only retrieve the last ten
query.limit(10);
// Include the post data with each comment
query.include("post");
query.find({
success: function(comments) {
// Comments now contains the last ten comments, and the "post" field
// has been populated. For example:
for (var i = 0; i < comments.length; i++) {
// This does not require a network access.
var post = comments[i].get("post");
}
}
});
Parse.Object's {Parse.Promise} fetch(options) when combined with Parse.Promise's always(callback) are the key.
We may override fetch method when extending Parse.Object to always retrieve the relation's objects.
For example, let's consider the following example, where we want to retrieve a post and its comments (let's assume this is happening inside a view that wants to render the post and its comments):
var Post = Parse.Object.extend("Post"),
postsQuery = new Parse.Query(Post),
myPost;
postsQuery.get("xWMyZ4YEGZ", {
success: function(post) {
myPost = post;
}
).then(function(post) {
post.relation("comments").query().find({
success: function(comments) {
myPost.comments = comments;
}
});
});
If we had to do this every time we wanted to get a post and its comments, it would get very repetitive and very tiresome. And, we wouldn't be DRY, copying and pasting like 15 lines of code every time.
So, instead, let's encapsulate that by extending Parse.Object and overriding its fetch function, like so:
/*
models/post.js
*/
window.myApp = window.myApp || {};
window.myApp.Post = Parse.Object.extend("Post", {
fetch: function(options) {
var _arguments = arguments;
this.commentsQuery = this.relation("comments").query();
return this.commentsQuery.find({
success: (function(_this) {
return function(comments) {
return _this.comments = comments;
};
})(this)
}).always((function(_this) {
return function() {
return _this.constructor.__super__.fetch.apply(_this, _arguments);
};
})(this));
}
});
Disclaimer: you have to really understand how closures and IIFEs work, in order to fully grok how the above works, but here's what will happen when fetch is called on an existing Post, at a descriptive level:
Attempt to retrieve the post's comments and set it to the post's comments attribute
Regardless of the outcome of the above (whether it fails or not) operation, always perform the post's default fetch operation, and invoke all of that operation's callbacks