Skip to content

Commit 9923f59

Browse files
committed
iCalendar notifications
1 parent 581f030 commit 9923f59

File tree

12 files changed

+150
-42
lines changed

12 files changed

+150
-42
lines changed

logicaldoc-core/src/main/java/com/logicaldoc/core/automation/StringTool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class StringTool {
1919
* @return the passed in String, or the empty String if it was null
2020
*/
2121
public String defaultString(String str) {
22-
return StringUtils.defaultString(str);
22+
return StringUtils.defaultIfEmpty(str, "");
2323
}
2424

2525
/**

logicaldoc-core/src/main/java/com/logicaldoc/core/communication/EMail.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ public class EMail extends Message {
4949
*/
5050
private long accountId;
5151

52+
/**
53+
* Optional headers to put in the email
54+
*/
55+
private Map<String, String> headers = new HashMap<>();
56+
5257
private Map<Integer, EMailAttachment> attachments = new HashMap<>();
5358

5459
private Recipient from;
@@ -336,4 +341,12 @@ public boolean equals(Object obj) {
336341
return false;
337342
return true;
338343
}
344+
345+
public Map<String, String> getHeaders() {
346+
return headers;
347+
}
348+
349+
public void setHeaders(Map<String, String> headers) {
350+
this.headers = headers;
351+
}
339352
}

