Search information by user on firebase - search

This is probably very simple ,so sorry...
I'm trying to create an application where i can create users and store informations by Firebase. There is an example here :
http://image.noelshack.com/fichiers/2015/11/1426182307-log.png
But now I want to check if the name already exists if someone wants to create a new user.
How would I go about grabbing individual user information without knowing their id , like simplelogin:54?
I've found this topic Get users by name property using Firebase but it is not the same thing because in my case I don't know the children after "Users"
Cheers,

Like Frank said, you must know something about the user to be able to look her/him up.
However, here is a general answer. I am assuming that by "name" you mean the property "identifiant" that you've created.
Suggestions
Start by looking over the Firebase Query documentation.
Short Answer
To check if a user exists by the identifiant property, you'd orderByChild("identifiant") and query for a specific user with the .equalTo("<identifient_here>").
For example, to check if a user with identifient="aaa",
var usersRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users");
var identifient = "aaa";
usersRef.orderByChild("identifiant").equalTo(identifient).once("value", function(snapshot) {
console.log("Loaded user by identifient:",identifient,snapshot.val());
});
If instead you want to query by the key (such as simplelogin:53), you could query by using orderByKey() instead of orderByChild()... or just simply setting the ref to the user's key like so:
var userKey = 'simplelogin:53';
var userRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users" + userKey);
userRef.once("value", function(snapshot) {
console.log("Loaded user",snapshot.val());
});
Long(er) Answer
You can handle this with a user factory (see Angular Providers documentation).
You return a promise in the factory using the $q service.
Here is the Angular API documentation for $q.
Example with UserFactory
Check out this working PLNKR example.
It's tied to one of my public Firebase instances.
I created the same simplelogin:53 user in /Users like you have.
If you search for the identifient = aaa, you'll get the right user.
The controller implementation here is for example purposes, and doesn't really do anything worth while. It's just for reference.
The Data
{
"Users" : {
"simplelogin:53" : {
"identifiant" : "aaa"
}
}
}
UserFactory
.factory('UserFactory', function($q, $firebaseObject, fbUrl){
return function(userId){
var deferred = $q.defer();
if (userId.isNotEmpty()) {
var userRef = new Firebase(fbUrl + '/Users/').orderByChild("identifiant").equalTo(userId);
userRef.once("value",
function(dataSnapshot){
if (dataSnapshot.val()) {
console.log("Loaded user",dataSnapshot.val());
deferred.resolve(dataSnapshot.val());
} else {
console.info("Couldn't find user by id",userId);
deferred.reject("No user found by identifient = '"+userId+"'");
}
},
function(error){
console.error("Error loading user",error);
deferred.reject(error);
}
);
} else {
deferred.reject("No id entered!");
}
return deferred.promise;
}
})
Controller
.controller('HomeController',function($scope, UserFactory) {
$scope.identifient = '';
var showError = function(errorMessage) {
if (errorMessage) {
showUser(false);
$scope.error = errorMessage;
} else {
delete $scope.error;
}
}
var showUser = function (userObject) {
if (userObject) {
showError(false);
$scope.user = userObject;
} else {
delete $scope.user;
}
}
$scope.loadUser = function() {
var userPromise = new UserFactory($scope.identifient);
userPromise.then(function(data){
showUser(data);
}).catch(function(error){
showError(error);
});
}
})
Template
<div ng-controller="HomeController">
<h2>Home Template</h2>
<input ng-model="identifient" placeholder="identifient"/>
<button ng-click="loadUser()">Find User</button>
<hr/>
<div ng-if="user">User: {{user}}</div>
<div ng-if="error">Error: {{error}}</div>
</div>
Hope that helps.

Related

Trying to get id parameter with nodejs and acces it in angular

