In Applozic/Ionic integrated app, I need to get last message and time of chat for a user or group
I have read documentation for Applozic - Ionic integration but have not found a solution for above. It only mentions below
//Get Total Unread Count
applozic.getUnreadCount(function(response){
var count = response;
},
function(error){alert(error)
});
//Get Unread count per user
var userId = 'USER_ID'; //pass UserId with which unread count
applozic.getUnreadCountForUser(userId,function(response){
var count = response;
},
function(error){alert(error)
});
//Get unread count per group
var groupId = 'GROUP_ID'; // pass groupId in which unreadcount required
applozic.getUnreadCountForGroup(groupId,function(response){
var count = response;
},
function(error){
});
Currently there is no method that provides the latest message for a particular user or group. But you can get the latest messages for all the contacts and group that the user has inititated a chat with OR get all the messages for a particular contact or group. For this there is a function in the plugin - getConversationList().
>>Getting Conversation List for particular contact/group:
Follow the below steps to get the messages for a particualar contact/group:
1)Create a messageListModel object:
var messageListModel = {
'startTime' : null, //start time
'endTime' : null, //end time
'contactId' : <your-contact-id>, //(this is string) pass contact id to get the message list for that contact
'searchString' : null, // pass the search string to get the latest messages that match the search string
'channelKey' : <your-group-id>, //(this is number) pass the channel key to get the message list for that channel
'conversationId' : null,
'isScroll' : false, //is scroll will be false if you want to get all list of chats
'isSkipRead' : false,
};
2) Pass this object to the getConversationList() function:
applozic.getConversationList(messageListModel, (conversationList)=> {
console.log(JSON.stringify(conversationList))
}, ()=>{});
You would receive a conversationList in the onSuccess callback function.
3) The conversation object has three objects:
a) Message - Message for a particular contact/group
b) Contact - would be null if the message is from group
c) Channel - would be null if the message is for a contact
So in your case you would receive a list of Conversations with the same Contact/Channel that you have passed in the messageListModel object. The last Conversation in the list is what you are looking for.
>>>Getting Latest Messages for all contacts/group:
You could also get the latest messages for all contacts/group that the user has inititated the chat with. Just like whatsapp homescreen.
1)Create a messageListModel object:
var messageListModel = {
'startTime' : null, //start time
'endTime' : null, //end time
'contactId' : null, //pass contact id to get the message list for that contact
'searchString' : null, // pass the search string to get the latest messages that match the search string
'channelKey' : null, // pass the channel key to get the message list for that channel
'conversationId' : null,
'isScroll' : false, //is scroll will be false if you want to get all list of chats
'isSkipRead' : false,
};
2) Pass this object to the getConversationList() function:
applozic.getConversationList(messageListModel, (conversationList)=> {
console.log(JSON.stringify(conversationList))
}, ()=>{});
You would receive a conversationList in the onSuccess callback function.
3) The conversation object has three objects:
a) Message - latest message for contact/group
b) Contact - would be null if the message is from group
c) Channel - would be null if the message is for a contact
You could find for the contact/channel in this list and get the message for that.
The Conversation list is sorted in descending order of the time a message was created. Just like What you see in whatsapp home screen. Latest messages are on top. So if your contact falls out of the top 60 conversations you need to make the call again but this time passing the latest message's createdAtTime in the message list model object like below, this would give you the batch of next 60 conversations:
var messageListModel = {
'startTime' : null, //start time
'endTime' : null, //end time
'contactId' : null, //pass contact id to get the message list for that contact
'searchString' : null, // pass the search string to get the latest messages that match the search string
'channelKey' : null, // pass the channel key to get the message list for that channel
'conversationId' : null,
'isScroll' : false, //is scroll will be false if you want to get all list of chats
'isSkipRead' : false,
'createdAtTime' : conversationList[conversationList.length - 1].message.createdAtTime;
};
How to get the Time of the message:
To get the time of the message you could do:
conversationList[index].message.createdAtTime;
Below are all the properties of the above used objects for your convenience.
Properties of Conversation object:
interface Conversation{
message : Message;
contact : Contact;
channel : Channel;
}
Properties of Message object:
interface Message{
createdAtTime : number;
to : string;
message : string;
key : string;
deviceKey : string;
userKey : string;
emailIds : string;
shared : boolean;
sent : boolean;
delivered : boolean;
type : number;
storeOnDevice : boolean;
contactIds : string;
groupId : number;
scheduledAt : number;
source : number;
timeToLive : number;
sentToServer : boolean;
fileMetaKey : string;
filePaths : string[];
pairedMessageKey : string;
sentMessageTimeAtServer : number;
canceled : boolean;
clientGroupId : string;
messageId : number;
read : boolean;
attDownloadInProgress : boolean;
applicationId : string;
conversationId : number;
topicId : string;
connected : boolean;
contentType : number;
status : number;
hidden : boolean;
replyMessage : number;
fileMeta : FileMeta;
metadata : Map<string,string>;
}
interface FileMeta{
key : string;
userKey : string;
blobKey : string;
name : string;
url : string;
size : number;
contentType : string;
thumbnailUrl : string;
createdAtTime : number;
}
Properties of a contact object:
interface Contact{
firstName : string;
middleName : string;
lastName : string;
emailIdLists : string[];
contactNumberLists : string[];
phoneNumbers : Map<string, string>;
contactNumber : string;
formattedContactNumber : string;
contactId : number;
fullName : string;
userId : string;
imageURL : string;
localImageUrl : string;
emailId : string;
applicationId : string;
connected : boolean;
lastSeenAtTime : number;
checked : boolean;
unreadCount : number;
blocked : boolean;
blockedBy : boolean;
status : string;
userTypeId : number;
contactType : number;
deletedAtTime : number;
latestMessageAtTime : number;
}
Properties of a Channel object:
interface Channel{
key : number;
parentKey : number;
clientGroupId : string;
name : string;
adminKey : string;
type : number;
unreadCount : number;
userCount : number;
subGroupCount : number;
imageUrl : string;
notificationAfterTime : number;
localImageUri : string;
contacts : Contact[];
}
Related
I keep seeing "lower-bounds (failed: Unbound type constructor Yojson.Basic.t)" when trying to publish to opam.
When I clicked the link and read the content, I see the below:
# 59 | web_config -> string -> string -> string -> int * Yojson.Basic.t
# ^^^^^^^^^^^^^^
# Error: Unbound type constructor Yojson.Basic.t
It's referencing my .mli file below:
module Database :
sig
type meta_data = {
fs : in_channel;
db_type : int;
db_column : int;
db_year : int;
db_month : int;
db_day : int;
ipv4_db_count : Stdint.uint32;
ipv4_base_addr : Stdint.uint32;
ipv6_db_count : Stdint.uint32;
ipv6_base_addr : Stdint.uint32;
ipv4_index_base_addr : Stdint.uint32;
ipv6_index_base_addr : Stdint.uint32;
ipv4_column_size : Stdint.uint32;
ipv6_column_size : Stdint.uint32;
}
type ip2location_record = {
country_short : string;
country_long : string;
region : string;
city : string;
isp : string;
latitude : float;
longitude : float;
domain : string;
zip_code : string;
time_zone : string;
net_speed : string;
idd_code : string;
area_code : string;
weather_station_code : string;
weather_station_name : string;
mcc : string;
mnc : string;
mobile_brand : string;
elevation : float;
usage_type : string;
address_type : string;
category : string;
}
exception Ip2location_exception of string
val get_api_version : string
val open_db : string -> meta_data
val close_db : meta_data -> unit
val query : meta_data -> string -> ip2location_record
end
module Web_service :
sig
type web_config = {
api_key : string;
api_package : string;
use_ssl : bool;
}
exception Ip2location_exception of string
val open_ws : string -> string -> bool -> web_config
val lookup :
web_config -> string -> string -> string -> int * Yojson.Basic.t
val get_credit : web_config -> int * Yojson.Basic.t
end
I have no idea what I'm missing now. Any pointers would be great.
This is an issue with your opam file which is missing the information that your package is not compatible with earlier versions of yojson. Typically, the type Yojson.Base.t was introduced as an alias of Yojson.Base.json in version 1.6.0 .
I'm trying to get a record from a GSI and I'm stucked.
API Schema:
type DriverInfos {
id: String!
status: Int
lastLat: Float
lastLng: Float
idDriver: String # GSI
}
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfos
}
Resolver :
{
"version" : "2017-02-28",
"operation" : "Query",
"index" : "idDriver-index",
"query" : {
## Provide a query expression. **
"expression": "#idDriver = :idDriver",
"expressionNames" : {
"#idDriver" : "idDriver"
},
"expressionValues" : {
":idDriver" : {
"S" : "${ctx.args.idDriver}"
}
}
}
}
Query :
query getDriverInfosByDriver{
getDriverInfosByDriver(idDriver: "1")
{
idDriver
status
lastLat
lastLng
}
}
Return :
{
"data": {
"getDriverInfosByDriver": {
"idDriver": null,
"status": null,
"lastLat": null,
"lastLng": null
}
}
}
GSI is well activated : Name : "idDriver-index" - PartitionKey : idDriver (String)
Try with other ids : 2, 3, ...
It seems that it comes from the resolver. I tried with different resolver but it always return an error.
Thank you in advance for your answers.
The issue is that a Query operation always returns a set of results not just one. If you want to leave your query type like this:
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfos
}
then you should to change your response mapping template to this:
#if($ctx.result.items.size() > 0)
$util.toJson($ctx.result.items[0])
#else
null
#end
If instead the getDriverInfosByDriver query should return multiple info objects then you should change your schema to:
type DriverInfo {
id: String!
status: Int
lastLat: Float
lastLng: Float
idDriver: String # GSI
}
type DriverInfoConnection {
items: [DriverInfo]
nextToken:String
}
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfoConnection
}
You can then leave your response mapping template as the default:
$util.toJson($ctx.result)
and then query it like so
query getDriverInfosByDriver{
getDriverInfosByDriver(idDriver: "1") {
items {
idDriver
status
lastLat
lastLng
}
}
}
Example:- searchCriteria(jsonObject)
1.
jsonObject : { employeeId :"xx" ,
employeeName : "yy",
employeeDOB : "zz",
}
2.
jsonObject : {
SSN:"xx"
}
3.
jsonObject : { agentId:"xx",
agentType: "yy"
}
So basically, we want to build a custom search component(which can be reused for other search methods,only parameters will change) where we will pass jsonObject which may change according to point1,point2,point3.
Jersey supports parsing values to Jettison JSONObject/JSONArray.
Example:
jsonObject : { employeeId :"xx" ,
employeeName : "yy",
employeeDOB : "zz",
}
Code:
#POST
#Path("/rest")
#Consumes(MediaType.APPLICATION_JSON)
public Object searchData(JSONObject json) {
String empId = json.optString("employeeId");
String empName = json.optString("employeeName");
String empDOB = json.optString("employeeDOB");
return new Object();
}
Similarly, you can implement your generic search to accept any object and extract the contents.
I'm trying to save two tasks to the same user story. The first request always succeeds, but the second service request always gets this message back in the response:
Concurrency conflict: [Object has been modified since being read for
update in this context] - ConcurrencyConflictException : Modified
since read on update : Object Class : com.f4tech.slm.domain.UserStory
: ObjectID :
I am using the JavaScript SDK to create the task. I do this twice:
Rally.data.ModelFactory.getModel({
type : 'Task',
success : function(task) {
var record = Ext.create(task, {
Name : taskName,
State : 'Defined',
TaskIndex : 1,
WorkProduct : workProductId,
Owner : userIdsTeam[owner],
SyncDevelopmentTasktoAccuRev : accuSync,
Estimate: hours,
TargetDeployment: targetDeployment,
context: {
project:'/project/' + currentProjectId,
projectScopeDown: true
},
});
record.save({
callback : afterSaveNewTaskCallback
});
}
});
Is there anything I can do to get rid of this error and successfully save two tasks?
In addition to Kyle's answer, you can also use the Rally.data.BulkRecordUpdater to have the creates/updates queued for you. http://developer.rallydev.com/apps/2.0p5/doc/#!/api/Rally.data.BulkRecordUpdater
Since your tasks are both attached to the same underlying user story the creates are both trying to lock on it to set the association and that's why the second one fails. You'll need to chain the callbacks together:
Rally.data.ModelFactory.getModel({
type : 'Task',
success : function(taskModel) {
//Create first task
var task1 = Ext.create(taskModel, {
//...fields...
});
task1.save({
callback: function() {
//Create second task
var task2 = Ext.create(taskModel, {
//...fields...
});
task2.save({
callback: afterSaveNewTaskCallback
});
}
});
}
});
How to receive posted values to variable in .asmx that was posted from extjs, so it can be saved using ado.net to database?
SENDING DATA WITH EXT.AJAX
{
text: 'Add',
formBind: true,
disabled: true,
handler: function () {
var form = this.up('form').getForm();
var formValues = form.getValues();
var firstName = formValues.firstName;
var lastName = formValues.lastName;
if (form.isValid()) {
Ext.Ajax.request({
url: 'WebServices/WebService.asmx/AddAgent',
headers: { 'Content-Type': 'application/json' },
method: 'POST',
jsonData: { FirstName: firstName, LastName: lastName }
});
}
}
}
When submited, firebug reports error:
How to properly recieve this values in .asmx so they can be used in [WebMethod] and saved with Ado.Net?
[Serializable]
public class Agents
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
//CREATE
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public string AddAgent()
{
string connStr = ConfigurationManager.ConnectionStrings["AgentsServices"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connStr))
{
connection.Open();
using (SqlCommand command = new SqlCommand("insert into Agent(id, firstName, lastName) values(#id, #firstName, #lastName)", connection))
{
command.Parameters.AddWithValue("#firstName", FirstName); //here i get message( The name "FirstNAme does not exist in current context")
command.Parameters.AddWithValue("#lastName", LastName); // -||-
command.ExecuteNonQuery();
}
}
}
EDIT:
No. stil 500 Internal Server Error:
Your web method doesn't seem to take any argument. Also your method expects to return a string and yet you do not return anything. So either return something or modify your method signature to void. Also you have set UseHttpGet = true and yet you are sending a POST request. Try like this:
[WebMethod]
[ScriptMethod]
public void AddAgent(Agents agents)
{
string connStr = ConfigurationManager.ConnectionStrings["AgentsServices"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connStr))
{
connection.Open();
using (SqlCommand command = new SqlCommand("insert into Agent(id, firstName, lastName) values(#id, #firstName, #lastName)", connection))
{
command.Parameters.AddWithValue("#firstName", agents.FirstName);
command.Parameters.AddWithValue("#lastName", agents.LastName);
command.ExecuteNonQuery();
}
}
}
Also since you have defined the Id property of your Agents model as a non-nullable integer I would recommend you sending a value for it:
jsonData: { agents: { Id: 0, FirstName: firstName, LastName: lastName } }