BrightSide Workbench Full Report + Source Code
PollControl.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2018 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.polls;
20 
21 import java.util.Collection;
22 import java.util.Date;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25 import org.apache.commons.mail.EmailException;
26 import org.turro.action.IEntityHolder;
27 import org.turro.assistant.Assistant;
28 import org.turro.assistant.AssistantSet;
29 import org.turro.auth.Authentication;
30 import org.turro.command.Command;
31 import org.turro.command.Context;
32 import org.turro.elephant.context.Application;
33 import org.turro.elephant.context.ElephantContext;
34 import org.turro.elephant.context.IConstructor;
35 import org.turro.elephant.entities.db.Poll;
36 import org.turro.elephant.util.Messages;
37 import org.turro.entities.Entities;
38 import org.turro.i18n.I_;
39 import org.turro.mail.message.MailMessageTemplate;
40 import org.turro.mail.pool.MailMessagePool;
41 import org.turro.mail.provider.MailProviders;
42 import org.turro.marker.ElephantMarker;
43 import org.turro.plugin.contacts.ContactList;
44 import org.turro.plugin.contacts.IContact;
45 import org.turro.mail.recipients.IMailRecipients;
46 import org.turro.zkoss.input.DateboxShort;
47 import org.turro.zkoss.input.GenericBandbox;
48 import org.turro.zkoss.input.GenericCombobox;
49 import org.turro.zkoss.input.GenericListbox;
50 import org.turro.zkoss.input.KnowsID;
51 import org.turro.zkoss.input.Percentbox;
52 import org.turro.zkoss.text.WikiEditor;
53 import org.zkoss.zk.ui.Executions;
54 import org.zkoss.zk.ui.HtmlBasedComponent;
55 import org.zkoss.zk.ui.IdSpace;
56 import org.zkoss.zk.ui.event.Event;
57 import org.zkoss.zk.ui.event.Events;
58 import org.zkoss.zk.ui.event.InputEvent;
59 import org.zkoss.zk.ui.ext.AfterCompose;
60 import org.zkoss.zk.ui.select.Selectors;
61 import org.zkoss.zk.ui.select.annotation.Listen;
62 import org.zkoss.zk.ui.select.annotation.Wire;
63 import org.zkoss.zul.Checkbox;
64 import org.zkoss.zul.Datebox;
65 import org.zkoss.zul.Hlayout;
66 import org.zkoss.zul.Intbox;
67 import org.zkoss.zul.Label;
68 import org.zkoss.zul.Listbox;
69 import org.zkoss.zul.Longbox;
70 import org.zkoss.zul.Panel;
71 import org.zkoss.zul.Space;
72 import org.zkoss.zul.Textbox;
73 import org.zkoss.zul.Timebox;
74 
79 public class PollControl extends Panel implements IdSpace, AfterCompose {
80 
81  private Poll poll;
82 
83  @Wire("#polls")
84  private PollListbox polls;
85 
86  @Wire("#title")
87  private Textbox title;
88 
89  @Wire("#location")
90  private Textbox location;
91 
92  @Wire("#deadline")
93  private Datebox deadline;
94 
95  @Wire("#maxPerOption")
96  private Intbox maxPerOption;
97 
98  @Wire("#maxVotedOptions")
99  private Intbox maxVotedOptions;
100 
101  @Wire("#optionType")
102  private OptionDataListbox optionType;
103 
104  @Wire("#maxmin")
105  private Hlayout maxmin;
106 
107  @Wire("#showParticipants")
108  private Checkbox showParticipants;
109 
110  @Wire("#showVotes")
111  private Checkbox showVotes;
112 
113  @Wire("#allowInsertions")
114  private Checkbox allowInsertions;
115 
116  @Wire("#allowNegatives")
117  private Checkbox allowNegatives;
118 
119  @Wire("#pollWiki")
120  private WikiEditor pollWiki;
121 
122  @Wire("#optionGrid")
123  private PollOptionGrid optionGrid;
124 
125  @Wire("#votesGrid")
126  private PollVotesGrid votesGrid;
127 
128  @Wire("#attachments")
129  private IEntityHolder attachments;
130 
131  @Wire("#files")
132  private IEntityHolder files;
133 
134  @Listen("onSelect = #polls")
135  public void onSelectPoll() {
136  setPoll(polls.getObjectValue());
137  }
138 
139  @Listen("onChange = #title")
140  public void onTitleChange(InputEvent event) {
141  if(poll != null) poll.setTitle(event.getValue());
142  }
143 
144  @Listen("onChange = #location")
145  public void onLocationChange(InputEvent event) {
146  if(poll != null) poll.setLocation(event.getValue());
147  }
148 
149  @Listen("onChange = #deadline")
150  public void onDeadlineChange() {
151  if(poll != null) poll.setDeadline(deadline.getValue());
152  }
153 
154  @Listen("onChange = #maxPerOption")
155  public void onMaxPerOptionChange(InputEvent event) {
156  if(poll != null) poll.setMaxPerOption(Integer.valueOf(event.getValue()));
157  }
158 
159  @Listen("onChange = #maxVotedOptions")
160  public void onMaxVotedOptionsChange(InputEvent event) {
161  if(poll != null) poll.setMaxVotedOptions(Integer.valueOf(event.getValue()));
162  }
163 
164  @Listen("onSelect = #optionType")
165  public void onTypeSelect() {
166  if(poll != null) {
167  poll.setOptionClass(optionType.getObjectValue().getType());
168  createMaxmin(null, null);
169  }
170  }
171 
172  @Listen("onCheck = #showParticipants")
173  public void onCheckParticipants() {
174  if(poll != null) poll.setShowParticipants(showParticipants.isChecked());
175  }
176 
177  @Listen("onCheck = #showVotes")
178  public void onCheckVotes() {
179  if(poll != null) poll.setShowVotes(showVotes.isChecked());
180  }
181 
182  @Listen("onCheck = #allowInsertions")
183  public void onCheckInsertions() {
184  if(poll != null) poll.setAllowInsertions(allowInsertions.isChecked());
185  }
186 
187  @Listen("onCheck = #allowNegatives")
188  public void onCheckNegatives() {
189  if(poll != null) poll.setAllowNegatives(allowNegatives.isChecked());
190  }
191 
192  @Listen("onChange = #pollWiki")
193  public void onWikiChange(InputEvent event) {
194  if(poll != null) poll.setWiki(event.getValue());
195  }
196 
197  @Listen("onClick = #createPoll")
198  public void onCreatePoll() {
199  Poll poll = new Poll();
202  setPoll(poll);
203  }
204 
205  @Listen("onClick = #savePoll")
206  public void onSave() {
207  if(poll != null) {
208  poll = PollsUtil.savePoll(poll, optionGrid.getValues());
210  polls.setObjectValue(poll);
211  setPoll(polls.getObjectValue());
212  }
213  }
214 
215  @Listen("onClick = #deletePoll")
216  public void onDelete() {
217  if(poll != null) {
218  Messages.confirmDeletion().add(poll.getTitle()).show(() -> {
219  PollsUtil.removePoll(poll);
221  setPoll(polls.getObjectValue());
222  });
223  }
224  }
225 
226  @Listen("onClick = #sendTest")
227  public void onSendTest() {
228  ContactList contacts = new ContactList();
229  contacts.add(Authentication.getIContact());
230  IMailRecipients.selectRecipients(contacts, new Command() {
231  @Override
232  public Object execute(Context context) {
233  IMailRecipients mr = (IMailRecipients) context.get("component");
234  Collection<IContact> emails = mr.getRecipients();
235  if(emails != null) {
236  AssistantSet as = new AssistantSet();
237  as.addContacts(emails);
238  doSend(as);
239  }
240  return null;
241  }
242  });
243  }
244 
245  @Listen("onClick = #send")
246  public void onSend() {
247  doSend(poll.getParticipants());
248  }
249 
250  public void setPoll(Poll poll) {
251  this.poll = poll;
252  updateControls();
253  }
254 
255  private void updateControls() {
256  if(poll != null) {
257  title.setValue(poll.getTitle());
258  title.setPlaceholder(I_.get("Title"));
259  title.setReadonly(false);
260  location.setValue(poll.getLocation());
261  location.setReadonly(false);
262  deadline.setValue(poll.getDeadline());
263  deadline.setReadonly(false);
264  maxPerOption.setValue(poll.getMaxPerOption());
265  maxPerOption.setReadonly(false);
266  maxVotedOptions.setValue(poll.getMaxVotedOptions());
267  maxVotedOptions.setReadonly(false);
268  optionType.setObjectValue(OptionDataType.getOptionType(poll.getOptionClass()));
269  optionType.setDisabled(false);
270  createMaxmin(poll.getOptionStart(), poll.getOptionEnd());
271  showParticipants.setChecked(poll.isShowParticipants());
272  showVotes.setChecked(poll.isShowVotes());
273  allowInsertions.setChecked(poll.isAllowInsertions());
274  allowNegatives.setChecked(poll.isAllowNegatives());
275  pollWiki.setImageFolder("/_internal/files/poll/" + poll.getId());
276  pollWiki.setFileFolder("/_internal/files/poll/" + poll.getId());
277  pollWiki.setValue(poll.getWiki());
278  pollWiki.setReadOnlyRepository(false);
279  if(poll.getId() != null && poll.getId() > 0) {
280  optionGrid.setAllowInsertions(true);
281  optionGrid.setAllowDeletions(true);
282  optionGrid.setReadOnly(false);
283  optionGrid.setPoll(poll);
284  votesGrid.setPoll(poll);
285  } else {
286  optionGrid.setAllowInsertions(false);
287  optionGrid.setAllowDeletions(false);
288  optionGrid.setReadOnly(true);
289  optionGrid.setPoll(null);
290  votesGrid.setPoll(null);
291  }
292  attachments.setEntity(poll);
293  attachments.refreshControls();
294  files.setEntity(poll);
295  files.refreshControls();
296  } else {
297  title.setValue(null);
298  title.setPlaceholder(null);
299  title.setReadonly(true);
300  location.setValue(null);
301  location.setReadonly(true);
302  deadline.setValue(null);
303  deadline.setReadonly(true);
304  maxPerOption.setValue(0);
305  maxPerOption.setReadonly(true);
306  maxVotedOptions.setValue(0);
307  maxVotedOptions.setReadonly(true);
308  optionType.setObjectValue(OptionDataType.OPTION_STRING);
309  optionType.setDisabled(true);
310  pollWiki.setImageFolder("/_internal/files/poll/empty");
311  pollWiki.setFileFolder("/_internal/files/poll/empty");
312  pollWiki.setValue(null);
313  pollWiki.setReadOnlyRepository(true);
314  showParticipants.setChecked(false);
315  showVotes.setChecked(false);
316  allowInsertions.setChecked(false);
317  allowNegatives.setChecked(false);
318  optionGrid.setAllowInsertions(false);
319  optionGrid.setAllowDeletions(false);
320  optionGrid.setReadOnly(true);
321  optionGrid.setPoll(null);
322  votesGrid.setPoll(null);
323  attachments.setEntity(null);
324  attachments.refreshControls();
325  files.setEntity(null);
326  files.refreshControls();
327  }
328  }
329 
330  /* Controls */
331 
332  public PollControl() {
333  Executions.createComponents("/WEB-INF/_zul/bs/comps/poll/pollControl.zul", this, null);
334  Selectors.wireComponents(this, this, false);
335  Selectors.wireEventListeners(this, this);
336  }
337 
338  protected String entityPath;
339  protected Object entity;
340 
341  public String getEntityPath() {
342  return entityPath;
343  }
344 
345  public void setEntityPath(String entityPath) {
346  this.entityPath = entityPath;
347  }
348 
349  public Object getEntity() {
350  return entity;
351  }
352 
353  public void setEntity(Object entity) {
354  this.entity = entity;
355  if(entity != null) {
357  }
358  }
359 
360  @Override
361  public void afterCompose() {
363  setPoll(polls.getObjectValue());
364  }
365 
366  /* Mail */
367 
368  protected void doSend(AssistantSet participants) {
370  MailMessagePool pool = MailProviders.instance().getGeneric(constructor);
371  if(pool != null) {
372  for(Assistant assistant : participants) {
373  try {
375  mmt.setSubject(I_.get("Poll") + ": " + poll.getTitle() + " - " + ElephantContext.getSiteName());
376  mmt.addTo(assistant.email, assistant.name);
377  ElephantMarker em = new ElephantMarker(constructor, true);
378  em.put("poll", poll);
379  em.put("contact", assistant.contact);
380  em.put("email", assistant.email);
381  em.put("notifier", this);
382  em.put("iee", Entities.getController(entity));
383  em.put("template", PollIterator.getOptionTemplate(poll));
384  mmt.setRoot("/poll");
385  mmt.setMessage(em, "poll", assistant.contact);
386  pool.addToPool(mmt);
387  pool.sendPool();
388  } catch (EmailException ex) {
389  Logger.getLogger(PollControl.class.getName()).log(Level.SEVERE, ElephantContext.logMsg(null), ex);
390  }
391  }
392  }
393  }
394 
395  /* Maxmin */
396 
397  private void createMaxmin(Object min, Object max) {
398  if(poll != null) {
399  maxmin.getChildren().clear();
400  HtmlBasedComponent minEditor = getEditor(poll.getOptionClass(), false, min);
401  minEditor.addEventListener(Events.ON_CHANGE, (Event event) -> {
402  poll.setOptionStart(getFormattedString(poll.getOptionClass(), getEditorValue(minEditor)));
403  });
404  maxmin.appendChild(new Label(I_.get("Min value")));
405  maxmin.appendChild(minEditor);
406  HtmlBasedComponent maxEditor = getEditor(poll.getOptionClass(), false, max);
407  maxEditor.addEventListener(Events.ON_CHANGE, (Event event) -> {
408  poll.setOptionEnd(getFormattedString(poll.getOptionClass(), getEditorValue(maxEditor)));
409  });
410  maxmin.appendChild(new Space());
411  maxmin.appendChild(new Label(I_.get("Max value")));
412  maxmin.appendChild(maxEditor);
413  }
414  }
415 
416  /* Editor helpers */
417 
418  public static HtmlBasedComponent getEditor(String optionClass, boolean readonly, Object value) {
419  if(OptionDataType.OPTION_DATETIME.getType().equals(optionClass)) {
420  DateboxShort db = new DateboxShort((Date) OptionDataType.OPTION_DATETIME.getValue((String) value));
421  db.setWithTime(true);
422  db.setReadonly(readonly);
423  return db;
424  } else if(OptionDataType.OPTION_DATE.getType().equals(optionClass)) {
425  DateboxShort db = new DateboxShort((Date) OptionDataType.OPTION_DATE.getValue((String) value));
426  db.setWithTime(false);
427  db.setReadonly(readonly);
428  return db;
429  } else if(OptionDataType.OPTION_TIME.getType().equals(optionClass)) {
430  Timebox db = new Timebox((Date) OptionDataType.OPTION_TIME.getValue((String) value));
431  db.setReadonly(readonly);
432  return db;
433  } else if(OptionDataType.OPTION_LONG.getType().equals(optionClass)) {
434  Longbox db = new Longbox((Long) OptionDataType.OPTION_LONG.getValue((String) value));
435  db.setReadonly(readonly);
436  return db;
437  } else {
438  Textbox tb = new Textbox((String) value);
439  tb.setReadonly(readonly);
440  tb.setMaxlength(255);
441  return tb;
442  }
443  }
444 
445  public static String getFormattedString(String optionClass, Object value) {
446  return OptionDataType.getOptionType(optionClass).getString(value);
447  }
448 
449  public static Object getEditorValue(HtmlBasedComponent hbc) {
450  if(hbc instanceof Checkbox) {
451  return ((Checkbox) hbc).isChecked();
452  } else if(hbc instanceof Percentbox) {
453  return ((Percentbox) hbc).getValue();
454  } else if(hbc instanceof Longbox) {
455  return ((Longbox) hbc).getValue();
456  } else if(hbc instanceof Datebox) {
457  return ((Datebox) hbc).getValue();
458  } else if(hbc instanceof Timebox) {
459  return ((Timebox) hbc).getValue();
460  } else if(hbc instanceof KnowsID) {
461  return ((KnowsID) hbc).getObjectId();
462  } else if(hbc instanceof GenericListbox) {
463  return ((GenericListbox) hbc).getObjectValue();
464  } else if(hbc instanceof GenericCombobox) {
465  return ((GenericCombobox) hbc).getObjectValue();
466  } else if(hbc instanceof GenericBandbox) {
467  return ((GenericBandbox) hbc).getObjectValue();
468  } else if(hbc instanceof Listbox) {
469  return ((Listbox) hbc).getSelectedItem().getValue();
470  } else {
471  return ((Textbox) hbc).getValue();
472  }
473  }
474 
475 }
void addContacts(Collection< IContact > contacts)
void setTitle(String title)
Definition: Poll.java:87
void setMaxPerOption(int maxPerOption)
Definition: Poll.java:136
void setAllowNegatives(boolean allowNegatives)
Definition: Poll.java:176
void setMaxVotedOptions(int maxVotedOptions)
Definition: Poll.java:144
void setShowParticipants(boolean showParticipants)
Definition: Poll.java:152
void setEntityPath(String entityPath)
Definition: Poll.java:103
void setLocation(String location)
Definition: Poll.java:95
void setShowVotes(boolean showVotes)
Definition: Poll.java:160
void setOptionClass(String optionClass)
Definition: Poll.java:184
void setDeadline(Date deadline)
Definition: Poll.java:111
void setAllowInsertions(boolean allowInsertions)
Definition: Poll.java:168
static Messages confirmDeletion()
Definition: Messages.java:87
Messages add(String word)
Definition: Messages.java:50
static IElephantEntity getController(String path)
Definition: Entities.java:78
static String get(String msg)
Definition: I_.java:41
MailMessage addToPool(String from, String to, String cc, String subject, String message)
static void selectRecipients(Collection< IContact > recipients, Command command)
Object put(Object key, Object value)
void onTitleChange(InputEvent event)
void doSend(AssistantSet participants)
void onMaxPerOptionChange(InputEvent event)
static Object getEditorValue(HtmlBasedComponent hbc)
static HtmlBasedComponent getEditor(String optionClass, boolean readonly, Object value)
void onWikiChange(InputEvent event)
void onLocationChange(InputEvent event)
void setEntityPath(String entityPath)
void onMaxVotedOptionsChange(InputEvent event)
static String getFormattedString(String optionClass, Object value)
void setEntity(Object entity)
static String getOptionTemplate(Poll poll)
static List< Poll > getPolls(String entityPath)
Definition: PollsUtil.java:148
static void removePoll(Poll poll)
Definition: PollsUtil.java:170
static Poll savePoll(Poll poll, List< PollOption > pos)
Definition: PollsUtil.java:157
void setAllowDeletions(boolean allowDeletions)
void setAllowInsertions(boolean allowInsertions)
void setReadOnly(boolean readOnly)
void setWithTime(boolean withTime)
void setImageFolder(String folder)
void setValue(String value)
Definition: WikiEditor.java:98
void setFileFolder(String folder)
void setReadOnlyRepository(boolean readOnlyRepository)
String getString(Object value)
static OptionDataType getOptionType(String value)
void setEntity(Object entity)