*I see no other way to get the number of users (per server)* => There are at least three alternative ways to get this number: a) You count the number of connection of a certain scope and then take the sum of it This will give you the total number of connections, no matter if audio/video, conferencing or a screensharing connection. b) You count the total number of RoomClients from the current session This will give you the total number of connections, no matter if audio/video, conferencing or a screensharing connection. c) You count the total number of RoomClients from the current session, but you filter the result based on if the RoomClient is a Audio/Video client or a Screensharing client With this method you would be able to calc the exact number of Audio/Video connection
Which of those would fit yours? Or did I misunderstood something? Sebastian 2012/10/24 Maxim Solodovnik <[email protected]> > Hello Sebastian, > > I'm afraid we need something like "lightweight RoomClient" in the DB to > resolve 3) > This can be done without performance degradation. > I see no other way to get the number of users. > > On Wed, Oct 24, 2012 at 3:31 PM, [email protected] < > [email protected]> wrote: > >> So will we find a consens here? :) >> >> 1) No DB query in Sync methods to keep performance up >> 2) Session objects should not stay in a database but in memory >> 3) To have the number of users per server instance there is no need to >> have the RoomClient in the database. >> >> Can we find a consens based on those resolutions? >> >> Sebastian >> >> 2012/10/22 [email protected] <[email protected]> >> >> Practically in this case you would have to iterate thorugh the connection. >>> You could also call IConnection => getConnection => getSize. >>> This would give a rough idea. But as you don't know how many of those >>> connection are screensharing or Audio/Video you can't tell how many users >>> exactly there are. >>> >>> If you want to share this information with others I would suggest you >>> simply add a SOAP/REST call and in that sense query the number of users via >>> a HTTP call. >>> >>> >>> Sebastian >>> >>> 2012/10/22 Maxim Solodovnik <[email protected]> >>> >>>> If I remember correctly I have added RoomClient to the DB since I need >>>> mechanism to retrieve how much users are currently in the room. >>>> >>>> >>>> On Mon, Oct 22, 2012 at 3:23 PM, [email protected] < >>>> [email protected]> wrote: >>>> >>>>> We could even store it currently in the IConnection. The Red5 >>>>> framework has the similar mechanism like the static Map that I've build. >>>>> >>>>> We will also stay with our Red5 implementation for the next 6 months >>>>> as we have no alternative to stream audio/video in HTML5. >>>>> >>>>> It is no option to stay with it, how can we offer OpenMeetings to be >>>>> scalable to 1000 concurrent users? We would have to limit it to 250. Also >>>>> it would become mandatory to have the database server on the same machine >>>>> as the red5 server. Otherwise you have performance bottlenecks. Can you >>>>> imagine what kind of negative public feedback we will have if every >>>>> question about performance of red5 is answered with: Did you install db >>>>> server on another instance of your network? >>>>> >>>>> Sorry but it is not possible. Also not for a temporary solution. We >>>>> can't sell this product like that and claim to have 1000 user sessions per >>>>> server unit. >>>>> >>>>> What requirements do exist to store the RoomClient in the database and >>>>> what is needed to be done to remove it from the db again? >>>>> >>>>> >>>>> Sebastian >>>>> >>>>> 2012/10/22 Maxim Solodovnik <[email protected]> >>>>> >>>>>> OK, I'm not insist. I believe RoomClient will be removed in the >>>>>> future. >>>>>> >>>>>> >>>>>> On Mon, Oct 22, 2012 at 3:00 PM, [email protected] < >>>>>> [email protected]> wrote: >>>>>> >>>>>>> Sorry but: >>>>>>> >>>>>>> for (RoomClient rc: allClient) { >>>>>>> if (rc.getPublicSID().equals(_publicSID) { >>>>>>> return rc; >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> That is simply not true. >>>>>>> There are _some_ implementations where it was needed that you need >>>>>>> to get the RoomClient by its public SID. However this usage was quite >>>>>>> limited. >>>>>>> >>>>>>> In general it was the way I described it: >>>>>>> The maps key was the streamid. And the streamid was obtained from >>>>>>> the IConnection of each stream. >>>>>>> >>>>>>> >>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ClientListManager.java?revision=1339514&view=markup >>>>>>> Line 118, that was the function that was mainly in use all over the >>>>>>> application. >>>>>>> There is no sorting, there is no iteration => nothing. >>>>>>> >>>>>>> Search in the ScopeApplicationAdapter for "getClientByStreamId" => >>>>>>> 52 of matches. >>>>>>> Every of this call is now replaced by a single DB query. >>>>>>> And if you iterate like described through all connection (like it is >>>>>>> in EVERY snyc method) >>>>>>> You will do a single query for EVERY connection. >>>>>>> Like 100 users in a room => 100 queries. >>>>>>> Think about the green dot that blinks every time you speak in the >>>>>>> video pod: >>>>>>> If it gets visible => one sync message >>>>>>> If its get transparent => one sync message. >>>>>>> If you have a quite good and sensitive micro it will flush 10 mabye >>>>>>> 10 times per second. >>>>>>> per 100 users in a room => 10 * 100 = 1000 queries in a SINGLE SECOND >>>>>>> => that is just impossible !! >>>>>>> And that is just a SINGLE videopod with 100 users watching. Now >>>>>>> scale that up to 1000 concurrent rooms with 4x4 meetings where every >>>>>>> user >>>>>>> has micro turned on ?! Should we calc the number of database queries >>>>>>> really?! >>>>>>> >>>>>>> Sorry we will not follow that route :) >>>>>>> >>>>>>> Sebastian >>>>>>> >>>>>>> 2012/10/22 Maxim Solodovnik <[email protected]> >>>>>>> >>>>>>>> Previous solution was: >>>>>>>> >>>>>>>> for (RoomClient rc: allClient) { >>>>>>>> if (rc.getPublicSID().equals(_publicSID) { >>>>>>>> return rc; >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> + screen sharing clients were filtered same way. >>>>>>>> Right now we can filter all sessions with 1 query this is why the >>>>>>>> code can work faster (after minor changes in iterating logic) >>>>>>>> >>>>>>>> I'm not insist RoomClient should be DB object. But having it as DB >>>>>>>> object was the only option to have user count in the room (in case >>>>>>>> Rooms >>>>>>>> are on the different servers). >>>>>>>> >>>>>>>> I believe right now org.apache.openmeetings.web.app.WebSession will >>>>>>>> be session object. >>>>>>>> I hope everything except audio and video will move to Wicket :) >>>>>>>> >>>>>>>> >>>>>>>> On Mon, Oct 22, 2012 at 2:33 PM, [email protected] < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> Hi Maxim, >>>>>>>>> >>>>>>>>> you can't persist on the argumentation that a HashMap stored in >>>>>>>>> the memory is slower then doing a single query for every entry of the >>>>>>>>> map ? >>>>>>>>> Basicaly the previous implementation was a single HashMap. >>>>>>>>> Getting a RoomClient from this map was: >>>>>>>>> map.get($streamId) >>>>>>>>> and now this single line is replaced by a Database query. The >>>>>>>>> performance of this single line is ... I guess smaller then 1 >>>>>>>>> millisecond. >>>>>>>>> How can you say that a "Right now I think the current code should work >>>>>>>>> faster or the same as previous one." :) >>>>>>>>> >>>>>>>>> I guess you had some other requirements that made you implement >>>>>>>>> this. >>>>>>>>> For example for the clustering solution. >>>>>>>>> However I also persist on my view: >>>>>>>>> A database is _not_ the right place for storing session variables. >>>>>>>>> This is simply a bad design decision that will cost a lot of >>>>>>>>> performance in >>>>>>>>> the future. >>>>>>>>> >>>>>>>>> Could you explain why there is a need for having the RoomClient in >>>>>>>>> the database? Maybe we can resolve those requirements differently so >>>>>>>>> that >>>>>>>>> we can have the RoomClient back in memory. >>>>>>>>> >>>>>>>>> Sebastian >>>>>>>>> >>>>>>>>> >>>>>>>>> 2012/10/19 Maxim Solodovnik <[email protected]> >>>>>>>>> >>>>>>>>>> Sorry for double post. >>>>>>>>>> >>>>>>>>>> Correct me if I'm wrong, but i think "Transient for XML >>>>>>>>>> export/import" is not necessary since it doesn't have @Element >>>>>>>>>> annotation >>>>>>>>>> On Oct 19, 2012 9:59 PM, "Maxim Solodovnik" <[email protected]> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> RoomClient was mooved to the DB while I implemented cluster. >>>>>>>>>>> Current changes only make the calls faster (since DB is quered >>>>>>>>>>> only once) >>>>>>>>>>> >>>>>>>>>>> I'll try to create couple of tests. Right now I think the >>>>>>>>>>> current code should work faster or the same as previous one. >>>>>>>>>>> >>>>>>>>>>> Old code did lots of full filterings of RommsClient hash map to >>>>>>>>>>> get subset required. >>>>>>>>>>> >>>>>>>>>>> I tests will show I'm wrong on this I'll try to tune up openjpa >>>>>>>>>>> cache and if it doesn't help will split RoomClient to the couple of >>>>>>>>>>> objects >>>>>>>>>>> and/or will create hashtable in parallel to speed up things. >>>>>>>>>>> >>>>>>>>>>> But I hope everything is not so slow since these changes are >>>>>>>>>>> present in 2.0 and nobody reports performance degradation. >>>>>>>>>>> >>>>>>>>>>> Sorry for typos, I'm from mobile phone >>>>>>>>>>> On Oct 19, 2012 9:11 PM, "[email protected]" < >>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>> >>>>>>>>>>>> I guess this happened lately in trunk. >>>>>>>>>>>> How are we the in the future planning to determine the current >>>>>>>>>>>> users in the room. >>>>>>>>>>>> Session or database based? >>>>>>>>>>>> >>>>>>>>>>>> I ask that critical as some queries require to sync messages to >>>>>>>>>>>> all clients of a room. >>>>>>>>>>>> This can happen 1000 times in a single second if you think >>>>>>>>>>>> about having up to 1000 concurrent user sessions. >>>>>>>>>>>> >>>>>>>>>>>> For example: >>>>>>>>>>>> ScopeApplicationAdapter::syncMessageToCurrentScope(String >>>>>>>>>>>> remoteMethodName, Object newMessage, boolean sendSelf, boolean >>>>>>>>>>>> sendScreen) >>>>>>>>>>>> => Collection<Set<IConnection>> conCollection = >>>>>>>>>>>> current.getScope() >>>>>>>>>>>> .getConnections(); >>>>>>>>>>>> ==> iterates through all connection of the scope. >>>>>>>>>>>> >>>>>>>>>>>> Now the new thing is that for every connection you will create >>>>>>>>>>>> a query for the RoomClient Object. >>>>>>>>>>>> This is simply impossible. >>>>>>>>>>>> >>>>>>>>>>>> We want to scale up to 1000 concurrent user sessions and more. >>>>>>>>>>>> The RoomClient is a typical Session object and it should stay >>>>>>>>>>>> in the session. >>>>>>>>>>>> It is the same issue like with the WhiteboardObject. >>>>>>>>>>>> We are making a real time application, there is no chance to >>>>>>>>>>>> run queries in sync methods. >>>>>>>>>>>> >>>>>>>>>>>> Can we find some consens here? I know you must have refactored >>>>>>>>>>>> already a lot but I strictly did implement zero db related stuff >>>>>>>>>>>> in sync >>>>>>>>>>>> methods. >>>>>>>>>>>> >>>>>>>>>>>> There might be a chance for some events to trigger db >>>>>>>>>>>> actions.However I don't think having two times the RoomClient >>>>>>>>>>>> stored (one >>>>>>>>>>>> time session, second time database) makes sense. >>>>>>>>>>>> >>>>>>>>>>>> What are you thoughts on this? >>>>>>>>>>>> >>>>>>>>>>>> Sebastian >>>>>>>>>>>> >>>>>>>>>>>> 2012/10/19 [email protected] <[email protected]> >>>>>>>>>>>> >>>>>>>>>>>>> Hi Maxim, >>>>>>>>>>>>> >>>>>>>>>>>>> I don't understand this new code in the Rooms Entity: >>>>>>>>>>>>> @OneToMany(fetch = FetchType.LAZY) >>>>>>>>>>>>> >>>>>>>>>>>>> @JoinColumn(name = "room_id") >>>>>>>>>>>>> private List<RoomClient> currentusers; >>>>>>>>>>>>> >>>>>>>>>>>>> We calc the current users online by iterating through the Red5 >>>>>>>>>>>>> Connections. >>>>>>>>>>>>> In which OpenMeetings version was it changed? >>>>>>>>>>>>> >>>>>>>>>>>>> I guess you can set it Transient for XML export/import. So >>>>>>>>>>>>> maybe annotate it with: >>>>>>>>>>>>> @org.simpleframework.xml.Transient >>>>>>>>>>>>> same like roomOrganisations. >>>>>>>>>>>>> >>>>>>>>>>>>> Sebastian >>>>>>>>>>>>> >>>>>>>>>>>>> 2012/10/19 <[email protected]> >>>>>>>>>>>>> >>>>>>>>>>>>> Author: solomax >>>>>>>>>>>>>> Date: Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> New Revision: 1400075 >>>>>>>>>>>>>> >>>>>>>>>>>>>> URL: http://svn.apache.org/viewvc?rev=1400075&view=rev >>>>>>>>>>>>>> Log: >>>>>>>>>>>>>> Wicket: calendar form is improved >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>> >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>> >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>> >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>> >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>> URL: >>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>> >>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>> (original) >>>>>>>>>>>>>> +++ >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> @@ -76,6 +76,24 @@ public class RoomDAO implements OmDAO<Ro >>>>>>>>>>>>>> return q.getSingleResult(); >>>>>>>>>>>>>> } >>>>>>>>>>>>>> >>>>>>>>>>>>>> + public List<Rooms> getPublicRooms() { >>>>>>>>>>>>>> + //TypedQuery<Rooms> q = >>>>>>>>>>>>>> em.createNamedQuery("getNondeletedRooms", Rooms.class); >>>>>>>>>>>>>> + TypedQuery<Rooms> q = em.createQuery( >>>>>>>>>>>>>> + "SELECT r from Rooms r LEFT >>>>>>>>>>>>>> JOIN FETCH r.currentusers WHERE r.ispublic= true and r.deleted= >>>>>>>>>>>>>> false ORDER >>>>>>>>>>>>>> BY r.name ASC", Rooms.class); >>>>>>>>>>>>>> + return q.getResultList(); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + public List<Rooms> getOrganisationRooms(long orgId) { >>>>>>>>>>>>>> + TypedQuery<Rooms> q = em.createQuery( >>>>>>>>>>>>>> + "SELECT DISTINCT c.room FROM >>>>>>>>>>>>>> Rooms_Organisation c LEFT JOIN FETCH c.room LEFT JOIN FETCH >>>>>>>>>>>>>> c.room.currentusers " >>>>>>>>>>>>>> + + "WHERE c.organisation.organisation_id = >>>>>>>>>>>>>> :orgId " >>>>>>>>>>>>>> + + "AND c.deleted = false AND c.room.deleted = >>>>>>>>>>>>>> false " >>>>>>>>>>>>>> + + "AND c.organisation.deleted = false " >>>>>>>>>>>>>> + + "ORDER BY c.room.name ASC", Rooms.class); >>>>>>>>>>>>>> + q.setParameter("orgId", orgId); >>>>>>>>>>>>>> + return q.getResultList(); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + >>>>>>>>>>>>>> public Rooms update(Rooms entity, long userId) { >>>>>>>>>>>>>> if (entity.getRooms_id() == null) { >>>>>>>>>>>>>> /* Red5SIP integration >>>>>>>>>>>>>> *******************************************************************************/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>> URL: >>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>> >>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>> (original) >>>>>>>>>>>>>> +++ >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> @@ -38,7 +38,6 @@ import javax.persistence.NamedQuery; >>>>>>>>>>>>>> import javax.persistence.OneToMany; >>>>>>>>>>>>>> import javax.persistence.OneToOne; >>>>>>>>>>>>>> import javax.persistence.Table; >>>>>>>>>>>>>> -import javax.persistence.Transient; >>>>>>>>>>>>>> >>>>>>>>>>>>>> import org.apache.openjpa.persistence.ElementDependent; >>>>>>>>>>>>>> import org.apache.openmeetings.persistence.beans.OmEntity; >>>>>>>>>>>>>> @@ -69,7 +68,6 @@ public class Rooms implements Serializab >>>>>>>>>>>>>> private String name; >>>>>>>>>>>>>> >>>>>>>>>>>>>> @Lob >>>>>>>>>>>>>> - // @Basic(fetch=FetchType.LAZY) >>>>>>>>>>>>>> @Column(name = "comment_field") >>>>>>>>>>>>>> @Element(data = true, required = false) >>>>>>>>>>>>>> private String comment; >>>>>>>>>>>>>> @@ -217,10 +215,8 @@ public class Rooms implements Serializab >>>>>>>>>>>>>> @org.simpleframework.xml.Transient >>>>>>>>>>>>>> private List<Rooms_Organisation> roomOrganisations = >>>>>>>>>>>>>> new ArrayList<Rooms_Organisation>(); >>>>>>>>>>>>>> >>>>>>>>>>>>>> - /* >>>>>>>>>>>>>> - * Non persistent attributes >>>>>>>>>>>>>> - */ >>>>>>>>>>>>>> - @Transient >>>>>>>>>>>>>> + @OneToMany(fetch = FetchType.LAZY) >>>>>>>>>>>>>> + @JoinColumn(name = "room_id") >>>>>>>>>>>>>> private List<RoomClient> currentusers; >>>>>>>>>>>>>> >>>>>>>>>>>>>> public String getComment() { >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>> URL: >>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>> >>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>> (original) >>>>>>>>>>>>>> +++ >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> @@ -18,14 +18,36 @@ >>>>>>>>>>>>>> */ >>>>>>>>>>>>>> package org.apache.openmeetings.web.components.user.calendar; >>>>>>>>>>>>>> >>>>>>>>>>>>>> +import java.util.ArrayList; >>>>>>>>>>>>>> +import java.util.List; >>>>>>>>>>>>>> + >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.openmeetings.data.calendar.daos.AppointmentReminderTypDaoImpl; >>>>>>>>>>>>>> +import org.apache.openmeetings.data.conference.RoomDAO; >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.openmeetings.data.conference.Roommanagement; >>>>>>>>>>>>>> +import org.apache.openmeetings.data.user.dao.UsersDaoImpl; >>>>>>>>>>>>>> import >>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.calendar.Appointment; >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.calendar.AppointmentReminderTyps; >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.domain.Organisation_Users; >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.rooms.RoomTypes; >>>>>>>>>>>>>> +import org.apache.openmeetings.persistence.beans.rooms.Rooms; >>>>>>>>>>>>>> +import org.apache.openmeetings.web.app.Application; >>>>>>>>>>>>>> +import org.apache.openmeetings.web.app.WebSession; >>>>>>>>>>>>>> +import org.apache.wicket.ajax.AjaxRequestTarget; >>>>>>>>>>>>>> +import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox; >>>>>>>>>>>>>> +import >>>>>>>>>>>>>> org.apache.wicket.extensions.yui.calendar.DateTimeField; >>>>>>>>>>>>>> +import org.apache.wicket.markup.html.form.ChoiceRenderer; >>>>>>>>>>>>>> +import org.apache.wicket.markup.html.form.DropDownChoice; >>>>>>>>>>>>>> import org.apache.wicket.markup.html.form.Form; >>>>>>>>>>>>>> +import org.apache.wicket.markup.html.form.PasswordTextField; >>>>>>>>>>>>>> import org.apache.wicket.markup.html.form.RequiredTextField; >>>>>>>>>>>>>> import org.apache.wicket.markup.html.form.TextArea; >>>>>>>>>>>>>> +import org.apache.wicket.markup.html.form.TextField; >>>>>>>>>>>>>> import org.apache.wicket.model.IModel; >>>>>>>>>>>>>> +import org.apache.wicket.model.PropertyModel; >>>>>>>>>>>>>> >>>>>>>>>>>>>> public class CalendarForm extends Form<Appointment> { >>>>>>>>>>>>>> private static final long serialVersionUID = >>>>>>>>>>>>>> -1764738237821487526L; >>>>>>>>>>>>>> + private boolean createRoom = true; >>>>>>>>>>>>>> >>>>>>>>>>>>>> public CalendarForm(String id, IModel<Appointment> >>>>>>>>>>>>>> model) { >>>>>>>>>>>>>> super(id, model); >>>>>>>>>>>>>> @@ -33,5 +55,71 @@ public class CalendarForm extends Form<A >>>>>>>>>>>>>> >>>>>>>>>>>>>> add(new >>>>>>>>>>>>>> RequiredTextField<String>("appointmentName")); >>>>>>>>>>>>>> add(new >>>>>>>>>>>>>> TextArea<String>("appointmentDescription")); >>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>> TextField<String>("appointmentLocation")); >>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>> DateTimeField("appointmentStarttime")); >>>>>>>>>>>>>> + add(new DateTimeField("appointmentEndtime")); >>>>>>>>>>>>>> + final PasswordTextField pwd = new >>>>>>>>>>>>>> PasswordTextField("password"); >>>>>>>>>>>>>> + pwd.setEnabled(isPwdProtected()); >>>>>>>>>>>>>> + pwd.setOutputMarkupId(true); >>>>>>>>>>>>>> + add(pwd); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>> DropDownChoice<AppointmentReminderTyps>( >>>>>>>>>>>>>> + "remind" >>>>>>>>>>>>>> + , >>>>>>>>>>>>>> Application.getBean(AppointmentReminderTypDaoImpl.class).getAppointmentReminderTypList() >>>>>>>>>>>>>> + , new >>>>>>>>>>>>>> ChoiceRenderer<AppointmentReminderTyps>("name", "typId"))); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + final DropDownChoice<RoomTypes> roomType = >>>>>>>>>>>>>> new DropDownChoice<RoomTypes>( >>>>>>>>>>>>>> + "room.roomtype" >>>>>>>>>>>>>> + , >>>>>>>>>>>>>> Application.getBean(Roommanagement.class).getAllRoomTypes() >>>>>>>>>>>>>> + , new >>>>>>>>>>>>>> ChoiceRenderer<RoomTypes>("name", "roomtypes_id")); >>>>>>>>>>>>>> + roomType.setEnabled(createRoom); >>>>>>>>>>>>>> + roomType.setOutputMarkupId(true); >>>>>>>>>>>>>> + add(roomType); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + final DropDownChoice<Rooms> room = new >>>>>>>>>>>>>> DropDownChoice<Rooms>( >>>>>>>>>>>>>> + "room" >>>>>>>>>>>>>> + , getRoomList() >>>>>>>>>>>>>> + , new >>>>>>>>>>>>>> ChoiceRenderer<Rooms>("name", "rooms_id")); >>>>>>>>>>>>>> + room.setEnabled(!createRoom); >>>>>>>>>>>>>> + room.setOutputMarkupId(true); >>>>>>>>>>>>>> + add(room); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + add(new AjaxCheckBox("createRoom", new >>>>>>>>>>>>>> PropertyModel<Boolean>(this, "createRoom")) { >>>>>>>>>>>>>> + private static final long >>>>>>>>>>>>>> serialVersionUID = -3743113990890386035L; >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + @Override >>>>>>>>>>>>>> + protected void >>>>>>>>>>>>>> onUpdate(AjaxRequestTarget target) { >>>>>>>>>>>>>> + createRoom = >>>>>>>>>>>>>> getConvertedInput(); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> target.add(roomType.setEnabled(createRoom), >>>>>>>>>>>>>> room.setEnabled(!createRoom)); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + }); >>>>>>>>>>>>>> + add(new AjaxCheckBox("isPasswordProtected") { >>>>>>>>>>>>>> + private static final long >>>>>>>>>>>>>> serialVersionUID = 6041200584296439976L; >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + @Override >>>>>>>>>>>>>> + protected void >>>>>>>>>>>>>> onUpdate(AjaxRequestTarget target) { >>>>>>>>>>>>>> + >>>>>>>>>>>>>> CalendarForm.this.getModelObject().setIsPasswordProtected(getConvertedInput()); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> pwd.setEnabled(isPwdProtected()); >>>>>>>>>>>>>> + target.add(pwd); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + }); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + private boolean isPwdProtected() { >>>>>>>>>>>>>> + return >>>>>>>>>>>>>> Boolean.TRUE.equals(getModelObject().getIsPasswordProtected()); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + private List<Rooms> getRoomList() { >>>>>>>>>>>>>> + //FIXME need to be reviewed >>>>>>>>>>>>>> + List<Rooms> result = new ArrayList<Rooms>(); >>>>>>>>>>>>>> + RoomDAO dao = >>>>>>>>>>>>>> Application.getBean(RoomDAO.class); >>>>>>>>>>>>>> + result.addAll(dao.getPublicRooms()); >>>>>>>>>>>>>> + for (Organisation_Users ou : >>>>>>>>>>>>>> Application.getBean(UsersDaoImpl.class).get(WebSession.getUserId()).getOrganisation_users()) >>>>>>>>>>>>>> { >>>>>>>>>>>>>> + >>>>>>>>>>>>>> result.addAll(dao.getOrganisationRooms(ou.getOrganisation().getOrganisation_id())); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + if (getModelObject().getRoom() != null && >>>>>>>>>>>>>> getModelObject().getRoom().getAppointment()) { //FIXME review >>>>>>>>>>>>>> + >>>>>>>>>>>>>> result.add(getModelObject().getRoom()); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + return result; >>>>>>>>>>>>>> } >>>>>>>>>>>>>> } >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>> URL: >>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>> >>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>> (original) >>>>>>>>>>>>>> +++ >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> @@ -71,7 +71,7 @@ >>>>>>>>>>>>>> $('#appointment').dialog({ >>>>>>>>>>>>>> closeOnEscape: true >>>>>>>>>>>>>> , resizable: true >>>>>>>>>>>>>> - , width: 400 >>>>>>>>>>>>>> + , width: 450 >>>>>>>>>>>>>> , autoOpen: false >>>>>>>>>>>>>> , modal: true >>>>>>>>>>>>>> }); >>>>>>>>>>>>>> @@ -89,53 +89,55 @@ >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="572" /></td> >>>>>>>>>>>>>> <td><input >>>>>>>>>>>>>> type="text" wicket:id="appointmentName" /></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> - <!-- tr> >>>>>>>>>>>>>> - >>>>>>>>>>>>>> <td> </td> >>>>>>>>>>>>>> - <td> >>>>>>>>>>>>>> - >>>>>>>>>>>>>> <wicket:ommessage key="570" /><input type="text" >>>>>>>>>>>>>> wicket:id="appointmentStarttime" /> >>>>>>>>>>>>>> - >>>>>>>>>>>>>> <wicket:ommessage key="571" /><input type="text" >>>>>>>>>>>>>> wicket:id="appointmentEndtime" /> >>>>>>>>>>>>>> - </td> >>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>> + >>>>>>>>>>>>>> <td><wicket:ommessage key="570" /></td> >>>>>>>>>>>>>> + <td><span >>>>>>>>>>>>>> wicket:id="appointmentStarttime"></span></td> >>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>> + >>>>>>>>>>>>>> <td><wicket:ommessage key="571" /></td> >>>>>>>>>>>>>> + <td><span >>>>>>>>>>>>>> wicket:id="appointmentEndtime"></span></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="565" /></td> >>>>>>>>>>>>>> - <td><select >>>>>>>>>>>>>> wicket:id="notification" ></select></td> >>>>>>>>>>>>>> + <td><select >>>>>>>>>>>>>> wicket:id="remind" ></select></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> <td >>>>>>>>>>>>>> colspan="2"><input type="checkbox" wicket:id="createRoom" >>>>>>>>>>>>>> /><wicket:ommessage key="1509" /></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="619" /></td> >>>>>>>>>>>>>> - <td><select >>>>>>>>>>>>>> wicket:id="roomType" ></select></td> >>>>>>>>>>>>>> + <td><select >>>>>>>>>>>>>> wicket:id="room.roomtype" ></select></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="406" /></td> >>>>>>>>>>>>>> <td><select >>>>>>>>>>>>>> wicket:id="room" ></select></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> - <td >>>>>>>>>>>>>> colspan="2"><input type="checkbox" >>>>>>>>>>>>>> wicket:id="isPasswordProtected" >>>>>>>>>>>>>> /><wicket:ommessage key="1509" /></td> >>>>>>>>>>>>>> + <td >>>>>>>>>>>>>> colspan="2"><input type="checkbox" >>>>>>>>>>>>>> wicket:id="isPasswordProtected" >>>>>>>>>>>>>> /><wicket:ommessage key="524" /></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="525" /></td> >>>>>>>>>>>>>> - <td><input >>>>>>>>>>>>>> type="text" wicket:id="password" /></td> >>>>>>>>>>>>>> + <td><input >>>>>>>>>>>>>> type="password" wicket:id="password" /></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> <td >>>>>>>>>>>>>> colspan="2"><wicket:ommessage key="1445" /></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> + <!-- >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="803" /></td> >>>>>>>>>>>>>> <td><select >>>>>>>>>>>>>> wicket:id="meetingMember" ></select></td> >>>>>>>>>>>>>> - </tr> >>>>>>>>>>>>>> + </tr --> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="569" /></td> >>>>>>>>>>>>>> <td><input >>>>>>>>>>>>>> type="text" wicket:id="appointmentLocation" /></td> >>>>>>>>>>>>>> - </tr--> >>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>> >>>>>>>>>>>>>> <td><wicket:ommessage key="573" /></td> >>>>>>>>>>>>>> - <td><input >>>>>>>>>>>>>> type="text" wicket:id="appointmentDescription" /></td> >>>>>>>>>>>>>> + <td><textarea >>>>>>>>>>>>>> wicket:id="appointmentDescription"></textarea></td> >>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>> <!-- tr> >>>>>>>>>>>>>> <td >>>>>>>>>>>>>> colspan="2" style="text-align: right"><input type="button" >>>>>>>>>>>>>> wicket:id="save" >>>>>>>>>>>>>> /><input type="button" wicket:id="cancel" /></td> >>>>>>>>>>>>>> - </tr--> >>>>>>>>>>>>>> + </tr --> >>>>>>>>>>>>>> </table> >>>>>>>>>>>>>> </form> >>>>>>>>>>>>>> </div> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>> URL: >>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>> >>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>> (original) >>>>>>>>>>>>>> +++ >>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>> @@ -150,6 +150,9 @@ public class CalendarPanel extends UserP >>>>>>>>>>>>>> Calendar end = >>>>>>>>>>>>>> WebSession.getCalendar(); >>>>>>>>>>>>>> >>>>>>>>>>>>>> end.setTimeInMillis(getRequestCycle().getRequest().getRequestParameters().getParameterValue("_end").toLong()); >>>>>>>>>>>>>> >>>>>>>>>>>>>> + if (start.equals(end)) { >>>>>>>>>>>>>> + >>>>>>>>>>>>>> end.add(Calendar.HOUR_OF_DAY, 1); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> Appointment a = new >>>>>>>>>>>>>> Appointment(); >>>>>>>>>>>>>> >>>>>>>>>>>>>> a.setAppointmentStarttime(start.getTime()); >>>>>>>>>>>>>> >>>>>>>>>>>>>> a.setAppointmentEndtime(end.getTime()); >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>> [email protected] >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>> [email protected] >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Sebastian Wagner >>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>> http://www.webbase-design.de >>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>> [email protected] >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> WBR >>>>>>>> Maxim aka solomax >>>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Sebastian Wagner >>>>>>> https://twitter.com/#!/dead_lock >>>>>>> http://www.webbase-design.de >>>>>>> http://www.wagner-sebastian.com >>>>>>> [email protected] >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> WBR >>>>>> Maxim aka solomax >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Sebastian Wagner >>>>> https://twitter.com/#!/dead_lock >>>>> http://www.webbase-design.de >>>>> http://www.wagner-sebastian.com >>>>> [email protected] >>>>> >>>> >>>> >>>> >>>> -- >>>> WBR >>>> Maxim aka solomax >>>> >>> >>> >>> >>> -- >>> Sebastian Wagner >>> https://twitter.com/#!/dead_lock >>> http://www.webbase-design.de >>> http://www.wagner-sebastian.com >>> [email protected] >>> >> >> >> >> -- >> Sebastian Wagner >> https://twitter.com/#!/dead_lock >> http://www.webbase-design.de >> http://www.wagner-sebastian.com >> [email protected] >> > > > > -- > WBR > Maxim aka solomax > -- Sebastian Wagner https://twitter.com/#!/dead_lock http://www.webbase-design.de http://www.wagner-sebastian.com [email protected]
