Heap analytics - not seeing custom properties - analytics

I've implemented Heap analytics successfully and i'm seeing data come in.
The way I set a user is:
window.heap.identify(currentUser.id);
window.heap.addEventProperties({ platform_type: 'Web' });
if (currentUser.id) {
console.log('been here');
window.heap.addUserProperties({
'first_name': currentUser.first_name,
'last_name': currentUser.last_name,
'type': currentUser.type,
'country': currentUser.country,
'company_name': currentUser.company_name,
'role': currentUser.role,
'email': currentUser.email
});
}
I'm seeing the Email property data being recorded and associated (Email was a property already pre-defined by Heap), but i'm not seeing any of the other properties.
So, the addUserProperties call is working, but some data is being ignored.
Any idea what i'm doing wrong?
Thanks!
Uri

For anyone with the same problem, for me, the custom properties started appearing after a few hours..

Related

Hide the default Gigya email share popup on click of the Gigya Share bar email icon

I am using the following code to implement the Set up Gigya share bar:
if ($window.gigya) {
// Step 1: Construct a UserAction object and fill it with data
var ua = new $window.gigya.socialize.UserAction();
ua.setLinkBack(articleUrl);
ua.setTitle($scope.title);
// Step 2: Define the Share Bar add-on's params object
var params = {
userAction: ua,
//shareButtons: 'linkedin,twitter,facebook,sina,email', // list of providers
shareButtons: 'linkedin,twitter,facebook,sina,email',
containerID: 'share-bar',
showCounts: 'none',
deviceType: 'auto',
cid: '',
wrap: true,
operationMode:'multiSelect',
onShareButtonClicked:function (e) {
console.log(e);
console.log(e.shareItem.provider);
if (e.shareItem.provider == 'email') {
var mailString = 'mailto:test#example.com'
$window.location.href = mailString;
}
}
};
// Step 3: Load the Share Bar add-on:
$window.gigya.socialize.showShareBarUI(params);
}
The above code displays the share bar provided by Gigya.
Now clicking the email option I am trying to open the default client mail (for example outlook). I see that the default email popup also get opened along with the outlook.
How to stop the default UI from opening in this case. I tried all the options but none are working for me.
Can anyone help me to know how to fix this issue.
I don't believe this behavior is supported. By design, the Share add-on, when sharing via email, constructs the actual message on the server using the UserAction passed in the request and then sends it from there. So, even if you got the default UI to not populate, how would you be getting the actual share data inside the 3rd party email program?

Unable to display $scope in view

I am querying a database and retrieving all the images belonging to the logged-in user, here is that code in uploadController:
UserImage.get($scope.user_id)
.success(function(data) {
$scope.userArray = data;
$location.path('/display');
});
I can console log the value of data and it is (first document):
0: Object
__v: 0
_id: "563bd07c7a49a7ac9ae1c513"
date: "2015-11-05T21:56:12.312Z"
gallery: "first gallery"
name: "1b0f6d56-9ed6-4412-a0d6-897a25fb3a84-460x360.jpeg"
user: "563bd0527a49a7ac9ae1c512"
so now I test that the target view (display.html) can receive the $scope.data:
<<div>{{userArray[0].name}}</div>
The $scope.userArray is not available to the display.html.
I tested the $scope in plunker and it worked ok:
http://plnkr.co/edit/q5XXnfl3JxkRdG0jLyps?p=preview
So I am a bit stumped.
first of all you should use ".then" instead of ".success" to use to promise system. If you want to know more about it
And i think your problem is also connected with $location.path('/display'); you ask your application to change location as soon as you get the answer, so it is probably loading another controller and stopping with your current one.

Include roles in User.login() and User.getCurrent() Angular SDK

