package comms.view.chat; import java.util.ArrayList; import java.util.Iterator; import comms.model.chat.CallRequest; import comms.model.chat.Conversation; import comms.model.chat.Participant; import comms.view.FeeddexApplication; import comms.view.FeeddexPage; import comms.view.FeeddexSession; import comms.bus.CallRequestService; import comms.bus.ChatService; import org.apache.wicket.Component; import org.apache.wicket.ResourceReference; import org.apache.wicket.ajax.AbstractAjaxTimerBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.IHeaderContributor; import org.apache.wicket.markup.html.IHeaderResponse; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.AbstractReadOnlyModel; /** *

* This page contains a regular Wicket component showing the available agents and * a separate component timer with AbstractAjaxTimerBehavior. This timer will * will each time send a piece of JavaScript containing list of the current * conversations and a function call to update the DOM to match this list. *

*

* In this (awkward) way we try to avoid focus issues with popup windows originating from * a dynamically created html element. *

*

* NOTE: Just recently I learned that AjaxRequestTarget.setFocus(null) is supposed * to avoid any focus issues. Maybe with that the whole script hassle could be avoided * *

*/ public class Conversations extends FeeddexPage implements IHeaderContributor { //FIXME Check access to this page // public Conversations( PageParameters pars ) { // this( pars.getString( "service" ), pars.getString("participant")); // } public Conversations() { this(FeeddexSession.get().getOrganisationId().toString(), FeeddexSession.getMe().getChatName()); } public Conversations(final String serviceId, final Object participant) { add(createUpdater("timer", serviceId, participant)); add(createAvailableAgents("availableAgents", serviceId )); } private Component createAvailableAgents(String id, final String serviceId) { final WebMarkupContainer agents = new WebMarkupContainer( id ); agents.setOutputMarkupId(true); ListView list = new ListView( "list", new AbstractReadOnlyModel(){ @Override public Object getObject() { return new ArrayList(ChatService.getInstance(serviceId).getAvailableAgents()); } } ){ @Override protected void populateItem(final ListItem item) { item.add( new Label( "agent", new AbstractReadOnlyModel() { @Override public Object getObject() { return item.getModelObject().toString(); } })); } }; agents.add( list ); WebMarkupContainer myAvailability = new WebMarkupContainer( "myAvailability" ); myAvailability.add(new Label("description", new AbstractReadOnlyModel() { @Override public Object getObject() { String key = ChatService.getInstance(serviceId).isAvailable( FeeddexSession.get().getChatParticipant()) ? "available" : "not_available"; return getString(key); } })); myAvailability.add(new AjaxLink("toggle") { @Override public void onClick(AjaxRequestTarget target) { ChatService service = ChatService.getInstance(serviceId); Participant participant = FeeddexSession.get().getChatParticipant(); service.setAvailable(participant, !service.isAvailable(participant)); target.addComponent(agents); } }); agents.add( myAvailability ); return agents; } /** * An AjaxTimers that will return a list * @param id * @param serviceId * @param participant * @return */ private Component createUpdater(String id, final String serviceId, final Object participant) { Component timer = new WebMarkupContainer("timer"); timer.add(new AbstractAjaxTimerBehavior(ChatService.getPollInterval()) { @Override protected void onTimer(AjaxRequestTarget target) { target.appendJavascript(createUpdateScript()); target.focusComponent(null); } private String createUpdateScript() { StringBuffer buf = new StringBuffer(); appendConversationsUpdateScript(buf); appendCallRequestsUpdateScript(buf); return buf.toString(); } private void appendConversationsUpdateScript(StringBuffer buf) { String urlBase = FeeddexApplication.getUrlAgentChat() + "/service/" + serviceId + "/participant/" + participant + "/conversation/"; buf.append("var conversations = new Array("); ChatService service = ChatService.getInstance(serviceId); Iterator itr = service.getAllConversations() .iterator(); if (itr.hasNext()) { Conversation conversation = itr.next(); buf.append(toJavaScriptString(urlBase, conversation)); while (itr.hasNext()) { buf.append(","); conversation = itr.next(); buf.append(toJavaScriptString(urlBase, conversation)); } } buf.append(");"); buf.append("updateConversations('conversations', conversations );"); } private void appendCallRequestsUpdateScript(StringBuffer buf) { String urlBase = FeeddexApplication.getUrlCallRequest() + "/service/" + serviceId + "/transaction/"; buf.append("var callrequests = new Array("); CallRequestService service = CallRequestService .getInstance(serviceId); Iterator itr = service.getAllCallRequests() .iterator(); if (itr.hasNext()) { CallRequest callrequest = itr.next(); buf.append(toJavaScriptString(urlBase, callrequest)); while (itr.hasNext()) { buf.append(","); callrequest = itr.next(); buf.append(toJavaScriptString(urlBase, callrequest)); } } buf.append(");"); buf .append("updateCallrequests('callrequests', callrequests );"); } private String toJavaScriptString(String urlBase, Conversation conversation) { return "{id:'" + conversation.getId() + "',url:'" + urlBase + conversation.getId() + "',name:'" + getDescription(conversation) + "',state:'" + "QUEUED" + // conversation.getStatus() + "'}"; } private String getDescription(Conversation conversation) { return "Conversatie " + conversation.getId(); } private String toJavaScriptString(String urlBase, CallRequest callrequest) { return "{id:'" + callrequest.getTransactionId() + "',url:'" + urlBase + callrequest.getTransactionId() + "',name:'" + getDescription(callrequest) + "'}"; } private String getDescription(CallRequest callrequest) { return "Call me (" + callrequest.getCreated() + ")"; // TODO // Phone // number } }); return timer; } public void renderHead(IHeaderResponse response) { response.renderCSSReference( new ResourceReference( this.getClass(), "Conversations.css")); response.renderJavascriptReference( new ResourceReference( this.getClass(), "Conversations.js")); } }