Sync data using Firebase and Ace Editor - firebase

After watching a demo on Firebase, I jumped in and tried to worked on an idea, collaboration on the same document. Turns out they already have Firepad as an example, but I still wanted to work on my own to better understand how Firebase works.
Using jQuery and Ace Editor, I'm able to create new documents but I find it hard to update once I started integrating Ace.
But then I'm getting an error from firebase.js
too many recursions
Changing the data on Firebase Forge automatically reflects on my page, but I cant seem to push my changes back to Firebase. Any ideas on how you'd pull this off?
--- EDIT---
Here's a sample code for a better view of what I'm working on.
var fileRef = new Firebase('https://user.firebaseio.com/document/body');
var editor = ace.edit("codepad");
editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/php");
fileRef.on('value', function(snapshot){
var file = snapshot.val();
editor.setValue(snapshot.val());
});
editor.getSession().on('change', function(e) {
fileRef.set(editor.getValue());
});

Related

Linking images from Firebase Storage to Firestore document and displaying them in React Native

Background
I'm trying to upload images to firebase storage manually (using the upload file button in the web page), however I have no clue how to later link them to a firestore document. What I have come up with (I'm unsure if it works) is copying the url for the image in the storage bucket and adding it to a string type field in the document called profilePicture. The reason I'm unable to get this to work is that I'm really new to React Native and I don't know how to properly require the images other than typing in the specific local route. Mind you also, the way I'm requiring user data such as a profile name is after logging in with email/password auth I pass the data as a param to react navigation and require it as extraData.
What I have tried
Once I've copied the image url and pasted it in the firestore document I'm doing this:
const profilePicture = props.extraData.profilePicture;
<Image source={require({profilePicture})}/>
I have also tried using backticks but that isn't working either. The error message I'm getting is:
TransformError src\screens\Profile\ProfileScreen.js: src\screens\Profile\ProfileScreen.js:Invalid call at line 27: require({
profilePicture: profilePicture
})
Note: this is an expo managed project.
Question
Is the problem in the code or in the way I'm linking both images? Maybe both? Should I require the document rather than relying on the data passed previously?
Thanks a lot in advance!
Edit 1:
I'm trying to get all info from the current user signed in, after a little research I've come to know about requiring images in this manner:
const ref = firebase.storage().ref('path/to/image.jpg');
const url = await ref.getDownloadURL();
and then I'd require the image as in <Image source={{uri: url}}/>
I get that this could be useful for something static, but I don't get how to update the ref for every single different user.
Edit 2:
Tried using the method mentioned in Edit 1, just to see what would happen, however It doesn't seem to work, the image just does not show up.
Maybe because my component is a function component rather than a class component (?
I understand that your goal is to generate, for each image that is uploaded to Cloud Storage, a Firestore document which contains a download URL.
If this is correct, one way is to use a Cloud Function that is triggered each time a new file is added to Cloud Storage. The following Cloud Function code does exactly that. You may adapt it to your exact requirements.
exports.generateFileURL = functions.storage.object().onFinalize(async object => {
try {
const bucket = admin.storage().bucket(object.bucket);
const file = bucket.file(object.name);
// You can check that the file is an image
const signedURLconfig = { action: 'read', expires: '08-12-2025' }; // Adapt as follows
const signedURLArray = await file.getSignedUrl(signedURLconfig);
const url = signedURLArray[0];
await admin.firestore().collection('profilePictures').add({ fileName: object.name, signedURL: url }) // Adapt the fields list as desired
return null;
} catch (error) {
console.log(error);
return null;
}
});
More info on the getSignedUrl() method of the Admin SDK here.
Also note that you could assign the Firestore document ID yourself, instead of having Firestore generating it as shown in the above code (with the add() method). For example, you can add to the image metadata the uid of the user and, in the Cloud Function,get this value and use this value as the Document ID.
Another possibility is to name the profile image with the user's uid.

Firebase Analytics preventing proper use of dynamic link

I'm running in trouble here with Firebase.
The code is in flutter, I am testing in iOS
It's all going well, but when I try to get the dynamic link sent from:
auth.sendSignInWithEmailLink(parameters);
I get a debug message:
[Firebase/Analytics][I-ACS023001] Deep Link does not contain valid required params. URL params: {
amv = 16;
apn = "com.myproject.app";
ibi = "com.myproject.app";
ifl = "https://myproject-com.firebaseapp.com/__/auth/action?apiKey=XXXXXXXXXXX&mode=signIn&oobCode=XXXXXX&continueUrl=https://myproject-com.firebaseapp.com/email123&lang=en";
link = "https://myproject-com.firebaseapp.com/__/auth/action?apiKey=XXXXXXX&mode=signIn&oobCode=XXXXXX&continueUrl=https://myproject-com.firebaseapp.com/email123&lang=en";
}
where I changed my project name to "myproject" and put XXX inplace of apiKey/oobcode
and then, when I try to get the dynamic link with my app
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
data is null.
So I am guessing Firebase Analytics is processing it and "killing" the dynamic link before my app can parse it.
Anyone managed to go through this?
I found the problem.
It is not that Firebase Analytics was "consuming" and killing the deep link.
The thing is that in iOS still today there is a delay the link and the state cycle...
https://medium.com/#diegoveloper/flutter-firebase-dynamic-link-6f1b79278ce0
This link explains it, problem 2 in the blog post.
Solved. I can still use analytics in Firebase.
It is impossible to remove analytics btw, you can only disable it.

Firebase Full-Text Search using Algolia

I configured different firebase functions by following this
. Now in this, there is firebase full-text search. I tried to follow it but it seems to be incomplete. I have searched and somehow got success in deploying. But it is still not creating index in Algolia. Can someone tell me the steps to correctly perform this?
I created the blog-posts and search nodes in my firebase project but problem is still there.
CODE:
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// Authenticate to Algolia Database.
// TODO: Make sure you configure the `algolia.app_id` and `algolia.api_key` Google Cloud environment variables.
const algoliasearch = require('algoliasearch');
const client = algoliasearch(functions.config().algolia.app_id, functions.config().algolia.api_key);
// Name fo the algolia index for Blog posts content.
const ALGOLIA_POSTS_INDEX_NAME = 'blogposts';
// Updates the search index when new blog entries are created or updated.
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
const firebaseObject = {
text: event.data.val(),
objectID: event.params.blogid
};
return index.saveObject(firebaseObject).then(
() => event.data.adminRef.parent.child('last_index_timestamp').set(
Date.parse(event.timestamp)));
});
// Starts a search query whenever a query is requested (by adding one to the `/search/queries`
// element. Search results are then written under `/search/results`.
exports.searchentry = functions.database.ref('/search/queries/{queryid}').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
const query = event.data.val().query;
const key = event.data.key;
return index.search(query).then(content => {
const updates = {
'/search/last_query_timestamp': Date.parse(event.timestamp)
};
updates[`/search/results/${key}`] = content;
return admin.database().ref().update(updates);
});
});
SEE IMAGE OF FIREBASE NODE
Open Image
Your help will be appreciated. Thanks
So I used the sample code provided here and placed it into a Firebase cloud function. Writing to '/blog-posts/{blogid}/text' inside the database should index whatever value is under text to Algolia.
There are a few things that might be going wrong here:
Check that your function is correctly placed into Firebase. You can do this from the console by clicking functions on the left side. You should see two functions named indexentry and searchentry. If you do not see those functions then you haven't correctly pushed your code to the Firebase cloud.
If you code is in Firebase cloud then I recommend adding console.log("write on blog-posts fired"); to your searchentry function. Then write some more data to your database under '/blog-posts/{blogid}/text'. You can check the function log in the Firebase console. I have noticed a slight delay in log records displaying some times, so be patient if you don't see it right away. I'd write a few pieces of data to '/blog-posts/{blogid}/text' then after a couple minutes I'd check the log. If the log has "write on blog-posts fired" in it then you know the function is being activated when you write to the database.
If all the above is operating correctly and you still don't have any data in Algolia then make sure you set your API keys. You can do this using the code firebase functions:config:set algolia.app_id="myAlgoliaAppId" algolia.api_key="myAlgoliaApiKey". You run this command in a terminal window inside the directory where you have your Firebase cloud functions. You can get you API keys by signing into your account. Remember not to share your API key with anyone.