logicaldoc-core/src/main/java/com/logicaldoc/core/communication/EMailAttachment.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,22 @@ public class EMailAttachment implements Serializable {
3434
private long size;
3535

3636
private String mimeType = "";
37+
38+
/**
39+
* Should be used to fill the Content-Disposition header
40+
*/
41+
private String disposition;
3742

43+
/**
44+
* Should be used to fill the Content-Type header
45+
*/
46+
private String contentType;
47+
48+
/**
49+
* Should be used to fill the Content-Transfer-Encoding header
50+
*/
51+
private String contentEncoding;
52+
3853
private String fileName = "";
3954

4055
public String getIcon() {
@@ -129,4 +144,28 @@ public String parseContent(Long tenantId, Locale locale, String encoding) {
129144

130145
return content;
131146
}
147+
148+
public String getDisposition() {
149+
return disposition;
150+
}
151+
152+
public void setDisposition(String disposition) {
153+
this.disposition = disposition;
154+
}
155+
156+
public String getContentType() {
157+
return contentType;
158+
}
159+
160+
public void setContentType(String contentType) {
161+
this.contentType = contentType;
162+
}
163+
164+
public String getContentEncoding() {
165+
return contentEncoding;
166+
}
167+
168+
public void setContentEncoding(String contentEncoding) {
169+
this.contentEncoding = contentEncoding;
170+
}
132171
}

logicaldoc-core/src/main/java/com/logicaldoc/core/communication/EMailSender.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,11 @@ public void sendAsync(EMail email, String templateName, Map<String, Object> dict
251251
* @param dictionary The dictionary to be used in the template
252252
*
253253
* @throws MessagingException raised if the email cannot be sent
254-
* @throws AutomationException the automation has been evaluated but produced an error
254+
* @throws AutomationException the automation has been evaluated but
255+
* produced an error
255256
*/
256-
public void send(EMail email, String templateName, Map<String, Object> dictionary) throws MessagingException, AutomationException {
257+
public void send(EMail email, String templateName, Map<String, Object> dictionary)
258+
throws MessagingException, AutomationException {
257259
if (!RunLevel.current().aspectEnabled("sendingMessages")) {
258260
log.error("Aspect not enabled");
259261
throw new MessagingException("Aspect sendingMessages not enabled");
@@ -309,6 +311,8 @@ public void send(EMail email) throws MessagingException {
309311
Session session = newMailSession();
310312

311313
MimeMessage message = new MimeMessage(session);
314+
for (Map.Entry<String, String> line : email.getHeaders().entrySet())
315+
message.addHeaderLine(line.getKey() + "=" + line.getValue());
312316

313317
// The FROM field must to be the one configured for the SMTP connection.
314318
// because of errors will be returned in the case the sender is not in
@@ -318,20 +322,23 @@ public void send(EMail email) throws MessagingException {
318322
Set<InternetAddress> cc = email.getAddressesCC();
319323
Set<InternetAddress> bcc = email.getAddressesBCC();
320324
message.setFrom(from);
321-
message.setRecipients(javax.mail.Message.RecipientType.TO, to.toArray(new InternetAddress[0]));
325+
if (CollectionUtils.isNotEmpty(to))
326+
message.setRecipients(javax.mail.Message.RecipientType.TO, to.toArray(new InternetAddress[0]));
322327
if (CollectionUtils.isNotEmpty(cc))
323328
message.setRecipients(javax.mail.Message.RecipientType.CC, cc.toArray(new InternetAddress[0]));
324-
if (CollectionUtils.isNotEmpty(cc))
329+
if (CollectionUtils.isNotEmpty(bcc))
325330
message.setRecipients(javax.mail.Message.RecipientType.BCC, bcc.toArray(new InternetAddress[0]));
326331
message.setSubject(email.getSubject(), UTF_8);
327332

328-
MimeBodyPart body = buildBodyPart(email);
329-
330333
/*
331334
* If we have to images, the parts must be 'related' otherwise 'mixed'
332335
*/
333336
Multipart mpMessage = new MimeMultipart(email.getImages().isEmpty() ? "mixed" : "related");
334-
mpMessage.addBodyPart(body);
337+
338+
if (StringUtils.isNotEmpty(email.getMessageText())) {
339+
MimeBodyPart body = buildBodyPart(email);
340+
mpMessage.addBodyPart(body);
341+
}
335342

336343
int i = 1;
337344
for (String image : email.getImages()) {
@@ -362,6 +369,19 @@ public void send(EMail email) throws MessagingException {
362369
} catch (UnsupportedEncodingException e) {
363370
throw new MessagingException(e.getMessage(), e);
364371
}
372+
373+
if (StringUtils.isNotEmpty(att.getDisposition()))
374+
if ("remove".equals(att.getDisposition()))
375+
part.removeHeader("Content-Disposition");
376+
else
377+
part.setDisposition(att.getDisposition());
378+
379+
if (StringUtils.isNotEmpty(att.getContentType()))
380+
part.setHeader("Content-Type", att.getContentType());
381+
382+
if (StringUtils.isNotEmpty(att.getContentEncoding()))
383+
part.setHeader("Content-Transfer-Encoding", att.getContentEncoding());
384+
365385
mpMessage.addBodyPart(part);
366386
}
367387

@@ -530,7 +550,7 @@ private MimeBodyPart buildBodyPart(EMail email) throws MessagingException {
530550
}
531551

532552
private String detectMimeType(EMailAttachment att) {
533-
String mime = "text/plain";
553+
String mime = StringUtils.isEmpty(att.getMimeType()) ? att.getMimeType() : "text/plain";
534554
try {
535555
MagicMatch match = Magic.getMagicMatch(att.getData(), true);
536556
mime = match.getMimeType();

logicaldoc-gui/src/main/java/com/logicaldoc/gui/common/client/beans/GUICalendarEvent.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class GUICalendarEvent implements Serializable {
6666

6767
private String automation;
6868

69+
private boolean iCalendar = true;
70+
6971
@Override
7072
public String toString() {
7173
return getId() + "-" + getTitle();
@@ -304,12 +306,20 @@ public String getLocation() {
304306
public void setLocation(String location) {
305307
this.location = location;
306308
}
307-
309+
308310
public List<GUIGroup> getAttendeesGroups() {
309311
return attendeesGroups;
310312
}
311313

312314
public void setAttendeesGroups(List<GUIGroup> attendeesGroups) {
313315
this.attendeesGroups = attendeesGroups;
314316
}
317+
318+
public boolean isiCalendar() {
319+
return iCalendar;
320+
}
321+
322+
public void setiCalendar(boolean iCalendar) {
323+
this.iCalendar = iCalendar;
324+
}
315325
}

logicaldoc-gui/src/main/java/com/logicaldoc/gui/frontend/client/calendar/CalendarEventDialog.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.smartgwt.client.widgets.Window;
4242
import com.smartgwt.client.widgets.form.DynamicForm;
4343
import com.smartgwt.client.widgets.form.ValuesManager;
44+
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
4445
import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
4546
import com.smartgwt.client.widgets.form.fields.DateItem;
4647
import com.smartgwt.client.widgets.form.fields.LinkItem;
@@ -59,6 +60,8 @@
5960
import com.smartgwt.client.widgets.menu.MenuItem;
6061
import com.smartgwt.client.widgets.tab.Tab;
6162
import com.smartgwt.client.widgets.tab.TabSet;
63+
import com.smartgwt.client.widgets.toolbar.ToolStrip;
64+
import com.smartgwt.client.widgets.toolbar.ToolStripButton;
6265

6366
/**
6467
* This is the form used for editing a calendar event.
@@ -143,27 +146,27 @@ public CalendarEventDialog(GUICalendarEvent calendarEvent, AsyncCallback<Void> o
143146
tabs.setHeight100();
144147
addItem(tabs);
145148

146-
HLayout buttonsPanel = new HLayout();
149+
ToolStrip buttonsBar = new ToolStrip();
150+
buttonsBar.setWidth100();
147151

148-
IButton save = new IButton();
149-
save.setMargin(3);
150-
save.setHeight(30);
151-
save.setTitle(I18N.message("save"));
152+
ToolStripButton save = new ToolStripButton(I18N.message("save"));
152153
save.addClickHandler(event -> onSave());
154+
buttonsBar.addButton(save);
153155

154-
IButton delete = new IButton();
155-
delete.setMargin(3);
156-
delete.setHeight(30);
157-
delete.setTitle(I18N.message(DDELETE));
156+
ToolStripButton delete = new ToolStripButton(I18N.message(DDELETE));
158157
delete.addClickHandler(event -> onDelete());
159-
160158
if (calendarEvent.getId() != 0)
161-
buttonsPanel.setMembers(save, delete);
162-
else
163-
buttonsPanel.setMembers(save);
159+
buttonsBar.addButton(delete);
160+
161+
CheckboxItem iCalendar = ItemFactory.newCheckbox("icalendar", I18N.message("notifyicalendar"));
162+
iCalendar.setValue(calendarEvent.isiCalendar());
163+
iCalendar.addChangedHandler(changed -> calendarEvent.setiCalendar(iCalendar.getValueAsBoolean()));
164+
buttonsBar.addFormItem(iCalendar);
165+
166+
buttonsBar.addFill();
164167

165168
if (!readOnly)
166-
addItem(buttonsPanel);
169+
addItem(buttonsBar);
167170
}
168171

169172
private Tab prepareReminders() {
@@ -792,6 +795,7 @@ private void onSave() {
792795

793796
saveAttendees();
794797

798+
LD.contactingServer();
795799
CalendarService.Instance.get().saveEvent(calendarEvent, new AsyncCallback<>() {
796800
@Override
797801
public void onFailure(Throwable caught) {
@@ -800,6 +804,7 @@ public void onFailure(Throwable caught) {
800804

801805
@Override
802806
public void onSuccess(Void arg) {
807+
LD.clearPrompt();
803808
destroy();
804809
if (onChangedCallback != null)
805810
onChangedCallback.onSuccess(arg);
@@ -887,6 +892,7 @@ private void onDelete() {
887892
if (calendarEvent.getParentId() != null) {
888893
LD.ask(I18N.message("delevent"), I18N.message("douwantdeletealloccurrences"), answer -> {
889894
Long id = Boolean.TRUE.equals(answer) ? calendarEvent.getParentId() : calendarEvent.getId();
895+
LD.contactingServer();
890896
CalendarService.Instance.get().deleteEvent(id, new AsyncCallback<>() {
891897
@Override
892898
public void onFailure(Throwable caught) {
@@ -895,11 +901,13 @@ public void onFailure(Throwable caught) {
895901

896902
@Override
897903
public void onSuccess(Void arg) {
904+
LD.clearPrompt();
898905
destroy();
899906
}
900907
});
901908
});
902-
} else
909+
} else {
910+
LD.contactingServer();
903911
CalendarService.Instance.get().deleteEvent(calendarEvent.getId(), new AsyncCallback<>() {
904912

905913
@Override
@@ -909,11 +917,13 @@ public void onFailure(Throwable caught) {
909917

910918
@Override
911919
public void onSuccess(Void arg) {
920+
LD.clearPrompt();
912921
destroy();
913922
if (onChangedCallback != null)
914923
onChangedCallback.onSuccess(arg);
915924
}
916925
});
926+
}
917927
});
918928
}
919929

logicaldoc-gui/src/main/java/com/logicaldoc/gui/frontend/client/document/DocumentToolbar.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ private void addCalendar() {
302302
user.setUsername(Session.get().getUser().getUsername());
303303
user.setFirstName(Session.get().getUser().getFirstName());
304304
user.setName(Session.get().getUser().getName());
305+
user.setEmail(Session.get().getUser().getEmail());
305306
calEvent.addAttendee(user);
306307

307308
List<GUIDocument> docs = grid.getSelectedDocuments();

logicaldoc-i18n/src/main/resources/i18n/messages.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2614,4 +2614,5 @@ customId = Custom ID
26142614
thisdocsecurityparent = This document does not define any security policy so <u>the policies of the folder will be used instead</u>
26152615
onlyoffice = OnlyOffice
26162616
allowclientid = Allow use of Client ID to hook session
2617-
editwithonlyoffice = Edit with OnlyOffice
2617+
editwithonlyoffice = Edit with OnlyOffice
2618+
notifyicalendar = Send iCalendar notifications

logicaldoc-i18n/src/main/resources/i18n/messages_en.properties

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,8 @@ feature.Feature_102=Reading Confirmation
837837
feature.Feature_103=Technical Support
838838
feature.Feature_104=ChatGPT
839839
feature.Feature_105=Google Calendar
840+
feature.Feature_106=Scanner
841+
feature.Feature_107=OnlyOffice
840842

841843
licensevalid=The license is valid
842844
licenseinvalid=The license is not valid
@@ -1511,7 +1513,7 @@ columnsindocuments=Columns in the Documents screen
15111513
columnsinsearch=Columns in the Search screen
15121514
openfolderstree=Open folders tree
15131515
workspace=Workspace
1514-
maxversions=Max. Versions
1516+
maxversions=Max Versions
15151517
bbefore=Before
15161518
ssince=Since
15171519
clear=Clear
@@ -2609,4 +2611,8 @@ synchronizegooglecal = Synchronize with Google Calendar
26092611
calendarenabledtip = Enables/Disables the connection with Google Calendar
26102612
apisecret = API Secret
26112613
customId = Custom ID
2612-
thisdocsecurityparent = This document does not define any security policy so <u>the policies of the folder will be used instead</u>
2614+
thisdocsecurityparent = This document does not define any security policy so <u>the policies of the folder will be used instead</u>
2615+
onlyoffice = OnlyOffice
2616+
allowclientid = Allow use of Client ID to hook session
2617+
editwithonlyoffice = Edit with OnlyOffice
2618+
notifyicalendar = Send iCalendar notifications

logicaldoc-i18n/src/main/resources/i18n/messages_en_US.properties

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,8 @@ feature.Feature_102=Reading Confirmation
837837
feature.Feature_103=Technical Support
838838
feature.Feature_104=ChatGPT
839839
feature.Feature_105=Google Calendar
840+
feature.Feature_106=Scanner
841+
feature.Feature_107=OnlyOffice
840842

841843
licensevalid=The license is valid
842844
licenseinvalid=The license is not valid
@@ -1511,7 +1513,7 @@ columnsindocuments=Columns in the Documents screen
15111513
columnsinsearch=Columns in the Search screen
15121514
openfolderstree=Open folders tree
15131515
workspace=Workspace
1514-
maxversions=Max. Versions
1516+
maxversions=Max Versions
15151517
bbefore=Before
15161518
ssince=Since
15171519
clear=Clear
@@ -2609,4 +2611,8 @@ synchronizegooglecal = Synchronize with Google Calendar
26092611
calendarenabledtip = Enables/Disables the connection with Google Calendar
26102612
apisecret = API Secret
26112613
customId = Custom ID
2612-
thisdocsecurityparent = This document does not define any security policy so <u>the policies of the folder will be used instead</u>
2614+
thisdocsecurityparent = This document does not define any security policy so <u>the policies of the folder will be used instead</u>
2615+
onlyoffice = OnlyOffice
2616+
allowclientid = Allow use of Client ID to hook session
2617+
editwithonlyoffice = Edit with OnlyOffice
2618+
notifyicalendar = Send iCalendar notifications

0 commit comments

Comments
 (0)