I'm currently writing an administrative interface using the Loopback Angular SDK. After having dug through the documentation and code, I'm still no wiser as to how to include the user's roles in the response. It's causing me real headaches on the frontend because I'm not yet experienced enough with Angular to figure out how to enforce a role check on each of my states (I'm using UI-Router).
client: /auth.js
// Log the user in
$scope.doAuth = function() {
$scope.hasError = false;
$scope.busy = true;
$scope.loginResult = User.login({include: 'roles'}, $scope.credentials,
function wasSuccessfulAuth(authResponse) {
$scope.busy = true;
$rootScope.isAuthenticated = true;
$rootScope.user = authResponse.user;
$location.path('dashboard');
},
function wasFailedAuth(authResponse) {
$timeout(function() {
$scope.hasError = true;
$scope.authError = authResponse.data.error.message || 'Unknown error';
$scope.busy = false;
}, 1000);
}
)
}
server: /common/models/user.json
{
"name": "user",
"plural": "Users",
"base": "User",
"properties": {
},
"relations": {
"roles": {
"type": "belongsTo",
"model": "RoleMapping",
"foreignKey": "principalId"
}
},
"acls": [],
"methods": []
}
So this works in the API explorer, I have the routes I'd expect with an object that has a relation, but I can't seem to get any further than that... All that gets returned is the standard user login stuff (id, accessToken, email, etc) The docs seem to run cold when I get this far but I'd have thought this would have been a common use case?
This is a bit of a showstopper for me.
It's actually surprisingly easy to solve this problem using LoopBack: this is where "model scopes" come in very handy -- including the default scope which I find extremely useful for this type of situation.
First, a brief explanation of model scopes:
A model scope is like a saved query or "view", that allows you to specify a built-in filter for any query for that scope. For example, if you set the default scope to a valid filter, every single query (of any kind) against your model will have this filter applied!
This can get you in a heap of trouble, but there's one use-case that's pretty safe (all other things equal) and actually addresses your question perfectly: when I said a scope lets you give a valid filter, it turns out filters aren't just where clauses, but also include, limit, etc.
So to solve your problem, you simply need a default scope on your User model that includes whatever you need to include. For your example:
Simply add a scope object to your common/models/user.json:
{
"name": "user",
"plural": "Users",
"base": "User",
"scope": {
"include": [
"roles"
]
},
"properties": {
},
"relations": {
"roles": {
"type": "belongsTo",
"model": "RoleMapping",
"foreignKey": "principalId"
}
},
"acls": [],
"methods": []
}
By adding a default scope with an "include", LoopBack will automatically embed the object(s) of the related model based on the named relation (just like if you added it in your query -- which as discussed, is not possible, or at least not easy, in this case).
One caveat: since Role and RoleMapping are built-in models and are surely marked as non-public, I am not actually sure whether you can include them directly (but for a different reason than above). I haven't worked enough with ACLs (yet), but presumably there's more complexity around access controls especially in related models.
So, whereas my example code above explain the mechanics of doing the include here, the policy concern may slow you down (I'd be curious to know if they do).
That said, however, I guess you could add a derived model (from RoleMapping) that you make public (just like you did for user), and use it instead everywhere (including in the relation to/from user) -- hopefully that's clear (let me know if not).
In conclusion: If you add a default scope to your derived user model, to do the include for you, the AngularJS service wrapper (built by lb-ng) will be none the wiser (the include all happens on the backend):
$scope.loginResult = User.login($scope.credentials,
function wasSuccessfulAuth(authResponse) {
console.log('Related models are here: ', authResponse.roles,
authResponse.user);
...
In other words, the resulting model will contain an array, .roles[], containing the related roles to this user (based on your relation definition), and .user with the entire user model right there!
This latter point is unclear but I'm confident in that, because I did exactly the above but with a different related model that I know works. And to my surprise, user was included as well, since that's explicitly requested by the LoopBack $resource wrapper (the one created by lb-ng). So, in fact, you don't have do a separate query to get the user -- it's already there! There's no API that I see when using the $service wrapper, to get at that built-in include and change it; I guess that's what was posted in a comment above.
Hope this is helpful.
Steve
User.login returns AccessToken instance. To get user role, you should make separate request to fetch user, including role.

cakephp hidden field issue

I have a problem with an input field in a view called add.ctp. When the input type is set to 'text', the program sequence is normal. But when I change the input type to 'hidden', the following error is displayed:
The request has ben black-holed. Error: The requested address was not found on this server.
mod-rewrite seems activated. Any ideas, what can be the reason for this?
There is no error with your code. CakePHP's Security component checks hidden form fields to prevent tampering by end users:
By default SecurityComponent prevents users from tampering with forms. It does this by working with FormHelper and tracking which files are in a form. It also keeps track of the values of hidden input elements. All of this data is combined and turned into a hash. When a form is submitted, SecurityComponent will use the POST data to build the same structure and compare the hash.
Use FormHelper::unlockField to make a field exempt from this feature:
$this->Form->unlockField('User.id');
This means there is an error with your code. Here is how to create hidden textbox
echo $this->Form->input('field_name', array('type'=>'hidden'));
I think It's because you are using SecurityComponent.
THe component monitor the form integrity, the hidden field shouldn't change from the user and because of that the security component "decide" that the something malicious has been done with the form for example CSRF attack and it prevent the submit. And I believe you are having some JavaScript which change the field value for some reason.
CakePHP 3
Please do not unlock fields/disable CSRF security component for any
particular action. This is important for the form security.
for those who are getting "The request has been black-holed."
,"form tampered error", "you are not authorized to access
that location." or "unexpected field in POST data". It is
mainly due to the CSRF component working as expected.
Disabling or modifying it is not a solution. Instead of disabling, please follow the right approach.
The right way should be as below:
On the Form, Add a hidden field as below.
<?= $this->Form->text('TPCalls.ID',['label' => false, 'class' => 'hidden']); ?>
before AJAX add the field
$("input[name='TPCalls[ID]']").val(event.id);
Then serialise it
var el = $("#xyzForm");
var ajaxTPCalls = el.serializeArray();
$.ajax({
type: el.attr('method'),
async: true,
url: el.attr('action'),
data: ajaxTPCalls,
dataType: "json",
cache: false,
success: function (data) {
toastr.success(data.message, data.title);
},
error: function (jqXHR) {
if (jqXHR.status == 403) {
$("body").html(jqXHR.responseText);
}
}
});
This way you do not disable CSRF or unlock any field. Any suggestions welcome.

How to stop models being overwritten on refresh in backbone.js

I have a collection of user models that starts with basic data:
[
{'_id': 1, 'username': 'Jamie', 'image': 'jamie.jpg'},
{'_id': 2, 'username': 'Andrew', 'image': 'andrew.jpg'},
{'_id': 3, 'username': 'Kerry', 'image': 'kerry.jpg'}
];
but when a user clicks on the collection models view I load more data into the model so then I can create a profile view of the data:
{
'_id' : 1,
'username' : 'Jamie',
'image' : 'jamie.jpg',
'age' : 21,
'country' : 'UK'
};
I have set it up so that when the full profile data has been loaded it wont be fetched again to save on GET requests.
However I have a refresh button on the main users view so and when I refresh the data all the loaded profile data is gone and I am required to make GET requests to get the information back.
I was wondering how I would go about solving this problem.
More details:
The purpose of the refresh button is to add new online users. I want this button so users who want to see new data will use this instead of refreshing the whole page.
The problem with wiping the loaded data is when a user goes back to the profile (which will happen a lot because I am going to add the ability to chat on each profile which requires the user to be on that users profile) there is an unnecessary GET requests because the data has already been loaded previously in the users session.
Running .fetch({add:true}) would avoid overwriting existing models, but then you'd be left with duplicates. To weed out duplicates and add new models to the collection, you'll need to combine .fetch({add:true}) with a custom parse() function:
parse: function(response) {
var client_ids = _.map(allUsers,function(user){ return user.get('id'); });
response = _.filter(response,function(user){
// true if user is not already in collection
return _.indexOf(client_ids,user.id) < 0;
});
return response;
}
I don't have any way to test this right now, so please try it out and let me know if it works.

Resources