Integrate your Web applications with your users' personal calendars.
I'll be the first to admit that I'm aging. How old am I? Well, that's a secret that I may divulge at the end of the article. But with age comes organization. Work days become hectic, and sometimes I need a reminder of what I'm supposed to do next. I'm sure some of your users need reminders at times too. That's where the concept of this article started.
Imagine this scenario. A user is on the phone with a customer, trying to resolve an issue. The user is logging the call on the system and indicates that she has promised to give a follow-up call in two days. Finally, the user puts a reminder on her personal calendar to call the customer back.
From Lotus Notes to Microsoft Outlook, email clients today include a calendar application. These calendar applications have built-in support for a file format named iCalendar. In the above scenario, the use of an iCalendar file could have eliminated the final step of manually adding the reminder to the user's personal calendar application.
The iCalendar file format is simply a plain-text file with an .ics extension. The file must always begin with BEGIN:VCALENDAR, and the last line of the file must always be END:VCALENDAR. Everything between the BEGIN and END lines represents the body of the iCalendar file.
Notice that the BEGIN and END statements are followed by the word VCALENDAR. The iCalendar file format is derived from the vCalendar file format. The VCALENDAR attributes were retained to maintain compatibility.
The basic file layout for an iCalendar file is illustrated in Figure 1.
BEGIN:VCALENDAR |
VERSION:2.0 |
BEGIN:VEVENT |
ORGANIZER:MAILTO: |
DTSTART:20090803T080000 |
DTEND:20090803T083000 |
DTSTAMP:20090802T103300 |
DESCRIPTION:Details of your reminder go here. |
SUMMARY:Subject for your reminder goes here. |
BEGIN:VALARM |
TRIGGER:-PT15M |
ACTION:DISPLAY |
DESCRIPTION:Alarm description goes here. |
END:VALARM |
END:VEVENT |
END:VCALENDAR |
Figure 1: This code illustrates the basic structure of an iCalendar file.
The BEGIN:VEVENT represents the beginning of the event. The DTSTART and DTEND attributes provide the starting and ending dates and times. The DTSTAMP shows the date and time the reminder was created. The DESCRIPTION and SUMMARY attributes provide a detailed description and a subject for the reminder.
The BEGIN:VALARM is the beginning of the reminder alarm attributes. In the above example, it is set to remind the user 15 minutes before the start time.
Figure 2 illustrates how to change the basic iCalendar file into a file that can be used in a CGIDEV2 Web application:
/$remindme-top Content-type: text/calendar BEGIN:VCALENDAR |
VERSION:2.0 |
BEGIN:VEVENT |
ORGANIZER:MAILTO: |
DTSTART:/%reminddate%/T080000 |
DTEND:/%reminddate%/T083000 |
DTSTAMP:/%currentdate%/T/%currenttime%/ |
DESCRIPTION:/%note%/ |
SUMMARY:/%subject%/ |
BEGIN:VALARM |
TRIGGER:-PT15M |
ACTION:DISPLAY |
DESCRIPTION:Alarm description goes here. |
END:VALARM |
END:VEVENT |
END:VCALENDAR |
Figure 2: Make these changes to the iCalendar file for use in CGIDEV2.
I've added a section name of remindme-top, as well as the content-type declaration for an iCalendar file. I've also replaced the starting date, ending date, current date, current time, description, and subject with variables. These variables will be populated in an RPG program.
The RPG program REMIND1 will display a Web page where the user can enter a subject, reminder date, and description. When the user submits the Web page, another RPG program will build an iCalendar file and allow the user to open the file. The file will open in the user's default program that handles .ics files. The source for the REMIND1 program is shown in Figure 3.
/copy qrpglesrc,hspecs /copy qrpglesrc,hspecsbnd h dftactgrp(*no) actgrp('REMIND1') /copy qrpglesrc,prototype /copy qrpglesrc,variables3 /copy qrpglesrc,usec d IfsMultIndicators... d ds d NoErrors n d NameTooLong n d NotAccessible n d NoFilesUsable n d DupSections n d FileIsEmpty n /copy qrpglesrc,prolog3 /free exsr RetrieveHtml; exsr Process; exsr Exit; // Retrieve html from the IFS begsr RetrieveHtml; SetNoDebug(*on); clrhtmlbuffer(); IfsMultIndicators = gethtmlifsmult('/htdocs/reminder.htm'); endsr; // Process screen begsr Process; updhtmlvar('pgm':GetEnv('SCRIPT_NAME':qusec)); updhtmlvar('title':'Calendar and CGIDEV2 Integration'); updhtmlvar('randomstring':RandomString(20)); wrtsection('reminder-top'); endsr; // Flush the html buffer to the browser and return begsr Exit; wrtsection('*fini'); *inlr = *on; endsr; |
Figure 3: Here's the source for the RPG program REMIND1.
Notice that the RetrieveHTML subroutine in the REMIND1 program loads the file REMINDER.HTM from the IFS. The source for the REMINDER.HTM is shown in Figure 4.
/$reminder-top Content-type: text/html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Sample CGIDEV2 Applications "/%pgm%/"></title> <script src="/js/prototype.js"></script> <script src="/js/calendarimport.js"></script> <link rel="stylesheet" href="/css/mc.css"> </head> <body> <table border="0" width="100%" cellpadding="3" cellspacing="0"> <tr> <td align="left" valign="middle"><img src="/images/mclogosmall.jpg" align="middle" alt="McClenny Consulting"></td> <td align="right">/%title%/</td> </tr> </table> <br><br> <p>This example will show how take information entered on a form, create a iCalendar file, and then import that file into your Microsoft Office Calendar. This example requires that you have an email client that supports iCalendar files.</p> <p>Simply enter in a subject, reminder date, and the supporting details, then click the Go button. Please note that the date must be in MM/DD/YYYY format. If you enter an invalid date, then the program will default to today's date.</p> <center> <form action="#"> <input value="/%randomstring%/"> <table > <tr> <td align="left"><strong>Subject:</strong></td> <td align="left"><input size="50" maxlength="50"></td> </tr> <tr> <td align="left"><strong>Reminder Date:</strong></td> <td align="left"><input size="15" maxlength="10"> (MM/DD/YYYY)</td> </tr> <tr> <td align="left"><strong>Details:</strong></td> <td align="left"><textarea cols="50" rows="5"></textarea></td> </tr> </table> <input value="Go" > </form> <br> <p><a href="/index.pgm">Return to CGIDEV2 examples</a></p> </center> </body> </html> |
Figure 4: This is the REMINDER.HTM source used in the REMIND1 RPG program.
Figure 5 shows the results of running the REMIND1 program in your browser.
Figure 5: This screen shot shows the Web page built in the REMIND1 RPG program. (Click image to enlarge.)
The REMINDER.HTM file contains two JavaScript functions in the header: prototype.js and calendarimport.js. Together, these two JavaScript functions are used to build the iCalendar file to be imported.
The function prototype.js is known as the Prototype JavaScript Framework. It is one of many JavaScript frameworks that can be used to ease the implementation of AJAX. This JavaScript function can be downloaded from the Prototype Web site at www.prototypejs.org.
The calendarimport.js function retrieves the values on the HTML form and calls another RPG program named REMIND2. Figure 6 shows the source for the calendarimport.js function.
function calendarimport() {
var xRandomString = $F('randomstring');
var xSubject = $F('subject');
var xRemindDate = $F('rdate');
var xNotes = $F('notes');
var url='remind2.pgm?subject=' + xSubject + '¬e=' + xNotes + '&reminddate=' + xRemindDate + '&randomstring=' + xRandomString;
new Ajax.Request(url , {method: 'get'});
window.open('/temp/' + xRandomString + '.ics');
return false;
}
Figure 6: Here's the source for the calendarimport.js JavaScript function.
The variables xRandomString, xSubject, xRemindDate, and xNotes are populated using the Prototype function $F. The $F function simply retrieves the values of the form fields in an HTML document. Notice that the form only has three visible input fields: subject, reminder date, and description. In the REMINDER.HTM, there is a fourth field that is hidden called randomstring. The program REMIND1 populates this hidden field with a random string of 20 characters using the CGIDEV2 RandomString procedure. This random string will become the name of the iCalendar file stored in the system.
The variable url is constructed to call the REMIND2 program, passing it the expected variables and contents entered on the form.
The Ajax.Request function is a Prototype function that can be used to call another RPG program. In this case, the url constructed in the prior line is called.
Finally, a new browser window is opened that will allow the user to open the iCalendar file.
The REMIND2 program called in the calendarimport.js JavaScript function will need to retrieve the iCalendar shell stored on the IFS, retrieve the values passed into the program (subject, reminder date, notes, and the random string), populate the variables in the iCalendar shell, and then save the iCalendar file to the IFS. Figure 7 shows the source for the REMIND2 program.
/copy qrpglesrc,hspecs /copy qrpglesrc,hspecsbnd h dftactgrp(*no) actgrp('REMIND2') /copy qrpglesrc,prototype /copy qrpglesrc,variables3 /copy qrpglesrc,usec d inpSubject s 50a d inpNote s 1000a d inpRemindDate s 10a d inpRandomString... d s 20a d FileName s 100a d WorkDate s d d IfsMultIndicators... d ds d NoErrors n d NameTooLong n d NotAccessible n d NoFilesUsable n d DupSections n d FileIsEmpty n /copy qrpglesrc,prolog3 /free exsr RetrieveHtml; exsr Process; exsr Exit; // Retrieve html from the IFS begsr RetrieveHtml; SetNoDebug(*on); clrhtmlbuffer(); IfsMultIndicators = gethtmlifsmult('/htdocs/remindme.ics'); endsr; // Process input parameters from the screen. begsr Process; inpSubject = zhbgetvar('subject'); inpNote = zhbgetvar('note'); inpRemindDate = zhbgetvar('reminddate'); inpRandomString = zhbgetvar('randomstring'); monitor; WorkDate = %date(inpRemindDate:*usa); on-error; WorkDate = %date(); endmon; updhtmlvar('reminddate':%char(WorkDate:*iso0)); updhtmlvar('currentdate':%char(%date():*iso0)); updhtmlvar('currenttime':%char(%time():*iso0)); updhtmlvar('note':inpNote); updhtmlvar('subject':inpSubject); wrtsection('remindme-top'); endsr; // Flush the html buffer to the browser and return begsr Exit; FileName = '/temp/' + %trim(inpRandomString) + '.ics'; rc = WrtHtmlToStmf(%trim(FileName)); *inlr = *on; endsr; |
Figure 7: The REMIND2 program builds the iCalendar file and saves it to the IFS.
One additional change is required in order to be able to open the iCalendar file. The configuration for the HTTP server will need to be changed so that it will recognize the .ics file. The content type of the iCalendar file is text/calendar. If this type is not already defined in the Apache configuration file, it will need to be inserted. Simply add the following line to your configuration file:
AddType text/calendar .ics
Integrating a Web application with a user's personal calendar can be an integral part of any successful application. By using CGIDEV2, the Prototype Framework, and an iCalendar file, it's never been easier.
Oh, and I almost forgot. At the time I'm writing this, I'm a youthful, but graying, 42.
LATEST COMMENTS
MC Press Online