I am trying to access a detail page that i have for a list of items in my html(ionic). So when I click on 1 item I need to go on a detail page with information about that specific item. I am using mongo database for the items , the model of the items are : name and ingredients.
I am stuck here and don't know what to do , please help if you have a bit of time , thank you.
My code :
<ion-list *ngFor="let recipe of recipes ; let i = index">
<ion-item>
<ion-label>{{recipe.name}}</ion-label>
</ion-item>
</ion-list>
Request for the database trying to get the id to access the item (I get the
public findByName(id: string) {
return this.http.get<any>(
"http://localhost:9020/:id" + id
);
}
This is what I tried in typescript
this.route.paramMap.subscribe((paramMap) => {
if (!paramMap.has("id")) {
this.navCtrl.navigateBack("/home");
return;
}
this._recipeDetail = this.nutService
.findByName(paramMap.get("id"))
.subscribe((id) => {
this.id = id;
});
});
Also in route module :
{
path: "name/:id",
loadChildren: () =>
import("./r-d/r-d.module").then(
(m) => m.RDPageModule
),
},
But its not working , maybe I don't have the right approach? Can someone please guide me a bit ?
Thank you for your time
this._recipeDetail = this.nutService
.findByName(paramMap.get("id"))
.subscribe((id) => {
this.id = id;
});
You should be expecting your api to return you the recipeDetail.. you are not storing it properly.
this.nutService.findByName(paramMap.get("id"))
.toPromise().then((data) => {
this.recipeDetail = data;
});
And then, you can display your recipeDetail inside your template. I have also changed .subscribe() to .toPromise().then(). This is a better approach to avoid memory leaks in your app.

How to provide custom names for page view events in Azure App Insights?

By default App Insights use page title as event name. Having dynamic page names, like "Order 32424", creates insane amount of event types.
Documentation on the matter says to use trackEvent method, but there are no examples.
appInsights.trackEvent("Edit button clicked", { "Source URL": "http://www.contoso.com/index" })
What is the best approach? It would be perfect to have some sort of map/filter which would allow to modify event name for some pages to the shared name, like "Order 23424" => "Order", at the same time to leave most pages as they are.
You should be able to leverage telemetry initializer approach to replace certain pattern in the event name with the more "common" version of that name.
Here is the example from Application Insights JS SDK GitHub on how to modify pageView's data before it's sent out. With the slight modification you may use it to change event names based on their appearance:
window.appInsights = appInsights;
...
// Add telemetry initializer
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(function (envelope) {
var telemetryItem = envelope.data.baseData;
// To check the telemetry item’s type:
if (envelope.name === Microsoft.ApplicationInsights.Telemetry.PageView.envelopeType) {
// this statement removes url from all page view documents
telemetryItem.url = "URL CENSORED";
}
// To set custom properties:
telemetryItem.properties = telemetryItem.properties || {};
telemetryItem.properties["globalProperty"] = "boo";
// To set custom metrics:
telemetryItem.measurements = telemetryItem.measurements || {};
telemetryItem.measurements["globalMetric"] = 100;
});
});
// end
...
appInsights.trackPageView();
appInsights.trackEvent(...);
With help of Dmitry Matveev I've came with the following final code:
var appInsights = window.appInsights;
if (appInsights && appInsights.queue) {
function adjustPageName(item) {
var name = item.name.replace("AppName", "");
if (name.indexOf("Order") !== -1)
return "Order";
if (name.indexOf("Product") !== -1)
return "Shop";
// And so on...
return name;
}
// Add telemetry initializer
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(function (envelope) {
var telemetryItem = envelope.data.baseData;
// To check the telemetry item’s type:
if (envelope.name === Microsoft.ApplicationInsights.Telemetry.PageView.envelopeType || envelope.name === Microsoft.ApplicationInsights.Telemetry.PageViewPerformance.envelopeType) {
// Do not track admin pages
if (telemetryItem.name.indexOf("Admin") !== -1)
return false;
telemetryItem.name = adjustPageName(telemetryItem);
}
});
});
}
Why this code is important? Because App Insights use page titles by default as Name for PageView, so you would have hundreds and thousands of different events, like "Order 123132" which would make further analysis (funnel, flows, events) meaningless.
Key highlights:
var name = item.name.replace("AppName", ""); If you put your App/Product name in title, you probably want to remove it from you event name, because it would just repeat itself everywhere.
appInsights && appInsights.queue you should check for appInsights.queue because for some reason it can be not defined and it would cause an error.
if (telemetryItem.name.indexOf("Admin") !== -1) return false; returning false will cause event to be not recorded at all. There certain events/pages you most likely do not want to track, like admin part of website.
There are two types of events which use page title as event name: PageView
and PageViewPerformance. It makes sense to modify both of them.
Here's one work-around, if you're using templates to render your /orders/12345 pages:
appInsights.trackPageView({name: TEMPLATE_NAME });
Another option, perhaps better suited for a SPA with react-router:
const Tracker = () => {
let {pathname} = useLocation();
pathname = pathname.replace(/([/]orders[/])([^/]+), "$1*"); // handle /orders/NN/whatever
pathname = pathname.replace(/([/]foo[/]bar[/])([^/]+)(.*)/, "$1*"); // handle /foo/bar/NN/whatever
useEffect(() => {
appInsights.trackPageView({uri: pathname});
}, [pathname]);
return null;
}

How Express routes similar url links?

