Pro neziskovou organizaci zabývající se péči o tělesně postižené, jsme vytvořili aplikaci, která umí plánovat práci lékařských asistentů u klientů doma. Jelikož každý klient má rozdílné požadavky na asistenta, v rozdílných časech, pro efektivní plánování se jevil nejvhodnější kalendářový pohled, který by šel filtrovat dle klientů, asistentů či dalších kritérií. Pro tento požadavek jsme využili Fullcalendar, který je nejrozšířenějším javascriptovým kalendářem na trhu.
Jak se dá propojit Fullcalendar se Salesforce ukážeme v následujících odstavcích.
- VisualForce Page
Prvním krokem je vytvoření VisualForce Page, která bude obsahovat FullCalendar a volání metod v Controlleru, který budeme tvořit posléze. Pro to, aby FullCalendar správně fungoval, musíme dotáhnout jeho knihovny, jquery a moment.js. Je lepší tyto zdroje mít uložené jako statické zdroje v Salesforce, ale pro ukázku využijeme CDN umístěni, viz níže:
1 2 3 4 5 6 7 |
<apex:page controller="CalendarController" action="{!pageLoad}"> <link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.css" rel="stylesheet" /> <script src="//code.jquery.com/jquery-3.2.1.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/locale/cs.js"></script> |
Následně přidáme nastavení samotného Fullcalendar. Jednotlivá nastavení můžete nalézt v dokumentaci, podstatné je umístění kalendáře na stránce do místa s id #calendar a pak ještě apex:repeat, který zobrazí seznam událostí z Controlleru a jeho proměnné ‚events‘.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<script> $(document).ready(function() { //Volání fullCallendar methody, která umístí Fullcalendar v místě ID '#calendar' $('#calendar').fullCalendar({ header: { left: 'prev,next today', center: 'title', right: 'month,agendaWeek,agendaDay', lang: 'cs' }, editable: false, defaultView:'agendaWeek', scrollTime: '08:00:00', minTime: '08:00:00', height: 550, events: [ //APEX Repeat který dotáhne pole eventů <apex:repeat value="{!events}" var="e"> { title: "{!e.title}", start: '{!e.startString}', end: '{!e.endString}', url: '{!e.url}', allDay: {!e.allDay}, className: '{!e.className}' }, </apex:repeat> ] }); }); </script> |
Nakonec přidáme ještě pole pro filtry dle Klienta a Asistenta, která jsou napojená na temp objekt v Salesforcu a slouží pro dohledání seznamu hodnotu. Při změně hodnoty je pak volána funkce changeFilter(), která následně volá funkci v Controlleru ‚changeFilterInController‘. Všimněte si i divu s id=’calendar‘. To je místo, kam se bude generovat náš kalendář.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<apex:sectionHeader title="Kalendář prací" /> <apex:outputPanel id="calPanel"> <apex:form > <apex:pageBlock > <div id="cal-options" style="margin-bottom:10px"> <!--Tmp pole pro výběr klienta a asistenta. Pak volá apex action níže--> Klient: <apex:inputField value="{!tmpJob.Klient__c}" onchange="changeFilter()" /> Asistent: <apex:inputField value="{!tmpJob.Asistent__c}" onchange="changeFilter()" /> </div> <div id="calendar"></div> <apex:actionFunction name="changeFilter" action="{!changeFilterInController}" /> </apex:pageBlock> </apex:form> </apex:outputPanel> |
2. Controller
FullCalendar komunikuje a získává data z Controlleru, který je popsaný níže. Jeho základní prvky:
- events – tady se natahají všechny události odpovídající filtru
- tmpJob – tmp objekt pro vykreslení Lookup polí a předávání hodnot mezi VisualForce a Controllerem
- metoda pageLoad – zpracuje podmínku a načte všechny události z databáze
- metoda changeFilterInController – volá se při změně jmen čili volbě jiného filtru. Překresluje FullCalendar dle nových parametrů
- class calEvent – pomocný objekt pro uložení dat události
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
public class CalendarController { //Liste eventů, který se posílá kalendáři public list<calEvent> events {get;set;} //TMP objekt pro vytvoření Lkp polí public JobCalendar__c tmpJob {get;set;} //Datum pro FullCalendar musí být v určitém formátu String dtFormat = 'yyyy-MM-dd HH:mm:ss'; public CalendarController() { tmpJob=new JobCalendar__c(); } public PageReference pageLoad() { events = new list<calEvent>(); List<Job__c> jobs; String query='select Id, Name, date_from__c, date_to__c, Status__c, Client__r.FullName__c, Asistent__r.FullName__c from Job__c '; String whereStr=''; String clientId=tmpJob.Klient__c; String asistentId=tmpJob.Asistent__c; if (tmpJob.Klient__c!=null && tmpJob.Asistent__c!=null){ //máme naplněné oba filtry whereStr='WHERE Client__c = :clientId AND Asistent__c = :asistentId'; }else if(tmpJob.Klient__c==null && tmpJob.Asistent__c!=null){ // je tam jen Asistent whereStr='WHERE Asistent__c = :asistentId'; }else if(tmpJob.Klient__c!=null && tmpJob.Asistent__c==null){ //je tam jen Klient whereStr='WHERE Client__c = :clientId'; } //Vytáhneme seznam prací z databáze jobs = Database.query(query +whereStr); //Tvoříme z nich eventy pro kalendář for(Job__c job : jobs){ DateTime startDT = job.date_from__c; DateTime endDT = job.date_to__c; calEvent jobEvent = new calEvent(); String asistenant=''; if (job.Asistent__r.FullName__c!=null){ asistenant=' - asistent: ' +job.Asistent__r.FullName__c; } jobEvent.title = job.Client__r.FullName__c +' - ' + job.Name + asistenant; jobEvent.allDay = false; jobEvent.startString = startDT.format(dtFormat); jobEvent.endString = endDT.format(dtFormat); jobEvent.url = '/' + job.Id ; //Přidáme barvy dle stavu if (job.Status__c=='Provedeno') { jobEvent.className = 'event-done'; }else{ jobEvent.className = 'event-inprogress'; } if (job.Asistent__c==null) { jobEvent.className = 'event-no-assistent'; } events.add(jobEvent); } return null; } //Změna filtru on obrazovce public PageReference changeFilterInController() { pageload(); return null; } //Pomocná Class pro data eventu public class calEvent{ public String title {get;set;} public Boolean allDay {get;set;} public String startString {get;set;} public String endString {get;set;} public String url {get;set;} public String className {get;set;} } } |
One Comment