I've managed to get a converse.js v.0.9.0 client working with an openfire server I have on a Debian machine.
The connection works just fine, I've created a couple of users to test things out and everything was working fine, I could login, make private conversations between users even create rooms, which were listed properly when clicking the "list rooms" button.
The problem came when a user wanted to join a room another user created. When doing so, the window with the room name popped properly but the users list in that room was empty and communication didn't exist at all (no one could see each others messages on that room).
I took a look on the openfire admin panel and in the conference server the room was properly displayed but only with 1 user in it.
Is this a problem with the openfire conference server configuration? or is it the converse client that needs an extra module for room chats?
I'l put the code of the test page to see if it can help.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>prueba</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/converse.css">
<script src="builds/converse.js"></script>
</head>
<body>
</body>
<script>
require(['converse'], function (converse) {
converse.initialize({
auto_list_rooms: false,
auto_subscribe: false,
bosh_service_url: 'http://converse:7070/http-bind/',
hide_muc_server: false,
i18n: locales.en,
prebind: false,
show_controlbox_by_default: true,
roster_groups: true
});
});
</script>
</html>
Solved!
The problem was the rooms options.
There are several ways to perform .join into a MUC (multi user chat) I'l quote Ignite Realtime on this:
// Create a MultiUserChat using a XMPPConnection for a room
MultiUserChat muc2 = new MultiUserChat(conn1, "myroom#conference.jabber.org");
// User2 joins the new room
// The room service will decide the amount of history to send
muc2.join("testbot2");
In this example we can see how to join a room with a given nickname and password:
// User2 joins the new room using a password
// The room service will decide the amount of history to send
muc2.join("testbot2", "password");
In this example we can see how to join a room with a given nickname specifying the amount of history to receive:
// User2 joins the new room using a password and specifying
// the amount of history to receive. In this example we are requesting the last 5 messages.
DiscussionHistory history = new DiscussionHistory();
history.setMaxStanzas(5);
muc2.join("testbot2", "password", history, conn1.getPacketReplyTimeout());
So my guess is that Converse Join function is formated only on the first way (the one with only the string parameters) and when I check further options in the server probably the overrided function wich ask for more parameters was denying converse the possibility to execute its join function wich only had one parameter.
Related
I've configured Conversejs to Auto join a room, with a preconfigured account and credentials. I would like it to clear the previous messages when the room is joined.
I've been able to put together this shell of a plugin, and have confirmed it executes but dont know the code to clear the chat text.
converse.plugins.add('myplugin', {
initialize: function () {
this._converse.api.listen.on('roomsAutoJoined', () => {
// How to clear chat ??
});
}
});
Basicically executing the /clear command for the user automatically when joining room.
There will always be another user signed into the room, or else I know it would clear automatically.
Also I'm using ejabberd if it matters.
You can set clear_muc_messages_on_reconnection to true.
I have the following workflow on a website:
Some user John Doe declares a company through form 1
(fields: name, head office location)
After John Doe submits (HTTP POST) form 1, he is redirected (HTTP 302) to company form 2 with additional legal information about the company.
The problem is, if John Doe hits the back button of his browser during step 2, he will land on the form 1, with data filled by the browser (using values he already submitted — that's what Firefox and major browsers seem to do).
John Doe might then think he can use this form to update some information (e.g. fix a typo in the name of the company) whereas he will actually create a new company doing so, as we don't know on the server side whether he wants to declare a new company or update the one he just created.
Do you know any simple solution to handle that problem ?
Use javascript/jquery script after the page is loaded to empty all the inputs. This will prevent confusion of "updating the company".
jQuery would look something like this:
$('#elementID').val('');
You can also handle the situation by manipulating the browser history
on load of form 2, and pass the CompanyId generated on submit of form 1 using querystring. So that you can actually update the company as the user
Suppose John submits form1.html, a unique CompanyId "1001" is generated and redirected to form2.html. Now on load of form2 you can modify the browser history form1.html?companyid=1001 using
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 1", "form1.html?companyid=1001");
Now, when the user click back button and submits the form1 again. you can check for companyid in querystring and update the company.
I think it is more user-friendly when user can return back to previous form and update it (instead preventing the described behavior).
I use in most cases similar way to handle described problem:
Let's assume that user is on the page /some-page, that contains "Create new company" button.
When the user opens this page, will be executed special method createOrFindCompanyDraft() on the server-side. This method creates new company "draft" record in DB (only for the current user). For example, draft record has primary key id=473. When you execute this method again it will return the same record with the id=473 (with "draft" status). "Draft" record should't display on any other interfaces.
And "Create new company" has link /company/common/473.
When user go to /company/common/473, you display form 1, that will be filled from "draft" record. At first time user will see empty form.
Technically user will update the existing record, but you can display "Create new company" title on the page.
Then user go to form 2, for example, /company/legal-info/473, you create similar draft record for the this form (similar to step 1).
When user submit the form 2, you will remove "draft" status from the record id=473 (and any related records).
Next time when user open page /some-page, will be created new draft record for the current user.
Browser history will contain:
/some-page
/company/common/473
/company/legal-info/473
/some-page2
I like this approach, because all form only update records. You can go to previous/next form many times (for example "Back"/"Forward" browser buttons). You can close browser, and open not completed forms tomorrow. This way doesn't require any additional manipulation with the browser history.
try this
<form autocomplete="off" ...></form>
And Another
Use temporary tables or session to store the Page 1 form data. If the page 2 form is submitted use the temporary data of page 1 which is stored in database or in session.
Use a Separate key (Hidden field ) in both page 1 and page 2.
Actually I thought of a trick to obtain that "create on first post, update after" behavior (just like the user thinks it should behave).
Let's say the step 1 form is at the URL /create_company/. Then I could have that page generate a random code XXX and redirect to /create_company/?token=XXX. When I create the company I save the information that it was created through page with token XXX (for instance, I save it in user's session as we don't need to keep that information forever) and when the form is submitted, if I know that a company was already generated using this token, I know the user used the same form instance and must have used the back button since the token would be different if he explicitly asked for another company.
What do you think ? (I initially thought there should be a simpler solution, as this seems a little bit over-engineered for such a simple issue)
This is more like a UX question.
I'd think that the solution lies within the information given to the user on that form, to help them understand what they're doing.
Set a title that says 'Create a company', for example, and set your submit button as 'Create Company' will help your user with that. Use a unique id when you create the company object, and pass the id back to the same URL in order to perform an update. You should then update your title and button that tells user that they are updating instead of creating.
In that sense I'd say it's better to use a more generic URL like /company and /company?id=12345.
You could also consider using Restful API protocol to help your server identifies the CRUD operation. http://www.restapitutorial.com/lessons/httpmethods.html
Without the "routing" part of django it is hard to help. I can just answer my experience from the express.js-router functionality:
you can specify a post on /company, which is for new users.
you can specify another route for post on /company/:companyid for a changing form
and as a response from the create-post you can redirect to the different location.
Today I wanted to greet the user in my app by name, but I did not manage to get it.
I found System.User, but lacking some examples I did not manage to get the info I needed. I saw no possibility to get the current user (id) to call User.GetFromId().
Can you guide me into the right direction? Have I been on the wrong path?
Okay, So first things first, getting access to a user's personal information is a privilege you have to request, so in your store app's Package.appxmanifest, you'll need to enable the User Account Information capability in the Capabilities tab.
Next, you'll want to be using the Windows.System.User class, not the System.User (System.User isn't available to Windows store apps, which you appear to be discussing given the tags you provided for your question)
Third, you'll want to request personal information like this.
IReadOnlyList<User> users = await User.FindAllAsync(UserType.LocalUser, UserAuthenticationStatus.LocallyAuthenticated);
User user = users.FirstOrDefault();
if (user != null)
{
String[] desiredProperties = new String[]
{
KnownUserProperties.FirstName,
KnownUserProperties.LastName,
KnownUserProperties.ProviderName,
KnownUserProperties.AccountName,
KnownUserProperties.GuestHost,
KnownUserProperties.PrincipalName,
KnownUserProperties.DomainName,
KnownUserProperties.SessionInitiationProtocolUri,
};
IPropertySet values = await user.GetPropertiesAsync(desiredProperties);
foreach (String property in desiredProperties)
{
string result;
result = property + ": " + values[property] + "\n";
System.Diagnostics.Debug.WriteLine(result);
}
}
When you call GetPropertiesAsync, your user will get a permission prompt from the system asking them if they want to give you access to that. If they answer 'No', you'll get an empty user object (but you'll still get a unique token you can use to distinguish that user if they use the app again).
If they answer yes, you'll be able to get access to the properties below, and various others.
See the UserInfo Sample Microsoft provided for more examples.
Okay, I know this question has been half answered around here, but I'll explain in full and see if there maybe a better way to handle this then in just two parts.
I'm building an HTML5 voting site, that will close voting every half hour. And then open a new batch of voting.
What I need to do, is have the URL of this site be 'masked' ie:
have a random URL for it be generated that leads to the same location- so say I'm directing users to voting.com, I want them to only access it via the url votingstuff.com/hg67, and have that end portion be changed every half hour- and once the new url is generated, remove access to the site via the old URL.
I might add that after the user votes, I'd also like to close their voting access until the new URL is posted. AKA- everyone only gets one chance to vote.
Thoughts? Libraries to check out? Sites that do this? I know the randomization has been answered a few times, but usually it's a generator led to by a page, I want to START with a randomly generated URL, and not have a page that creates it as a function. I may have to write code that generates the page I guess?
Here is an approach I can think of -
You don't need to handle multiple URL's, you can achieve this on the same URL itself by enabling/disabling access to the URL content every hour.
You will need some action on your application/server side as well. For reference lets assume you have a PHP server running. You will need some table that holds a status setting for you, something like this -
Settings Table
id settingCode value
=============================
1 votingOpen 1
You will also need to setup a cron job on your server that will run every half an hour. The cron job's task would be to run every half an hour & change the value of the votingOpen to its inverse. So assume open your votings, initial value of the votingOpen field would be 1 i.e the first half an hour of voting starts.
Along with this you will start the cron job as well. Now what will happen is that after half an hour the cron job will fetch the value of votingOpen read it & if its 1, it will change it to 0 & if its 0 it will change it to 1. This will happen every half an hour on your server.
Now you need to make this votingOpen variable accessible on your client side code using a simple query to fetch its value. On each render of your voting page, on top somewhere you can check this value & if its 1 i.e true, you will write the logic to go ahead & show the voting page. But if its 0, you can redirect the user or show a different message on that page.
Lets say your voting happens on http://somedomain.com/voting, on the render logic of this page you can do something like this -
Voting View Logic
<?php
$votingOpen = {some database query that fetches the value from the database};
if($votingOpen) {
// your voting view resides here
} else {
// either redirect user to some other page
// or show some message like voting is closed on this same page.
}
?>
Limit multiple votes from one person
Normally the best way to handle this is a combination or registered user only vote + cookie/localStorage + IP tracking
But if you don't have registered user voting, you can still capture IP of user & allow only one vote per IP and you can also set a cookie or a localStorage variable in the users computer so he can only vote once.
Hope this helps.
Ref for Cron Job - http://code.tutsplus.com/tutorials/managing-cron-jobs-with-php--net-19428
I am wondering how can I do the following about MS CRM 4.0:
I want to know for a campaign if a contact from a specific marketing list has not replied yet.
The field custom in the campaign response form is a partyfield. CRM doesn’t allow a PartyList field to be queried using a QueryExpression
Any ideas?
Thanks,
Katya
You cannot retrieve activityparty records directly, but you can use them in LinkEntities:
private bool contactHasResponded(Guid idCampaign, Guid idContact)
{
QueryExpression qryCampaignResponses = new QueryExpression("campaignresponse");
qryCampaignResponses.ColumnSet = new AllColumns();
qryCampaignResponses.Criteria = new FilterExpression();
qryCampaignResponses.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, idCampaign);
LinkEntity leContact = new LinkEntity("campaignresponse", "activityparty", "activityid", "activityid", JoinOperator.Inner);
leContact.LinkCriteria = new FilterExpression();
leContact.LinkCriteria.AddCondition("partyid", ConditionOperator.Equal, idContact);
qryCampaignResponses.LinkEntities.Add(leContact);
List<gcCampaignresponse> lstCampaignResponses = gcCampaignresponse.RetrieveMultiple(m_svcCrm, qryCampaignResponses);
return (lstCampaignResponses.Count > 0);
}
This will tell you whether there's a campaign response for a given campaign and contact. (I use entity classes generated by Stunnware Tools, so the RetrieveMultiple call looks a little different, but I think you get my point).
If you turn this QueryExpression/LinkEntity construct upside down, you can also get all contacts that have responded to a given campaign (you can also restrict that to contacts in a certain marketing list through a second LinkEntity).
The only thing that's not possible directly with a single query is the "negative" check you are looking for, so you'll have to take this result and do an "outer join" against your marketing list to get the contacts that have not responded.