Create ICS file based on Calendar Component?

  • 1
  • Question
  • Updated 7 months ago
  • Doesn't Need an Answer
Is there a way to generate a ICS file based on a calendar event?
Photo of Tyler Neal

Tyler Neal

  • 760 Points 500 badge 2x thumb

Posted 2 years ago

  • 1
Photo of Tyler Neal

Tyler Neal

  • 760 Points 500 badge 2x thumb
Figured it out :) . Ended up using a snippet that runs ics.js ( https://github.com/nwcell/ics.js/ ) to create and download the file.
Photo of Rich Slack

Rich Slack

  • 4,134 Points 4k badge 2x thumb
Cool idea, can you share your skuid specific code Tyler?
Photo of Bill McCullough

Bill McCullough, Champion

  • 12,426 Points 10k badge 2x thumb
Rich,

Here is a sample page that uses the referenced JavaScript library.  I added the ics.js library as an inline script.  You would probably be better off to create a static resource from the ics.js file and reference it on your page.

Thanks,

Bill

<skuidpage unsavedchangeswarning="yes" personalizationmode="server" useviewportmeta="true" showsidebar="true" showheader="true" tabtooverride="Event">
    <models>
        <model id="Event" limit="1" query="true" createrowifnonefound="false" datasource="salesforce" sobject="Event">
            <fields>
                <field id="Subject"/>
                <field id="CreatedDate"/>
                <field id="ActivityDate"/>
                <field id="ActivityDateTime"/>
                <field id="StartDateTime"/>
                <field id="EndDateTime"/>
                <field id="Description"/>
                <field id="Location"/>
                <field id="Id"/>
                <field id="IsAllDayEvent"/>
                <field id="DurationInMinutes"/>
                <field id="ShowAs"/>
                <field id="Type"/>
                <field id="EventSubtype"/>
                <field id="OwnerId"/>
                <field id="Owner.Name"/>
                <field id="Owner.Email"/>
            </fields>
            <conditions>
                <condition type="param" enclosevalueinquotes="true" operator="=" field="Id" value="id"/>
            </conditions>
            <actions/>
        </model>
        <model id="CurrentUser" limit="20" query="true" createrowifnonefound="false" datasource="salesforce" sobject="User">
            <fields/>
            <conditions/>
            <actions/>
        </model>
    </models>
    <components>
        <pagetitle model="Event" uniqueid="sk-2QdF-208">
            <maintitle>
                <template>{{Subject}}</template>
            </maintitle>
            <subtitle>
                <template>{{Model.label}}</template>
            </subtitle>
            <actions>
                <action type="multi" label="Save iCal" uniqueid="sk-2TjU-317" icon="sk-icon-calendar">
                    <actions>
                        <action type="custom" datasource="salesforce" actionname="chatterPost" snippet="saveIcsJs"/>
                    </actions>
                </action>
                <action type="savecancel" window="self" uniqueid="sk-2QdF-206"/>
            </actions>
        </pagetitle>
        <basicfieldeditor showsavecancel="false" showheader="true" model="Event" mode="read" uniqueid="sk-2QdF-224">
            <columns>
                <column width="50%">
                    <sections>
                        <section title="Basics" collapsible="no">
                            <fields>
                                <field id="Subject" uniqueid="sk-2QdF-216"/>
                                <field uniqueid="sk-2Sog-595" id="Location"/>
                                <field uniqueid="sk-2Sog-579" id="Description"/>
                            </fields>
                        </section>
                    </sections>
                </column>
                <column width="50%">
                    <sections>
                        <section title="System Info" collapsible="no">
                            <fields>
                                <field uniqueid="sk-2QdF-542" id="StartDateTime"/>
                                <field uniqueid="sk-2QdF-543" id="EndDateTime"/>
                            </fields>
                        </section>
                    </sections>
                </column>
            </columns>
        </basicfieldeditor>
    </components>
    <resources>
        <labels/>
        <css/>
        <javascript>
            <jsitem location="inline" name="icsjs" cachelocation="false" url="">/*! ics.js Wed Aug 20 2014 17:23:02 */
                var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&amp;&amp;/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&amp;&amp;i)&amp;&amp;e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&amp;&amp;navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&amp;&amp;self||typeof window!=="undefined"&amp;&amp;window||this.content);if(typeof module!=="undefined"&amp;&amp;module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&amp;&amp;define!==null&amp;&amp;define.amd!==null){define("FileSaver.js",function(){return saveAs})}
                
                var ics=function(e,t){"use strict";{if(!(navigator.userAgent.indexOf("MSIE")&gt;-1&amp;&amp;-1==navigator.userAgent.indexOf("MSIE 10"))){void 0===e&amp;&amp;(e="default"),void 0===t&amp;&amp;(t="Calendar");var r=-1!==navigator.appVersion.indexOf("Win")?"\r\n":"\n",n=[],i=["BEGIN:VCALENDAR","PRODID:"+t,"VERSION:2.0"].join(r),o=r+"END:VCALENDAR",a=["SU","MO","TU","WE","TH","FR","SA"];return{events:function(){return n},calendar:function(){return i+r+n.join(r)+o},addEvent:function(t,i,o,l,u,s){if(void 0===t||void 0===i||void 0===o||void 0===l||void 0===u)return!1;if(s&amp;&amp;!s.rrule){if("YEARLY"!==s.freq&amp;&amp;"MONTHLY"!==s.freq&amp;&amp;"WEEKLY"!==s.freq&amp;&amp;"DAILY"!==s.freq)throw"Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";if(s.until&amp;&amp;isNaN(Date.parse(s.until)))throw"Recurrence rrule 'until' must be a valid date string";if(s.interval&amp;&amp;isNaN(parseInt(s.interval)))throw"Recurrence rrule 'interval' must be an integer";if(s.count&amp;&amp;isNaN(parseInt(s.count)))throw"Recurrence rrule 'count' must be an integer";if(void 0!==s.byday){if("[object Array]"!==Object.prototype.toString.call(s.byday))throw"Recurrence rrule 'byday' must be an array";if(s.byday.length&gt;7)throw"Recurrence rrule 'byday' array must not be longer than the 7 days in a week";s.byday=s.byday.filter(function(e,t){return s.byday.indexOf(e)==t});for(var c in s.byday)if(a.indexOf(s.byday[c])&lt;0)throw"Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'"}}var g=new Date(l),d=new Date(u),f=new Date,S=("0000"+g.getFullYear().toString()).slice(-4),E=("00"+(g.getMonth()+1).toString()).slice(-2),v=("00"+g.getDate().toString()).slice(-2),y=("00"+g.getHours().toString()).slice(-2),A=("00"+g.getMinutes().toString()).slice(-2),T=("00"+g.getSeconds().toString()).slice(-2),b=("0000"+d.getFullYear().toString()).slice(-4),D=("00"+(d.getMonth()+1).toString()).slice(-2),N=("00"+d.getDate().toString()).slice(-2),h=("00"+d.getHours().toString()).slice(-2),I=("00"+d.getMinutes().toString()).slice(-2),R=("00"+d.getMinutes().toString()).slice(-2),M=("0000"+f.getFullYear().toString()).slice(-4),w=("00"+(f.getMonth()+1).toString()).slice(-2),L=("00"+f.getDate().toString()).slice(-2),O=("00"+f.getHours().toString()).slice(-2),p=("00"+f.getMinutes().toString()).slice(-2),Y=("00"+f.getMinutes().toString()).slice(-2),U="",V="";y+A+T+h+I+R!=0&amp;&amp;(U="T"+y+A+T,V="T"+h+I+R);var B,C=S+E+v+U,j=b+D+N+V,m=M+w+L+("T"+O+p+Y);if(s)if(s.rrule)B=s.rrule;else{if(B="rrule:FREQ="+s.freq,s.until){var x=new Date(Date.parse(s.until)).toISOString();B+=";UNTIL="+x.substring(0,x.length-13).replace(/[-]/g,"")+"000000Z"}s.interval&amp;&amp;(B+=";INTERVAL="+s.interval),s.count&amp;&amp;(B+=";COUNT="+s.count),s.byday&amp;&amp;s.byday.length&gt;0&amp;&amp;(B+=";BYDAY="+s.byday.join(","))}(new Date).toISOString();var H=["BEGIN:VEVENT","UID:"+n.length+"@"+e,"CLASS:PUBLIC","DESCRIPTION:"+i,"DTSTAMP;VALUE=DATE-TIME:"+m,"DTSTART;VALUE=DATE-TIME:"+C,"DTEND;VALUE=DATE-TIME:"+j,"LOCATION:"+o,"SUMMARY;LANGUAGE=en-us:"+t,"TRANSP:TRANSPARENT","END:VEVENT"];return B&amp;&amp;H.splice(4,0,B),H=H.join(r),n.push(H),H},download:function(e,t){if(n.length&lt;1)return!1;t=void 0!==t?t:".ics",e=void 0!==e?e:"calendar";var a,l=i+r+n.join(r)+o;if(-1===navigator.userAgent.indexOf("MSIE 10"))a=new Blob([l]);else{var u=new BlobBuilder;u.append(l),a=u.getBlob("text/x-vCalendar;charset="+document.characterSet)}return saveAs(a,e+t),l},build:function(){return!(n.length&lt;1)&amp;&amp;i+r+n.join(r)+o}}}console.log("Unsupported Browser")}};</jsitem>
                <jsitem location="inlinesnippet" name="saveIcsJs" cachelocation="false">var params = arguments[0],
$ = skuid.$;

var row=params.row;

cal_single = ics();
cal_single.addEvent(row.Subject, row.Description, row.Location, row.StartDateTime, row.EndDateTime);
cal_single.download('event');</jsitem>
            </javascript>
            <actionsequences uniqueid="sk-2QdF-259"/>
        </resources>
        <styles>
            <styleitem type="background" bgtype="none"/>
        </styles>
    </skuidpage>