Developing web app with node.js and express.
I have following two urls to distinguish:
/api/v1/source?id=122323
/api/v1/source?timestamp=1555050505&count=10
I come up a naive solution. I leave such similar urls to one route method and use if eles to specify solutions, i.e:
if(id){
//solution with id
}
if(timestamp&&count){
//solution with timestamp and count but without id
}
Apparently, this is not clean. Because in the future,I may want to add new field which will make this router huge and ugly.
So How can I overcome this? Or to change url structure.I want to build a Restful api.
Try to put together all the properties in a list and use Array#every to check if all the values in Array evaluates to true.
Maybe something like this:
(( /* req, res */)=>{
// Dummy express Request Object
const req = {
params : {
//id : '123',
count : 10,
timestamp : 1555050505,
newParameter : 'whatever value'
}
}
let { params } = req;
let {
id
, count
, timestamp
, newParameter
} = params;
if(id){
console.log('Action with id');
return;
}
let secondConditionArray = [
count, timestamp, newParameter
];
if( secondConditionArray.every(Boolean) ){
console.log('Second Action')
} else {
console.log('Some values are no truthy')
}
})()
You can get Url parameters with req.params
if(req.params.id){
//solution with id
}
if(req.params.timestamp && req.params.count){
//solution with timestamp and count but without id
}

Migrating to FlowRouter, need something similar to a template data context

So I've read a lot on the discussion of Iron Router vs FlowRouter.
I started my project using Iron Router, but since changed my mind and I'm currently migrating to FlowRouter.
Everything was going smoothly until I started migrating the comments section of my app. You see, this section is reused several times on the app, it serves as a comment section for news, posts, photos, videos, etc.
Example using IR's data context:
Router.route('/news/:slug', {
name: 'newsItem',
waitOn: function() { Meteor.subscribe('news.single', this.params.slug) },
data: function() {
return News.findOne({slug: this.params.slug});
}
});
<template name="newsItem">
<p>{{title}}</p>
<p>{{body}}</p>
{{> commentSection}}
</template>
The Comment collection schema has a "type" (to know to what type of "thing" this comment belongs to, news, photos, etc). That type was set on the "form .submit" event of commentSection template. Example:
'submit form': function(e, template) {
e.preventDefault();
var $body = $(e.target).find('[name=body]');
console.log(template.data.type);
var comment = {
type: template.data.type,
parentId: template.data._id,
parentSlug: template.data.slug,
body: $body.val()
};
Meteor.call('insertComment', comment, function(error, commentId) {
if (error){
alert(error.reason);
} else {
$body.val('');
}
});
}
This worked because the template data context contained the News item which in turn has a a type property as well.
How could I achieve something similar to this only using Flow Router without setting data on the template as it is recommended by the official guide?
You'll want to use a template subscription and a {{#with}} helper probably.
Template.newsItem.onCreated( function() {
Template.instance().subscribe('news.single', FlowRouter.current().params.slug);
});
Template.newsItem.helpers({
item() {
let item = News.findOne();
if( item ) {
return item;
}
}
});
<template name="newsItem">
{{#with item}}
<!-- Your existing stuff -->
{{/with}}
</template>

Node.js & Express: Need to redirect to specific pages based on POST values (using MongoDB)

I am creating a blog with Node, Express and MongoDB. I'm using Mongoose to connect to MongoDB.
I have a create new post form that creates and saves new posts in MongoDB just fine.
When creating a post you can mark the post as published or leave that option unchecked. When you save the post I want you to either:
A) Be redirected to the home page if the post was published, or
B) be redirected to the post's edit/update page if the post was not marked to be published.
Here's the code in the view that I'm trying to use to accomplish the above:
addPost: function(req, res) {
return new Post(req.body.post).save(function() {
if (req.body.published === true) {
return res.redirect("/");
} else {
return res.redirect("/office/post/" + [NEED OBJECT ID HERE] + "/edit");
}
});
}
This is the corresponding view that sends the POST data:
form.web-form(method="post", action="/post/new")
fieldset.fieldset
label.form-label(for="title") Title
input.text-input(id="title", type="text", name="post[title]", placeholder="Post title")
input.text-input(id="alias", type="hidden", name="post[alias]")
label.form-label(for="subhead") Subhead
input.text-input(id="subhead", type="text", name="post[subhead]", placeholder="Post subhead")
label.form-label(for="preview") Preview
textarea.text-area(id="preview", name="post[preview]", rows="4", placeholder="Preview")
label.form-label(for="post-body") Body
textarea.text-area(id="post-body", name="post[body]", rows="5", placeholder="Main content")
input.check-box(onclick="changeButton()", id="published", type="checkbox", name="post[published]")
label.inline-label(for="published") Publish
input.btn-submit(id="submit-post", type="submit", value="Save!")
a.btn-cancel(href="/") Cancel
Any help is greatly appreciated! Thanks!
Like this?
addPost: function(req, res) {
// strip 'post[' and ']' from submitted parameters
var params = {};
for (var k in req.body)
{
params[k.substring(5, k.length - 1)] = req.body[k];
};
var post = new Post(params);
return post.save(function() {
if (params.published === true) {
return res.redirect("/");
} else {
return res.redirect("/office/post/" + post._id + "/edit");
}
});
}

Resources