Firebase and Angularfire nightmare migration for Update

I am new to firebase and I am having a bit of a nightmare trying to adapt old code to what is now deprecated and what is not. I am trying to write a function which updates one "single" record in my datasource using the now approved $save()promise but it is doing some really strange stuff to my data source.
My function (should) enables you to modify a single record then update the posts json array. However, instead of doing this, it deletes the whole datasource on the firebase server and it is lucky that I am only working with testdata at this point because everything would be gone.
$scope.update = function() {
var fb = new Firebase("https://mysource.firebaseio.com/Articles/" + $scope.postToUpdate.$id);
var article = $firebaseObject(ref);
article.$save({
Title: $scope.postToUpdate.Title,
Body: $scope.postToUpdate.Body
}).then(function(ref) {
$('#editModal').modal('hide');
console.log($scope.postToUpdate);
}, function(error) {
console.log("Error:", error);
});
}
Funnily enough I then get a warning in the console "after" I click the button:
Storing data using array indices in Firebase can result in unexpected behavior. See https://www.firebase.com/docs/web/guide/understanding-data.html#section-arrays-in-firebase for more information. Also note that you probably wanted $firebaseArray and not $firebaseObject.
(No shit?) I am assuming here that $save() is not the right call, so what is the equivalent of $routeParams/$firebase $update()to do a simple binding of the modified data and my source? I have been spending hours on this and really don't know what is the right solution.
Unless there's additional code that you've left out, your article $firebaseObject should most likely use the fb variable you created just before it.
var article = $firebaseObject(fb);
Additionally, the way in which you're using $save() is incorrect. You need to modify the properties on the $firebaseObject directly and then call $save() with no arguments. See the docs for more.
article.Title = $scope.postToUpdate.Title;
article.Body = $scope.postToUpdate.Body;
article.$save().then(...

When I connect to firebase, I only see the structures and no devices (Nest API)

I am trying to read basic information about thermostats using the methods in the thermostat control example (https://developer.nest.com/documentation/control), but when I connect to firebase I only see the structure object (which only contains name, away, smoke_co_alarms, structure_id and thermostats) in the snapshot– There is no devices object. I am connecting to firebase using
var nestToken = $.cookie('nest_token');
var dataRef = new Firebase('wss://developer-api.nest.com/');
dataRef.auth(nestToken);
I tried to connect directly to devices using wss://developer-api.nest.com/devices, but that only returns an undefined data-structure.
I've also tried connecting to firebase using https://developer-api.nest.com/ and https://developer-api.nest.com/, but they raised an authorization error and caused my javascript to go into an infinite loop sending requests.
I'm reading data using:
dataRef.on('value', function (snapshot) {
var data = snapshot.val();
structure = firstChild(data.structures);
console.log(data);
console.log(data.structures);
console.log(data.devices);
console.log(data.devices.thermostats);
console.log(structure.thermostats);
};
Lastly, I tried it on an account with real devices and one with virtual devices, so I know that couldn't be causing it (even though I didn't expect it to).
Any ideas what I am doing wrong? The issue couldn't be in my App.js file, could it? Is there some configuration I need to do on the user's end in addition to the authentication? I get the feeling it's probably something really simple that's staring me in the face.
So I figured it out: It's a permissions issue. When my client-profile was setup, it only requested permission to read the away/home status. So when I query Firebase it only returns the a snapshot with structure because that is where the away/home status can be read. So, in summary, if you're not seeing the devices structure, even though devices are associated with the user, check your client permissions.
Using (some of) your code, I have no trouble seeing the devices object:
var dataRef = new Firebase('wss://developer-api.nest.com');
dataRef.auth(nestTokenLive);
dataRef.on('value', function (snapshot) {
var data = snapshot.val();
console.log(data);
console.log(data.devices);
});
Results in:
> Object {devices: Object, structures: Object}
> Object {thermostats: Object}

Resources