├── README.md ├── _site ├── Accessing-Data-using-SOQL-and-DML.html ├── Batch-and-Schedule.html ├── Creating-Triggers.html ├── Creating-a-Controller-Extension.html ├── Creating-a-Developer-Edition-Account.html ├── Creating-a-Visualforce-Page.html ├── Creating-an-Apex-Class.html ├── Creating-the-Application.html ├── Creating-the-Data-Model.html ├── Gemfile ├── Gemfile.lock ├── Module2.html ├── Prerequisites.html ├── Testing.html ├── Using-JavaScript-in-Visualforce-Pages.html ├── Using-the-Salesforce1-Platform-APIs.html ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── js │ │ ├── bootstrap.js │ │ └── bootstrap.min.js ├── css │ ├── main.css │ ├── styles.css │ └── syntax.css ├── images │ ├── api.jpg │ ├── app.jpg │ ├── conference-app.jpg │ ├── connected-app.jpg │ ├── consumer-key.jpg │ ├── custom-object.jpg │ ├── devconsole.jpg │ ├── doublebooking.jpg │ ├── hotel-tab.jpg │ ├── hotelmap.jpg │ ├── logo.png │ ├── lookup.jpg │ ├── marriott.jpg │ ├── new-field.jpg │ ├── queryeditor.jpg │ ├── salesforce1.png │ ├── schema.jpg │ ├── search-schema.jpg │ ├── session-detail.jpg │ ├── session-field.jpg │ ├── session-layout.jpg │ ├── session-object.jpg │ ├── setup.jpg │ ├── speaker-layout.jpg │ ├── speaker-lookup.jpg │ ├── speaker-lookup.png │ ├── sysadmin.jpg │ ├── test1.jpg │ ├── test2.jpg │ └── upload.jpg ├── index.html ├── jekyll │ └── update │ │ └── 2014 │ │ └── 06 │ │ └── 07 │ │ └── welcome-to-jekyll.html ├── lib │ └── jquery.js └── signup.html ├── client ├── css │ ├── ratchet.css │ └── styles.css ├── fonts │ ├── ratchicons.eot │ ├── ratchicons.svg │ ├── ratchicons.ttf │ └── ratchicons.woff ├── index.html ├── js │ └── app.js ├── lib │ ├── forcetk.js │ └── jquery.js └── oauthcallback.html ├── package.json └── server.js /README.md: -------------------------------------------------------------------------------- 1 | # Salesforce Developer Workshop 2 | 3 | Supporting files for the workshop. 4 | 5 | Step-by-step workshop instructions are available here: 6 | 7 | [http://ccoenraets.github.io/salesforce-developer-workshop/](http://ccoenraets.github.io/salesforce-developer-workshop/) 8 | -------------------------------------------------------------------------------- /_site/Accessing-Data-using-SOQL-and-DML.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 5: Accessing Data using SOQL and DML

66 |
67 |

SOQL is the Salesforce Object Query Language. It is the language you use to retrieve data in Salesforce, and it's similar to SQL. 68 | You use the Salesforce Data Manipulation Language (DML) to insert, update and delete data. In this module, you use the Developer Console to familiarize yourself with SOQL 69 | and DML. In the next modules, you'll use SOQL and DML statements in Apex classes and triggers.

70 | 71 |

Step 1: Execute SOQL statements

72 | 73 |
    74 |
  1. In the Developer Console, click the Query Editor tab at the bottom of the window

    75 | 76 |

  2. 77 |
  3. Enter the following SOQL statement and click the Execute button to retrieve conference sessions:

    78 |
    SELECT Id, Name, Session_Date__c, Level__c FROM Session__c
     79 | 
  4. 80 |
  5. Execute the following statement to retrieve the beginner sessions (assuming you created any):

    81 |
    SELECT Id, Name, Session_Date__c, Level__c FROM Session__c
     82 |     WHERE Level__c = 'Beginner'
     83 | 
  6. 84 |
  7. Execute the following statement to retrieve a list of speakers ordered by first name and last name:

    85 |
    SELECT Id, First_Name__c, Last_Name__c, Email__c FROM Speaker__c
     86 |     ORDER BY First_Name__c, Last_Name__c
     87 | 
  8. 88 |
  9. Execute the following statement to to retrieve the conference schedule with session and speaker information:

    89 |
    SELECT Session__r.Name,
     90 |        Session__r.Session_Date__c,
     91 |        Speaker__r.First_Name__c,
     92 |        Speaker__r.Last_Name__c
     93 |     FROM Session_Speaker__c
     94 |     ORDER BY Session__r.Session_Date__c, Session__r.Name
     95 | 
    96 |

    Because this is equivalent to a right join, this query will only return sessions with a speaker assignment.

  10. 97 |
98 | 99 |

Step 2: Execute DML Statements

100 | 101 |
    102 |
  1. In the Developer Console, click Debug > Open Execute Anonymous Window and execute the following statements to create a session:

    103 |
    Session__c session=new Session__c(Name='Advanced Apex', Level__c='Advanced');
    104 | insert session;
    105 | 
    106 |

    You can execute a SOQL statement in the Query Editor as described above to make sure the session was created.

  2. 107 |
  3. Execute the following statements to update a session:

    108 |
    Session__c session = [SELECT Id FROM Session__c WHERE NAME='Advanced Apex'];
    109 | session.Level__c = 'Intermediate';
    110 | update session;
    111 | 
  4. 112 |
113 | 114 |

Additional Resources

115 | 116 | 119 | 120 |
121 |
122 | Previous 123 | Next 124 |
125 | 126 |

127 | 128 |
129 | 130 |
131 | 132 | 151 | 152 | 153 | 154 | 155 |
156 | 157 |
158 | 159 |
160 | 161 |
162 | 165 |
166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /_site/Batch-and-Schedule.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 12: Batch and Schedule

66 |
67 |

In this module, you create and execute a batch process to send reminder emails to the conference speakers.

68 | 69 |

Step 1: Create the Batch Class

70 | 71 |
    72 |
  1. In the Developer Console, select File > New > Apex Class, specify SendReminderEmail as the class name and click OK

  2. 73 |
  3. Make the class global, implement the Batchable interface, and define the three methods of the interface:

    74 |
    global class SendReminderEmail implements Database.Batchable<sObject> {
     75 | 
     76 |     global Database.QueryLocator start(Database.BatchableContext bc) {
     77 | 
     78 |     }
     79 | 
     80 |     global void execute(Database.BatchableContext bc, List<Speaker__c> scope) {
     81 | 
     82 |     }
     83 | 
     84 |     global void finish(Database.BatchableContext bc) {
     85 | 
     86 |     }
     87 | 
     88 | }
     89 | 
  4. 90 |
  5. Declare three instance variables to store the query, the email subject, and the email body:

    91 |
    global String query;
     92 | global String subject;
     93 | global String body;
     94 | 
  6. 95 |
  7. Define a constructor implemented as follows:

    96 |
    global SendReminderEmail(String query, String subject, String body) {
     97 |     this.query = query;
     98 |     this.subject = subject;
     99 |     this.body = body;
    100 | }
    101 | 
  8. 102 |
  9. Implement the start() method as follows:

    103 |
    global Database.QueryLocator start(Database.BatchableContext bc) {
    104 |     return Database.getQueryLocator(query);
    105 | }
    106 | 
  10. 107 |
  11. Implement the execute() method as follows:

    108 |
    global void execute(Database.BatchableContext bc, List<Speaker__c> scope) {
    109 |     for (Speaker__c speaker : scope) {
    110 |         EmailManager.sendMail(speaker.Email__c, this.subject, this.body);
    111 |     }
    112 | }
    113 | 
  12. 114 |
  13. Save the file.

  14. 115 |
116 | 117 |

Step 2: Run the Batch

118 | 119 |
    120 |
  1. Make sure you have assigned your own email address to one of the speakers

  2. 121 |
  3. In the Developer Console, click Debug > Open Execute Anonymous Window

  4. 122 |
  5. Type the following Apex code:

    123 |
    String q = 'SELECT First_Name__c, Last_Name__c, Email__c FROM Speaker__c WHERE Email__c != null';
    124 | SendReminderEmail batch = new SendReminderEmail(q, 'Final Reminder', 'The conference starts next Monday');
    125 | Database.executeBatch(batch);
    126 | 
  6. 127 |
  7. Click Execute

  8. 128 |
  9. Check your email

  10. 129 |
130 | 131 |
132 |
133 | Previous 134 |
135 | 136 |

137 | 138 |
139 | 140 |
141 | 142 | 161 | 162 | 163 | 164 | 165 |
166 | 167 |
168 | 169 |
170 | 171 |
172 | 175 |
176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /_site/Creating-Triggers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 6: Creating Triggers

66 |
67 |

In this module, you create a trigger that sends confirmation emails to speakers when they are assigned to a session. 68 | You create another trigger that rejects double bookings of speakers.

69 | 70 |

Step 1: Create a Trigger that Sends Confirmation Emails

71 | 72 |

In this step, you create a trigger that sends confirmation emails to speakers when they are assigned to a session.

73 | 74 |
    75 |
  1. In the Developer Console, click File > New > Apex Trigger

  2. 76 |
  3. Specify SendConfirmationEmail as the trigger name, Session_Speaker__c as the sObject, and click Submit

  4. 77 |
  5. Implement the trigger as follows:

    78 |
    trigger SendConfirmationEmail on Session_Speaker__c (after insert) {
     79 | 
     80 |     for(Session_Speaker__c newItem : trigger.new) {
     81 | 
     82 |         // Retrieve session name and time + speaker name and email address
     83 |         Session_Speaker__c sessionSpeaker =
     84 |             [SELECT Session__r.Name,
     85 |                     Session__r.Session_Date__c,
     86 |                     Speaker__r.First_Name__c,
     87 |                     Speaker__r.Last_Name__c,
     88 |                  Speaker__r.Email__c
     89 |              FROM Session_Speaker__c WHERE Id=:newItem.Id];
     90 | 
     91 |         // Send confirmation email if we know the speaker's email address
     92 |         if (sessionSpeaker.Speaker__r.Email__c != null) {
     93 |             String address = sessionSpeaker.Speaker__r.Email__c;
     94 |             String subject = 'Speaker Confirmation';
     95 |             String message = 'Dear ' + sessionSpeaker.Speaker__r.First_Name__c +
     96 |                 ',\nYour session "' + sessionSpeaker.Session__r.Name + '" on ' +
     97 |                 sessionSpeaker.Session__r.Session_Date__c + ' is confirmed.\n\n' +
     98 |                 'Thanks for speaking at the conference!';
     99 |             EmailManager.sendMail(address, subject, message);
    100 |         }
    101 |     }
    102 | 
    103 | }
    104 | 
    105 |
    106 |

    In a real-life application, hardcoding the email message is not a recommended approach. Consider using email templates instead.

    107 |
  6. 108 |
  7. Save the file. The trigger takes effect as soon as you save it.

  8. 109 |
  9. Test the trigger

    110 | 111 |
      112 |
    • Create a speaker that has your own email address
    • 113 |
    • Assign that speaker to a session, and check your email: you should receive a speaker confirmation email
    • 114 |
    115 | 116 |
    117 |

    Sending a confirmation email when a speaker is assigned to a session (in other words, when a Session_Speaker__c record is created) can be accomplished without writing code by defining a workflow rule. The programmatic approach used in this workshop allows you to satisfy additional requirements. For example, sending a confirmation email "on demand", independently of a record being created or updated.

    118 |
  10. 119 |
120 | 121 |

Step 2: Create a Trigger that Rejects Double Bookings

122 | 123 |
    124 |
  1. In the Developer Console, click File > New > Apex Trigger

  2. 125 |
  3. Specify RejectDoubleBooking as the trigger name, Session_Speaker__c as the sObject, and click Submit

  4. 126 |
  5. Implement the trigger as follows:

    127 |
    trigger RejectDoubleBooking on Session_Speaker__c (before insert, before update) {
    128 | 
    129 |     for(Session_Speaker__c sessionSpeaker : trigger.new) {
    130 | 
    131 |         Session__c session = [SELECT Id, Session_Date__c FROM Session__c
    132 |                                 WHERE Id=:sessionSpeaker.Session__c];
    133 | 
    134 |         List<Session_Speaker__c> conflicts =
    135 |             [SELECT Id FROM Session_Speaker__c
    136 |                 WHERE Speaker__c = :sessionSpeaker.Speaker__c
    137 |                 AND Session__r.Session_Date__c = :session.Session_Date__c];
    138 | 
    139 |         if(!conflicts.isEmpty()){
    140 |             sessionSpeaker.addError('The speaker is already booked at that time');
    141 |         }
    142 | 
    143 |     }
    144 | 
    145 | }
    146 | 
  6. 147 |
  7. Save the file

  8. 148 |
  9. Test the trigger:

    149 | 150 |
      151 |
    • Assign a speaker to a session scheduled at a time the speaker is available and make sure it still works
    • 152 |
    • Assign a speaker to a session scheduled at the same time as another session the speaker is already assigned to: you should see the error message
    • 153 |
    154 | 155 |

    156 | 157 |
    158 |

    RejectDoubleBooking is not sufficient to entirely prevent the double booking of speakers. For example, the user could change the date and time of a session in a way that creates a double booking for a speaker assigned to that session. You could create an additional trigger to take care of that situation.

    159 |
  10. 160 |
161 | 162 |
163 |
164 | Previous 165 | Next 166 |
167 | 168 |

169 | 170 |
171 | 172 |
173 | 174 | 193 | 194 | 195 | 196 | 197 |
198 | 199 |
200 | 201 |
202 | 203 |
204 | 207 |
208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /_site/Creating-a-Controller-Extension.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 8: Creating a Controller Extension

66 |
67 |

In this module, you enhance the Visualforce page you built in module 7: you create a controller extension that allows users to upload speaker pictures.

68 | 69 |

70 | 71 |

Step 1: Create a Controller extension

72 | 73 |

In this step, you experiment with the mechanics of a controller extension. You create a simple controller extension that exposes an increment() method and a counter property. When you click the Increment button in the SpeakerForm page, the extension's increment() method increments the counter property whose new value is automatically displayed in the page. In the next step, you make SpeakerControllerExtension a lot more useful by adding code to support the upload of speaker pictures.

74 | 75 |
    76 |
  1. In the Developer Console, select File > New > Apex Class, specify SpeakerControllerExtension as the class name and click OK

  2. 77 |
  3. Implement the class as follows:

    78 |
    public class SpeakerControllerExtension {
     79 | 
     80 |     public Integer counter {get; set;}
     81 | 
     82 |     private final Speaker__c speaker;
     83 |     private ApexPages.StandardController stdController;
     84 | 
     85 |     public SpeakerControllerExtension(ApexPages.StandardController stdController) {
     86 |         this.speaker = (Speaker__c)stdController.getRecord();
     87 |         this.stdController = stdController;
     88 |         counter = 0;
     89 |     }
     90 | 
     91 |     public void increment() {
     92 |         counter++;
     93 |     }
     94 | 
     95 | }
     96 | 
  4. 97 |
  5. Save the file

  6. 98 |
  7. In the Developer Console, open the SpeakerForm page, and add the controller extension to the page definition:

    99 |
    <apex:page standardController="Speaker__c" extensions="SpeakerControllerExtension">
    100 | 
  8. 101 |
  9. Add an Increment button (right after the Save button):

    102 |
    <apex:commandButton action="{!increment}" value="Increment"/>
    103 | 
  10. 104 |
  11. Display the counter (right after </apex:pageBlock>):

    105 |
    {!counter}
    106 | 
  12. 107 |
  13. Save the file

  14. 108 |
  15. Test the application

    109 | 110 |
      111 |
    • Click the Speakers tab, select a speaker, and click Edit
    • 112 |
    • Click the Increment button several times and watch the counter value displayed at the bottom of the page
    • 113 |
  16. 114 |
115 | 116 |

Step 2: Extend the Data Model

117 | 118 |

In this step, you add two fields to the Speaker object: Picture_Path to store the location of the picture on the server, and Picture, a Formula field used to display the image in the Visualforce page.

119 | 120 |
    121 |
  1. In Setup, select Build > Create > Objects, and click the Speaker link

  2. 122 |
  3. In the Custom Fields & Relationships section, click New, and create a Picture_Path field defined as follows:

    123 | 124 |
      125 |
    • Data Type: Text
    • 126 |
    • Field Label: Picture Path
    • 127 |
    • Length: 255
    • 128 |
    • Field Name: Picture_Path
    • 129 |
    130 | 131 |

    Click Next, Next, Save & New

  4. 132 |
  5. Create a Picture field defined as follows:

    133 | 134 |
      135 |
    • Data Type: Formula
    • 136 |
    • Field Label: Picture
    • 137 |
    • Field Name: Picture
    • 138 |
    • Formula Return Type: Text
    • 139 |
    • Formula: IMAGE(Picture_Path__c, '')
    • 140 |
    141 | 142 |

    Click Next, Next, Save

  6. 143 |
144 | 145 |

Step 3: Add Image Upload Support

146 | 147 |
    148 |
  1. In the Developer Console, open SpeakerControllerExtension

  2. 149 |
  3. Remove the counter variable declaration, the counter variable initialization in the class constructor, and the increment() method definition

  4. 150 |
  5. Declare the following variables (right before the speaker variable declaration):

    151 |
    public blob picture { get; set; }
    152 | public String errorMessage { get; set; }
    153 | 
  6. 154 |
  7. Declare a save() method implemented as follows to override the standard controller's default behavior (right after the constructor method):

    155 |
    public PageReference save() {
    156 |     errorMessage = '';
    157 |     try {
    158 |         upsert speaker;
    159 |         if (picture != null) {
    160 |             Attachment attachment = new Attachment();
    161 |             attachment.body = picture;
    162 |             attachment.name = 'speaker_' + speaker.id + '.jpg';
    163 |             attachment.parentid = speaker.id;
    164 |             attachment.ContentType = 'application/jpg';
    165 |             insert attachment;
    166 |             speaker.Picture_Path__c = '/servlet/servlet.FileDownload?file='
    167 |                                       + attachment.id;
    168 |             update speaker;
    169 |         }
    170 |         return new ApexPages.StandardController(speaker).view();
    171 |     } catch(System.Exception ex) {
    172 |         errorMessage = ex.getMessage();
    173 |         return null;
    174 |     }
    175 | }
    176 | 
  8. 177 |
  9. Save the file

  10. 178 |
  11. In the Developer Console, open the SpeakerForm page

  12. 179 |
  13. Remove the Increment button

  14. 180 |
  15. Add an inputFile (right after the Email inputField):

    181 |
    <apex:inputFile value="{!picture}" accept="image/*" />
    182 | 
  16. 183 |
  17. Instead of the counter, display the potential errorMessage right after </apex:pageBlock>

    184 |
    {!errorMessage}
    185 | 
  18. 186 |
  19. Save the file

  20. 187 |
188 | 189 |

Step 4: Test the Application

190 | 191 |
    192 |
  1. Click the Speakers tab

  2. 193 |
  3. Click New to add a speaker

  4. 194 |
  5. Enter the speaker first name, last name and email

  6. 195 |
  7. Click the Choose File button and select a jpg file on your file system

  8. 196 |
  9. Click the Save button: you should see the image on the speaker's details page

  10. 197 |
198 | 199 |
200 |
201 | Previous 202 | Next 203 |
204 | 205 |

206 | 207 |
208 | 209 |
210 | 211 | 230 | 231 | 232 | 233 | 234 |
235 | 236 |
237 | 238 |
239 | 240 |
241 | 244 |
245 | 246 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /_site/Creating-a-Developer-Edition-Account.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 1: Creating a Developer Edition Account

66 |
67 |

In this module, you create a Developer Edition Account that provides you with a full-featured but isolated Salesforce environment to perform the exercises in this workshop.

68 | 69 |
70 |

If you already signed up for a Developer Edition account, you can skip the instructions below and go directly to Module 2.

71 |
72 | 73 |

Steps

74 | 75 |
    76 |
  1. Open a browser and access the following URL: http://developer.salesforce.com/join

  2. 77 |
  3. Fill in the signup form:

    78 | 79 |
      80 |
    • Enter your First Name and Last Name
    • 81 |
    • For Email, enter an email address you have access to at this time (you will need to open an activation email)
    • 82 |
    • For Username, specify a unique user name in the form of an email address. for example: firsname.lastname@s1workshop.com (It doesn't have to be an existing email address: the Username is not used to send you emails)
    • 83 |
    • Check the Master Subscription Agreement checkbox and click the Sign Me Up button
    • 84 |
  4. 85 |
  5. Check your email. You will receive an activation email for your Developer Edition Account.

  6. 86 |
  7. Click the link in the activation email. Enter your new password information, and click Save.

  8. 87 |
88 | 89 |
90 |
91 | Previous 92 | Next 93 |
94 | 95 |

96 | 97 |
98 | 99 |
100 | 101 | 120 | 121 | 122 | 123 | 124 |
125 | 126 |
127 | 128 |
129 | 130 |
131 | 134 |
135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /_site/Creating-a-Visualforce-Page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 7: Creating a Visualforce Page

66 |
67 |

In this module, you create a Visualforce page to provide a custom user interface for creating and editing speakers.

68 | 69 |

Step 1: Create the SpeakerForm Visualforce Page

70 | 71 |
    72 |
  1. In the Developer Console, select File > New > Visualforce Page, specify SpeakerForm as the page name and click OK

  2. 73 |
  3. Implement SpeakerForm as follows:

    74 |
    <apex:page standardController="Speaker__c">
     75 | <apex:form >
     76 |     <apex:pageBlock title="Edit Speaker">
     77 |         <apex:pageBlockSection columns="1">
     78 |             <apex:inputField value="{!Speaker__c.First_Name__c}"/>
     79 |             <apex:inputField value="{!Speaker__c.Last_Name__c}"/>
     80 |             <apex:inputField value="{!Speaker__c.Email__c}"/>
     81 |         </apex:pageBlockSection>
     82 |         <apex:pageBlockButtons >
     83 |             <apex:commandButton action="{!save}" value="Save"/>
     84 |         </apex:pageBlockButtons>
     85 |     </apex:pageBlock>
     86 | </apex:form>
     87 | </apex:page>
     88 | 
  4. 89 |
  5. Save the file

  6. 90 |
  7. Test the Visualforce page. There are several ways you can test your Visualforce page. For example, you can:

    91 | 92 |
      93 |
    • Click the Preview button in the file editor for SpeakerForm in the developer console
    • 94 |
    • Directly access the Visualforce page by appending /apex/SpeakerForm to your instance's domain name in the browser. For example, access: https://na17.salesforce.com/apex/SpeakerForm (make sure you use your own Salesforce domain name)
    • 95 |
  8. 96 |
97 | 98 |

Step 2: Set SpeakerForm as the Default Form

99 | 100 |

In this step, you set the SpeakerForm page as the default form for creating and editing speakers:

101 | 102 |
    103 |
  1. In Setup, select Build > Create > Objects and click the Speaker link

  2. 104 |
  3. Scroll down to the Buttons, Links, and Actions section, and click Edit next to New

  4. 105 |
  5. Check Override With Visualforce Page, and select SpeakerForm

  6. 106 |
  7. Click Save

  8. 107 |
  9. In the Buttons, Links, and Actions section, click Edit next to Edit

  10. 108 |
  11. Check Override With Visualforce Page, and select SpeakerForm

  12. 109 |
  13. Click Save

  14. 110 |
111 | 112 |

Step 3: Test the Application

113 | 114 |
    115 |
  1. Click the Speakers Tab

  2. 116 |
  3. Select a speaker and click Edit: you are now editing the speaker information using your Visualforce page

  4. 117 |
  5. Modify some data, and click Save

  6. 118 |
119 | 120 |
121 |

At this stage, the Visualforce page doesn't provide any additional capability compared to the default speaker form. In 122 | the next module, you will enhance SpeakerForm to support the upload of the speaker picture.

123 |
124 | 125 |
126 |
127 | Previous 128 | Next 129 |
130 | 131 |

132 | 133 |
134 | 135 |
136 | 137 | 156 | 157 | 158 | 159 | 160 |
161 | 162 |
163 | 164 |
165 | 166 |
167 | 170 |
171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /_site/Creating-an-Apex-Class.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 4: Creating an Apex Class

66 |
67 |

In this module, you create an EmailManager class that encapsulates the logic to send confirmation emails to the conference speakers.

68 | 69 |

Step 1: Create the EmailManager class

70 | 71 |
    72 |
  1. In Salesforce, click your name in the upper right corner of the screen. In the dropdown menu, click Developer Console.

    73 | 74 |

  2. 75 |
  3. In the Developer Console, click File > New > Apex Class. Specify EmailManager as the class name and click OK

  4. 76 |
  5. Implement the class as follows:

    77 |
    public class EmailManager{
     78 | 
     79 |     public void sendMail(String address, String subject, String body) {
     80 |         Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
     81 |         String[] toAddresses = new String[] {address};
     82 |         mail.setToAddresses(toAddresses);
     83 |         mail.setSubject(subject);
     84 |         mail.setPlainTextBody(body);
     85 |         Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
     86 |     }
     87 | 
     88 | }
     89 | 
  6. 90 |
  7. Click File > Save to save the file

  8. 91 |
92 | 93 |

Step 2: Send an Email

94 | 95 |

In this module, you test the EmailManager class by sending an email from the developer console. Later in this workshop, you'll integrate the EmailManager class with other parts of the application to automate the process of sending confirmation emails.

96 | 97 |
    98 |
  1. In the Developer Console, click Debug > Open Execute Anonymous Window

  2. 99 |
  3. Type the following Apex code (provide your own email address):

    100 |
    String address = 'YOUR_EMAIL_ADDRESS';
    101 | String subject = 'Speaker Confirmation';
    102 | String body = 'Thank you for speaking at the conference.';
    103 | EmailManager em = new EmailManager();
    104 | em.sendMail(address, subject, body);
    105 | 
  4. 106 |
  5. Click the Execute button

  6. 107 |
  7. Check your email: you should have received the confirmation email

  8. 108 |
109 | 110 |

Step 3: Using a Static Method

111 | 112 |

Since EmailManager is a utility class that doesn't work with instance-specific variables, you can make the sendMail() method static:

113 | 114 |
    115 |
  1. In the Developer Console, open the EmailManager class

  2. 116 |
  3. To turn sendMail() into a static method, change its signature as follows (add the static keyword):

    117 |
    public static void sendMail(String address, String subject, String body) {
    118 | 
  4. 119 |
  5. Save the file

  6. 120 |
  7. Go back to the Execute Anonymous Window (Debug > Open Execute Anonymous Window)

  8. 121 |
  9. Modify the Apex code to invoke sendMail() statically:

    122 |
    String address = 'YOUR_EMAIL_ADDRESS';
    123 | String subject = 'Speaker Confirmation';
    124 | String body = 'Thank you for speaking at the conference.';
    125 | EmailManager.sendMail(address, subject, body);
    126 | 
  10. 127 |
  11. Click Execute and check your email

  12. 128 |
129 | 130 |
131 |
132 | Previous 133 | Next 134 |
135 | 136 |

137 | 138 |
139 | 140 |
141 | 142 | 161 | 162 | 163 | 164 | 165 |
166 | 167 |
168 | 169 |
170 | 171 |
172 | 175 |
176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /_site/Creating-the-Application.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 3: Creating the Application

66 |
67 |

In this module, you create Tabs to provide access to the Session and Speaker objects. You group these tabs together in an Application to make them easier to access, and you optimize Page Layouts to show relevant information in the Speaker and Session lists.

68 | 69 |

70 | 71 |

Step 1: Creating Tabs

72 | 73 |

To create the Sessions tab:

74 | 75 |
    76 |
  1. In Setup mode, select Build > Create > Tabs

  2. 77 |
  3. In the Custom Object Tabs section, click New

  4. 78 |
  5. Select Session as the Object, click the magnifier icon next to Tab Style and select the Books icon

  6. 79 |
  7. Click Next, Next

  8. 80 |
  9. Uncheck the Include Tab checkbox to ensure the Sessions tab doesn't appear in any of the existing applications, and click Save (In step 2, we will add the Sessions tab to a new application).

  10. 81 |
82 | 83 |

To create the Speakers tab:

84 | 85 |
    86 |
  1. In the Custom Object Tabs section, click New

  2. 87 |
  3. Select Speaker as the Object, click the magnifier icon next to Tab Style and select the Presenter icon

  4. 88 |
  5. Click Next, Next

  6. 89 |
  7. Uncheck the Include Tab checkbox to ensure the Speakers tab doesn't appear in any of the existing applications, and click Save

  8. 90 |
91 | 92 |

Step 2: Creating the App

93 | 94 |

A Salesforce App is a group of Tabs that makes it easy for users to access a set of related features.

95 | 96 |
    97 |
  1. In Setup mode, select Build > Create > Apps

  2. 98 |
  3. In the Apps section, click New

  4. 99 |
  5. Check Custom app and click Next

  6. 100 |
  7. Enter Conference for both the App Label and App Name, and click Next

  8. 101 |
  9. Accept the default App Logo and click Next

  10. 102 |
  11. Add the Sessions and Speakers tabs to the Selected Tabs and click Next

  12. 103 |
  13. Check the System Administrator profile and click Save

    104 | 105 |

  14. 106 |
  15. Select Conference in the App selector (upper right corner of the screen)

    107 | 108 |

    109 | 110 |
    111 |

    If the Conference App doesn't appear in the App Selector, you probably forgot to assign it to the System Administrator profile. In Setup, select Build > Create > App, click Edit next to Conference, check the System Administrator profile, and click Save.

    112 |
  16. 113 |
114 | 115 |

Step 3: Enter Sample Data

116 | 117 |
    118 |
  1. Click the Speakers Tab, click New, and add a few sample speakers

  2. 119 |
  3. Click the Sessions Tab, click New, and add a few sample sessions

  4. 120 |
  5. To assign speakers to a session:

    121 | 122 |
      123 |
    • In the details view for a session, click New Session Speaker
    • 124 |
    • Click the magnifier icon next to the Speaker field, select a speaker in the Speaker lookup dialog and click Save
    • 125 |
    126 | 127 |

    128 | 129 |

    130 | 131 |
    132 |

    Notice that the list of speakers in both the speaker lookup dialog and the session details page doesn't currently provide very informative data. We will fix this in the next steps.

    133 |
  6. 134 |
135 | 136 |

Step 4: Optimize the Session Page Layout

137 | 138 |

In this step, you optimize the Session details screen: to allow the user to easily identify the speakers for a session, you add the appropriate fields to the Speaker list.

139 | 140 |

141 | 142 |
    143 |
  1. In Setup mode, select Build > Create > Objects

  2. 144 |
  3. Click the Session link

  4. 145 |
  5. In the Page Layouts section, click Edit next to Session Layout

  6. 146 |
  7. In the Related Lists section, click the wrench icon (Related list properties)

  8. 147 |
  9. Add the following fields to the list of Selected Fields:

    148 | 149 |
      150 |
    • Speaker: Speaker Number
    • 151 |
    • Speaker: First Name
    • 152 |
    • Speaker: Last Name
    • 153 |
  10. 154 |
  11. Remove the following field from the list of Selected Fields:

    155 | 156 |
      157 |
    • Session Speaker: Session Speaker Name
    • 158 |
  12. 159 |
  13. Click OK

  14. 160 |
  15. Click Save (upper left corner)

  16. 161 |
162 | 163 |

Step 5: Optimize the Speaker Page Layout

164 | 165 |

In this step, you optimize the Speaker details screen: to allow the user to easily identify the sessions for a speaker, you add the appropriate fields to the Session list.

166 | 167 |

168 | 169 |
    170 |
  1. In Setup mode, select Build > Create > Objects

  2. 171 |
  3. Click the Speaker link

  4. 172 |
  5. In the Page Layouts section, click Edit next to Speaker Layout

  6. 173 |
  7. In the Related Lists section, click the wrench icon (Related list properties)

  8. 174 |
  9. Add the following fields to the list of Selected Fields:

    175 | 176 |
      177 |
    • Session: Session Name
    • 178 |
    • Session: Session Date
    • 179 |
  10. 180 |
  11. Remove the following field from the list of Selected Fields:

    181 | 182 |
      183 |
    • Session Speaker: Session Speaker Name
    • 184 |
  12. 185 |
  13. Click OK

  14. 186 |
  15. Click Save (upper left corner)

  16. 187 |
188 | 189 |

Step 6: Optimize the Speaker Lookup

190 | 191 |

In this step, you optimize the Speaker lookup dialog to allow the user to easily identify speakers.

192 | 193 |

194 | 195 |
    196 |
  1. In Setup mode, select Build > Create > Objects

  2. 197 |
  3. Click the Speaker link

  4. 198 |
  5. Scroll down to the Search Layouts section, and click Edit next to Lookup Dialogs

  6. 199 |
  7. Add First Name and Last Name to the Selected Fields

  8. 200 |
  9. Click Save

  10. 201 |
202 | 203 |

Step 7: Test the Application

204 | 205 |
    206 |
  1. Click the Sessions tab, select a session and make sure the speaker list shows the speaker number, first name, and last name

  2. 207 |
  3. Assign a new speaker to a session and make sure the speaker lookup dialog shows the speaker first name and last name

  4. 208 |
  5. Click the Speakers tab, select a speaker and make sure the session list shows the session name and date

  6. 209 |
210 | 211 |
212 |

If the lists don't show the expected fields, you probably forgot to click the Save button in the Page Layout screen. Go back to steps 4 and 5, and make sure you click Save at the end.

213 |
214 | 215 |
216 |
217 | Previous 218 | Next 219 |
220 | 221 |

222 | 223 |
224 | 225 |
226 | 227 | 246 | 247 | 248 | 249 | 250 |
251 | 252 |
253 | 254 |
255 | 256 |
257 | 260 |
261 | 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /_site/Creating-the-Data-Model.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 2: Creating the Data Model

66 |
67 |

In this module, you create the custom objects that make up the data model for the conference application.

68 | 69 |

70 | 71 |

Step 1: Create the Conference Session Object

72 | 73 |
    74 |
  1. Login into your Developer Edition account

  2. 75 |
  3. Click the Setup link (upper right corner)

    76 | 77 |

  4. 78 |
  5. In the left navigation, select Build > Create > Objects

    79 | 80 |

  6. 81 |
  7. Click New Custom Object, and define the Session object as follows (accept the default values for the properties that are not mentioned below):

    82 | 83 |
      84 |
    • Label: Session
    • 85 |
    • Plural Label: Sessions
    • 86 |
    • Object Name: Session
    • 87 |
    • Record Name: Session Name
    • 88 |
    • Data Type: Text
    • 89 |
    90 | 91 |

  8. 92 |
  9. Click Save

  10. 93 |
  11. In the Custom Fields & Relationships section, click New

    94 | 95 |

  12. 96 |
  13. Create a Session Date field defined as follows:

    97 | 98 |
      99 |
    • Data Type: Date/Time
    • 100 |
    • Field Label: Session Date
    • 101 |
    • Field Name: Session_Date
    • 102 |
    103 | 104 |

    105 | 106 |

    Click Next, Next, Save & New

  14. 107 |
  15. Create a Description field defined as follows:

    108 | 109 |
      110 |
    • Data Type: Text Area (Long)
    • 111 |
    • Field Label: Description
    • 112 |
    • Field Name: Description
    • 113 |
    114 | 115 |

    Click Next, Next, Save & New

  16. 116 |
  17. Create a Level field defined as follows:

    117 | 118 |
      119 |
    • Data Type: Picklist
    • 120 |
    • Field Label: Level
    • 121 |
    • Values: Beginner, Intermediate, Advanced (specify each value on its own row)
    • 122 |
    • Field Name: Level
    • 123 |
    124 | 125 |

    Click Next, Next, Save

  18. 126 |
127 | 128 |

Step 2: Create the Speaker Object

129 | 130 |
    131 |
  1. In Setup mode, select Build > Create > Objects

  2. 132 |
  3. Click New Custom Object, and define the Speaker object as follows (accept the default values for the properties that are not mentioned below):

    133 | 134 |
      135 |
    • Label: Speaker
    • 136 |
    • Plural Label: Speakers
    • 137 |
    • Object Name: Speaker
    • 138 |
    • Record Name: Speaker Number
    • 139 |
    • Data Type: Auto Number
    • 140 |
    • Display Format: SP-{00000}
    • 141 |
    • Starting Number: 1
    • 142 |
  4. 143 |
  5. Click Save

  6. 144 |
  7. In the Custom Fields & Relationships section, click New, and create a First Name field defined as follows:

    145 | 146 |
      147 |
    • Data Type: Text
    • 148 |
    • Field Label: First Name
    • 149 |
    • Length: 30
    • 150 |
    • Field Name: First_Name
    • 151 |
    152 | 153 |

    Click Next, Next, Save & New

  8. 154 |
  9. Create a Last Name field defined as follows:

    155 | 156 |
      157 |
    • Data Type: Text
    • 158 |
    • Field Label: Last Name
    • 159 |
    • Length: 30
    • 160 |
    • Field Name: Last_Name
    • 161 |
    162 | 163 |

    Click Next, Next, Save & New

  10. 164 |
  11. Create an Email field defined as follows:

    165 | 166 |
      167 |
    • Data Type: Email
    • 168 |
    • Field Label: Email
    • 169 |
    • Field Name: Email
    • 170 |
    171 | 172 |

    Click Next, Next, Save & New

  12. 173 |
  13. Create a Bio field defined as follows:

    174 | 175 |
      176 |
    • Data Type: Text Area (Long)
    • 177 |
    • Field Label: Bio
    • 178 |
    • Field Name: Bio
    • 179 |
    180 | 181 |

    Click Next, Next, Save

  14. 182 |
183 | 184 |

Step 3: Create the Session_Speaker Junction Object

185 | 186 |

The Session_Speaker object is used to model the many-to-many relationship between Session and Speaker: a session can have one or many speakers, and a speaker can have one or many sessions.

187 | 188 |
    189 |
  1. In Setup mode, select Build > Create > Objects

  2. 190 |
  3. Click New Custom Object, and define the Session_Speaker object as follows:

    191 | 192 |
      193 |
    • Label: Session Speaker
    • 194 |
    • Plural Label: Session Speakers
    • 195 |
    • Object Name: Session_Speaker
    • 196 |
    • Record Name: Session Speaker Number
    • 197 |
    • Data Type: Auto Number
    • 198 |
    • Display Format: SESP-{00000}
    • 199 |
    • Starting Number: 1
    • 200 |
  4. 201 |
  5. Click Save

  6. 202 |
  7. In the Custom Fields & Relationships section, click New, and create a Session field defined as follows:

    203 | 204 |
      205 |
    • Data Type: Master-Detail Relationship
    • 206 |
    • Related To: Session
    • 207 |
    • Field Label: Session
    • 208 |
    • Field Name: Session
    • 209 |
    210 | 211 |

    Click Next, Next, Next, set the Related List Label to "Speakers" and click Save & New

  8. 212 |
  9. Create a Speaker field defined as follows:

    213 | 214 |
      215 |
    • Data Type: Master-Detail Relationship
    • 216 |
    • Related To: Speaker
    • 217 |
    • Field Label: Speaker
    • 218 |
    • Field Name: Speaker
    • 219 |
    220 | 221 |

    Click Next, Next, Next, set the Related List Label to "Sessions" and click Save

  10. 222 |
223 | 224 |

Step 4: Examine the Data Model in Schema Builder

225 | 226 |
    227 |
  1. In Setup mode, search for "schema" in the left navigation, and click Schema Builder

    228 | 229 |

  2. 230 |
  3. Click Clear All

  4. 231 |
  5. Check Session, Speaker, and Session Speaker

  6. 232 |
  7. Examine the MyConference data model. Rearrange the objects as needed.

  8. 233 |
234 | 235 |
236 |
237 | Previous 238 | Next 239 |
240 | 241 |

242 | 243 |
244 | 245 |
246 | 247 | 266 | 267 | 268 | 269 | 270 |
271 | 272 |
273 | 274 |
275 | 276 |
277 | 280 |
281 | 282 | 283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /_site/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'github-pages' 3 | -------------------------------------------------------------------------------- /_site/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | RedCloth (4.2.9) 5 | activesupport (4.1.1) 6 | i18n (~> 0.6, >= 0.6.9) 7 | json (~> 1.7, >= 1.7.7) 8 | minitest (~> 5.1) 9 | thread_safe (~> 0.1) 10 | tzinfo (~> 1.1) 11 | blankslate (2.1.2.4) 12 | classifier (1.3.4) 13 | fast-stemmer (>= 1.0.0) 14 | colorator (0.1) 15 | commander (4.1.6) 16 | highline (~> 1.6.11) 17 | fast-stemmer (1.0.2) 18 | ffi (1.9.3) 19 | gemoji (1.5.0) 20 | github-pages (19) 21 | RedCloth (= 4.2.9) 22 | jekyll (= 1.5.1) 23 | jekyll-mentions (= 0.0.6) 24 | jekyll-redirect-from (= 0.3.1) 25 | jekyll-sitemap (= 0.3.0) 26 | jemoji (= 0.1.0) 27 | kramdown (= 1.3.1) 28 | liquid (= 2.5.5) 29 | maruku (= 0.7.0) 30 | rdiscount (= 2.1.7) 31 | redcarpet (= 2.3.0) 32 | highline (1.6.21) 33 | html-pipeline (1.5.0) 34 | activesupport (>= 2) 35 | nokogiri (~> 1.4) 36 | i18n (0.6.9) 37 | jekyll (1.5.1) 38 | classifier (~> 1.3) 39 | colorator (~> 0.1) 40 | commander (~> 4.1.3) 41 | liquid (~> 2.5.5) 42 | listen (~> 1.3) 43 | maruku (= 0.7.0) 44 | pygments.rb (~> 0.5.0) 45 | redcarpet (~> 2.3.0) 46 | safe_yaml (~> 1.0) 47 | toml (~> 0.1.0) 48 | jekyll-mentions (0.0.6) 49 | html-pipeline (~> 1.5.0) 50 | jekyll (~> 1.4) 51 | jekyll-redirect-from (0.3.1) 52 | jekyll (~> 1.4) 53 | jekyll-sitemap (0.3.0) 54 | jekyll (~> 1.4) 55 | jemoji (0.1.0) 56 | gemoji (~> 1.5.0) 57 | html-pipeline (~> 1.5.0) 58 | jekyll (~> 1.4) 59 | json (1.8.1) 60 | kramdown (1.3.1) 61 | liquid (2.5.5) 62 | listen (1.3.1) 63 | rb-fsevent (>= 0.9.3) 64 | rb-inotify (>= 0.9) 65 | rb-kqueue (>= 0.2) 66 | maruku (0.7.0) 67 | mini_portile (0.6.0) 68 | minitest (5.3.4) 69 | nokogiri (1.6.2.1) 70 | mini_portile (= 0.6.0) 71 | parslet (1.5.0) 72 | blankslate (~> 2.0) 73 | posix-spawn (0.3.8) 74 | pygments.rb (0.5.4) 75 | posix-spawn (~> 0.3.6) 76 | yajl-ruby (~> 1.1.0) 77 | rb-fsevent (0.9.4) 78 | rb-inotify (0.9.5) 79 | ffi (>= 0.5.0) 80 | rb-kqueue (0.2.3) 81 | ffi (>= 0.5.0) 82 | rdiscount (2.1.7) 83 | redcarpet (2.3.0) 84 | safe_yaml (1.0.3) 85 | thread_safe (0.3.4) 86 | toml (0.1.1) 87 | parslet (~> 1.5.0) 88 | tzinfo (1.2.1) 89 | thread_safe (~> 0.1) 90 | yajl-ruby (1.1.0) 91 | 92 | PLATFORMS 93 | ruby 94 | 95 | DEPENDENCIES 96 | github-pages 97 | -------------------------------------------------------------------------------- /_site/Module2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 |
62 |

Home

63 |
64 |

This is Module 2

65 | 66 |
    67 |
  1. item1

  2. 68 |
  3. item2

    69 | 70 |
      71 |
    • a
    • 72 |
    • b
    • 73 |
    • c
    • 74 |
  4. 75 |
  5. item3

    76 | 77 |
      78 |
    • a
    • 79 |
    • b
    • 80 |
    • c
    • 81 |
  6. 82 |
83 |
some code
 84 | 
85 |
86 | 99 |
100 | 101 |
102 | 105 |
106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /_site/Prerequisites.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Prerequisites

66 |
67 |

Browser Requirements

68 | 69 |
    70 |
  • Google Chrome
  • 71 |
  • Mozilla Firefox
  • 72 |
  • Safari
  • 73 |
  • Internet Explorer 9 or higher
  • 74 |
75 | 76 |

Other Requirements

77 | 78 |
79 | 80 |
81 | 82 | 101 | 102 | 103 | 104 | 105 |
106 | 107 |
108 | 109 |
110 | 111 |
112 | 115 |
116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /_site/Testing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 11: Testing

66 |
67 |

In this module, you write tests for the RejectDoubleBooking trigger you created in module 6.

68 | 69 |

Step 1: Create a Test Class

70 | 71 |
    72 |
  1. In the Developer Console, select File > New > Apex Class, specify TestRejectDoubleBooking as the class name and click OK

  2. 73 |
  3. Make the class private, and add the @isTest class annotation:

    74 |
    @isTest
     75 | private class TestRejectDoubleBooking{
     76 | 
     77 | }
     78 | 
  4. 79 |
80 | 81 |

Step 2: Add a Test Method to Test Single Bookings

82 | 83 |
    84 |
  1. Add a TestSingleBooking() method to the TestRejectDoubleBooking class to make sure the trigger does not prevent a valid speaker booking:

    85 |
    static testmethod void TestSingleBooking() {
     86 |     Datetime now = System.now();
     87 | 
     88 |     Speaker__c speaker = new Speaker__c(First_Name__c='John', Last_Name__c='Smith');
     89 |     insert speaker;
     90 | 
     91 |     Session__c session = new Session__c(Name='Some Session', Session_Date__c=now);
     92 |     insert session;
     93 | 
     94 |     Session_Speaker__c assignment =
     95 |         new Session_Speaker__c(Session__c=session.Id, Speaker__c=speaker.Id);
     96 |     Test.startTest();
     97 |     Database.SaveResult result = Database.insert(assignment, false);
     98 |     Test.stopTest();
     99 | 
    100 |     System.assert(result.isSuccess());
    101 | }
    102 | 
  2. 103 |
  3. Save the file

  4. 104 |
  5. Click Run Test in the upper right corner of the code editor

  6. 105 |
  7. Click the Tests tab at the bottom of the code editor, and examine the test results.

    106 | 107 |

  8. 108 |
109 | 110 |

Step 3: Add a Test Method to Test Double Bookings

111 | 112 |
    113 |
  1. Add a TestDoubleBooking() method to the TestRejectDoubleBooking class to make sure trigger actually rejects double bookings:

    114 |
    static testmethod void TestDoubleBooking() {
    115 |     Datetime now = System.now();
    116 | 
    117 |     Speaker__c speaker = new Speaker__c(First_Name__c='John', Last_Name__c='Smith');
    118 |     insert speaker;
    119 | 
    120 |     Session__c session1 = new Session__c(Name='Session 1', Session_Date__c=now);
    121 |     insert session1;
    122 |     Session__c session2 = new Session__c(Name='Session 2', Session_Date__c=now);
    123 |     insert session2;
    124 | 
    125 |     Session_Speaker__c assignment1 =
    126 |         new Session_Speaker__c(Session__c=session1.Id, Speaker__c=speaker.Id);
    127 |     insert assignment1;
    128 | 
    129 |     Session_Speaker__c assignment2 =
    130 |         new Session_Speaker__c(Session__c=session2.Id, Speaker__c=speaker.Id);
    131 |     Test.startTest();
    132 |     Database.SaveResult result = Database.insert(assignment2, false);
    133 |     Test.stopTest();
    134 | 
    135 |     System.assert(!result.isSuccess());
    136 | }
    137 | 
  2. 138 |
  3. Save the file

  4. 139 |
  5. Click Run Test in the upper right corner of the code editor

  6. 140 |
  7. Click the Tests tab at the bottom of the code editor, and examine the test results.

    141 | 142 |

  8. 143 |
144 | 145 |
146 |
147 | Previous 148 | Next 149 |
150 | 151 |

152 | 153 |
154 | 155 |
156 | 157 | 176 | 177 | 178 | 179 | 180 |
181 | 182 |
183 | 184 |
185 | 186 |
187 | 190 |
191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /_site/Using-JavaScript-in-Visualforce-Pages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 9: Using JavaScript in Visualforce Pages

66 |
67 |

In this module, you create a custom controller with a method that returns a list of conference hotels. You create a Visualforce page that invokes that method using JavaScript Remoting, and uses the Google Maps SDK to display the hotels on a map.

68 | 69 |

70 | 71 |

Step 1: Create the Hotel Object

72 | 73 |
    74 |
  1. In Setup, select Build > Create > Objects

  2. 75 |
  3. Click New Custom Object, and define the Hotel Object as follows:

    76 | 77 |
      78 |
    • Label: Hotel
    • 79 |
    • Plural Label: Hotels
    • 80 |
    • Object Name: Hotel
    • 81 |
    • Record Name: Hotel Name
    • 82 |
    • Data Type: Text
    • 83 |
  4. 84 |
  5. Click Save

  6. 85 |
  7. In the Custom Fields & Relationships section, click New, and create a Location field defined as follows:

    86 | 87 |
      88 |
    • Data Type: Geolocation
    • 89 |
    • Field Label: Location
    • 90 |
    • Latitude and Longitude Display Notation: Decimal
    • 91 |
    • Decimal Places: 7
    • 92 |
    • Field Name: Location
    • 93 |
    94 | 95 |

    Click Next, Next, Save

  8. 96 |
  9. Create a Tab for the Hotel object

    97 | 98 |
      99 |
    • In Setup, select Build > Create > Tabs
    • 100 |
    • In the Custom Object Tabs section, click New
    • 101 |
    • Select the Hotel object and Building as the Tab Style Icon
    • 102 |
    • Click Next, Next
    • 103 |
    • Uncheck the Include Tab checkbox, check the Conference checkbox, and click Save
    • 104 |
    105 | 106 |

  10. 107 |
  11. Enter a couple of hotels with location information. For example:

    108 | 109 |
      110 |
    • Marriott Marquis (37.785143 -122.403405)
    • 111 |
    • Hilton Union Square (37.786164 -122.410137)
    • 112 |
    • Hyatt (37.794157 -122.396311)
    • 113 |
    114 | 115 |

  12. 116 |
117 | 118 |

Step 2: Create the HotelRemoter Controller

119 | 120 |
    121 |
  1. In the Developer Console, select File > New > Apex Class, specify HotelRemoter as the class name and click OK

  2. 122 |
  3. Implement the class as follows:

    123 |
    global with sharing class HotelRemoter {
    124 | 
    125 |     @RemoteAction
    126 |     global static List<Hotel__c> findAll() {
    127 |         return [SELECT Id, Name, Location__Latitude__s, Location__Longitude__s
    128 |                     FROM Hotel__c];
    129 |     }
    130 | 
    131 | }
    132 | 
  4. 133 |
  5. Save the file

  6. 134 |
135 | 136 |

Step 3: Create a Visualforce Page with Google Maps

137 | 138 |
    139 |
  1. In the Developer Console, select File > New > Visualforce Page, specify HotelMap as the page name and click OK

  2. 140 |
  3. Implement HotelMap as follows:

    141 |
    <apex:page sidebar="false" showheader="false">
    142 | 
    143 | <head>
    144 | <style type="text/css">
    145 |   html { height: 100% }
    146 |   body { height: 100%; margin: 0; padding: 0 }
    147 |   #map-canvas { height: 100% }
    148 | </style>
    149 | <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    150 | <script>
    151 | var map;
    152 | 
    153 | function initialize() {
    154 |     var mapOptions = {
    155 |         center: new google.maps.LatLng(37.784173, -122.401557),
    156 |         zoom: 15
    157 |     };
    158 |     map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    159 | }
    160 | 
    161 | google.maps.event.addDomListener(window, 'load', initialize);
    162 | 
    163 | </script>
    164 | </head>
    165 | <body>
    166 |   <div id="map-canvas"/>
    167 | </body>
    168 | 
    169 | </apex:page>
    170 | 
  4. 171 |
  5. Save the file

  6. 172 |
  7. Click the Preview button (upper left corner) to test the HotelMap page in the browser

  8. 173 |
174 | 175 |

Step 4: Display the Hotels on the Map

176 | 177 |
    178 |
  1. Assign HotelRemoter as the controller for the HotelMap Visualforce page:

    179 |
    <apex:page sidebar="false" showheader="false" controller="HotelRemoter">
    180 | 
  2. 181 |
  3. Define a function named loadHotels() implemented as follows (right after the initilize() function):

    182 |
    function loadHotels() {
    183 |     Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.HotelRemoter.findAll}',
    184 |         function(result, event){
    185 |             if (event.status) {
    186 |                 for (var i=0; i<result.length; i++) {
    187 |                     var id = result[i].Id;
    188 |                     var name = result[i].Name;
    189 |                     var lat = result[i].Location__Latitude__s;
    190 |                     var lng = result[i].Location__Longitude__s;
    191 |                     addMarker(id, name, lat, lng);
    192 |                 }
    193 |             } else {
    194 |                 alert(event.message);
    195 |             }
    196 |         },
    197 |         {escape: true}
    198 |     );
    199 | }
    200 | 
  4. 201 |
  5. Define the addMarker() function implemented as follows (right after the loadHotels() function):

    202 |
    function addMarker(id, name, lat, lng) {
    203 |     var marker = new google.maps.Marker({
    204 |             position: new google.maps.LatLng(lat, lng),
    205 |             map: map,
    206 |             title: name
    207 |     });
    208 |     google.maps.event.addListener(marker, 'click', function(event) {
    209 |         window.top.location = '/' + id;
    210 |     });
    211 | }
    212 | 
  6. 213 |
  7. Invoke loadHotels() as the last line of the initialize() function:

    214 |
    loadHotels();
    215 | 
  8. 216 |
  9. Save the file

  10. 217 |
  11. Click the Preview button (upper left corner) to test the HotelMap page in the browser. You should now see markers on the map representing the hotels you entered in Step 1.

  12. 218 |
219 | 220 |
221 |
222 | Previous 223 | Next 224 |
225 | 226 |

227 | 228 |
229 | 230 |
231 | 232 | 251 | 252 | 253 | 254 | 255 |
256 | 257 |
258 | 259 |
260 | 261 |
262 | 265 |
266 | 267 | 268 | 269 | 270 | 271 | 272 | -------------------------------------------------------------------------------- /_site/Using-the-Salesforce1-Platform-APIs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 |

Module 10: Using the Salesforce1 Platform APIs

66 |
67 |

In this module, you create an application that runs outside your Salesforce instance: it uses OAuth to authenticate with Salesforce, and the REST APIs to access Salesforce data.

68 | 69 |

70 | 71 |

Requirement

72 | 73 |

You need Node.js to perform the exercises in this module. If you don't already have Node.js installed on your system, you can install it here.

74 | 75 |
76 |

This module is recommended but optional. If you are not interested in building custom applications (applications hosted outside your Salesforce instance), you can move to Module 11.

77 |
78 | 79 |

Step 1: Create a Connected App

80 | 81 |
    82 |
  1. In Setup, click Build > Create > Apps

  2. 83 |
  3. In the Connected Apps section, click New, and define the Connected App as follows:

    84 | 85 |
      86 |
    • Connected App Name: MyConference
    • 87 |
    • API Name: MyConference
    • 88 |
    • Contact Email: enter your email address
    • 89 |
    • Enabled OAuth Settings: Checked
    • 90 |
    • Callback URL: http://localhost:3000/oauthcallback.html
    • 91 |
    • Selected OAuth Scopes: Full Access (full)
    • 92 |
    93 | 94 |

  4. 95 |
  5. Click Save.

  6. 96 |
97 | 98 |

Step 2: Install the Supporting Files

99 | 100 |
    101 |
  1. Download and unzip this file, or clone this repository

  2. 102 |
  3. Using your favorite code editor, examine the code in client/index.html:

    103 | 104 |
      105 |
    • It provides the basic markup to render a list of sessions as shown in the screenshot above.
    • 106 |
    • It uses ratchet.css. Ratchet is a simple CSS toolkit that provides styles for mobile applications.
    • 107 |
    • It uses ForceTK, the Force.com JavaScript REST Toolkit, to integrate with Salesforce.
    • 108 |
    • You will code the logic of the application (OAuth login) and data access logic in js/app.js which is empty at this time.
    • 109 |
  4. 110 |
  5. Using your favorite code editor, examine the code in client/oauthcallback.html:

    111 | 112 |

    At the end of the OAuth workflow, the Salesforce authentication process loads the redirect URI you specified in your Connected App and passes the access token and other OAuth values (server instance, refresh token, etc.) in the query string. Your redirect URI page simply needs to parse the query string, extract the access token and the other OAuth values, and pass that information back to your application by invoking the oauthCallback() function you will code in Step 4.

  6. 113 |
  7. Using your favorite code editor, examine the code in server.js. server.js implements a small HTTP server that provides two features:

    114 | 115 |
      116 |
    • Web server for static content. The document root for the web server is the client directory.
    • 117 |
    • Proxy for Salesforce REST requests. Because of the browser’s cross-origin restrictions, your JavaScript application hosted on your own server (or localhost) will not be able to make API calls directly to the *.salesforce.com domain. The solution is to proxy your API calls through your own server.
    • 118 |
  8. 119 |
120 | 121 |

Step 3: Start the Node.js server

122 | 123 |
    124 |
  1. Open Terminal (Mac) or a Command prompt (Windows)

  2. 125 |
  3. Navigate (cd) to the salesforce-developer-workshop (or salesforce-developer-workshop-master) directory

  4. 126 |
  5. Install the Node.js server dependencies:

    127 |
    npm install
    128 | 
  6. 129 |
  7. Start the server:

    130 |
    node server
    131 | 
  8. 132 |
  9. Test the application. Open a browser and access the following URL:

    133 |
    http://localhost:3000
    134 | 
    135 |

    Since we didn't authenticate with Salesforce yet, all you should see at this point is an empty list of sessions.

  10. 136 |
137 | 138 |

Step 4: Authenticate with Salesforce using OAuth

139 | 140 |
    141 |
  1. Using your favorite code editor, open app.js in salesforce-developer-workshop/client/js

  2. 142 |
  3. Declare the following variables:

    143 |
    var apiVersion = 'v30.0',
    144 | clientId = 'YOUR_CONSUMER_KEY',
    145 | loginUrl = 'https://login.salesforce.com/',
    146 | redirectURI = 'http://localhost:3000/oauthcallback.html',
    147 | proxyURL = 'http://localhost:3000/proxy/',
    148 | client = new forcetk.Client(clientId, loginUrl, proxyURL);
    149 | 
  4. 150 |
  5. In Setup (back in Salesforce), click Build > Create > Apps. In the Connected Apps section, click MyConference, and copy the Consumer Key to your clipboard.

    151 | 152 |

  6. 153 |
  7. In app.js, replace YOUR_CONSUMER_KEY with the consumer key you copied to your clipboard

  8. 154 |
  9. In app.js, declare a function named login() implemented as follows (right after the variable declarations):

    155 |
    function login() {
    156 |     var url = loginUrl + 'services/oauth2/authorize?display=popup&response_type=token'
    157 |                 + '&client_id=' + encodeURIComponent(clientId)
    158 |                 + '&redirect_uri=' + encodeURIComponent(redirectURI);
    159 |     window.open(url);
    160 | }
    161 | 
  10. 162 |
  11. Declare a function named oauthCallback() implemented as follows (right after the login() function):

    163 |
    function oauthCallback(response) {
    164 |     if (response && response.access_token) {
    165 |         client.setSessionToken(response.access_token,
    166 |                                apiVersion,
    167 |                                response.instance_url);
    168 |         console.log('OAuth authentication succeeded');
    169 |     } else {
    170 |         alert("AuthenticationError: No Token");
    171 |     }
    172 | }
    173 | 
    174 |
    175 |

    oauthCallback() is called by the oauthcallback.html page at the end of the OAuth workflow (see oauthcallback.html in step 2 for details).

    176 |
  12. 177 |
  13. Invoke the login() function as the last line of the app.js file:

    178 |
    login();
    179 | 
  14. 180 |
  15. Test the application

    181 | 182 |
      183 |
    • Open a browser and access http://localhost:3000
    • 184 |
    • Login with your Developer Edition credentials
    • 185 |
    • Open the browser console: you should see the OAuth authentication succeeded message
    • 186 |
    187 | 188 |
    189 |

    It may take a few minutes for a Connected App to be available after you create it. If you get this message: error=invalidclientid&error_description=client%20identifier%20invalid, wait a few minutes and try again.

    190 |
  16. 191 |
192 | 193 |

Step 5: Using the REST APIs

194 | 195 |
    196 |
  1. In app.js, declare a function named getSessions() implemented as follows (right after the oauthCallback() function):

    197 |
    function getSessions() {
    198 |     var soql = "SELECT Id, Name, Session_Date__c FROM Session__c",
    199 |         html = '';
    200 |     client.query(soql,
    201 |         function (data) {
    202 |             var sessions = data.records;
    203 |             for (var i=0; i<sessions.length; i++) {
    204 |                 html += '<li class="table-view-cell">' + sessions[i].Name + '</li>';
    205 |             }
    206 |             $('.session-list').html(html);
    207 |         },
    208 |         function (error) {
    209 |             alert("Error: " + JSON.stringify(error));
    210 |         });
    211 |     return false;
    212 | }
    213 | 
  2. 214 |
  3. Modify the oauthCallback() function to invoke getSessions() when the user has been successfully authenticated.

    215 |
    console.log('OAuth authentication succeeded');
    216 | getSessions();
    217 | 
  4. 218 |
  5. Test the application

    219 | 220 |
      221 |
    • Open a browser and access http://localhost:3000
    • 222 |
    • Login with your Developer Edition credentials
    • 223 |
    • You should now see the list of sessions
    • 224 |
  6. 225 |
226 | 227 |
228 |

This is just the starting point for building a custom application written in JavaScript, authenticating with Salesforce using OAuth, and accessing Salesforce data using the REST APIs. If you are planning on building a real-life application based on this architecture, consider using a JavaScript framework such as Backbone.js or AngularJS with Ionic.

229 |
230 | 231 |
232 |
233 | Previous 234 | Next 235 |
236 | 237 |

238 | 239 |
240 | 241 |
242 | 243 | 262 | 263 | 264 | 265 | 266 |
267 | 268 |
269 | 270 |
271 | 272 |
273 | 276 |
277 | 278 | 279 | 280 | 281 | 282 | 283 | -------------------------------------------------------------------------------- /_site/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn:active, 33 | .btn.active { 34 | background-image: none; 35 | } 36 | .btn-default { 37 | text-shadow: 0 1px 0 #fff; 38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 39 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 40 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 41 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 42 | background-repeat: repeat-x; 43 | border-color: #dbdbdb; 44 | border-color: #ccc; 45 | } 46 | .btn-default:hover, 47 | .btn-default:focus { 48 | background-color: #e0e0e0; 49 | background-position: 0 -15px; 50 | } 51 | .btn-default:active, 52 | .btn-default.active { 53 | background-color: #e0e0e0; 54 | border-color: #dbdbdb; 55 | } 56 | .btn-primary { 57 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 58 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 59 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 60 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 61 | background-repeat: repeat-x; 62 | border-color: #2b669a; 63 | } 64 | .btn-primary:hover, 65 | .btn-primary:focus { 66 | background-color: #2d6ca2; 67 | background-position: 0 -15px; 68 | } 69 | .btn-primary:active, 70 | .btn-primary.active { 71 | background-color: #2d6ca2; 72 | border-color: #2b669a; 73 | } 74 | .btn-success { 75 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 76 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 77 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 78 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 79 | background-repeat: repeat-x; 80 | border-color: #3e8f3e; 81 | } 82 | .btn-success:hover, 83 | .btn-success:focus { 84 | background-color: #419641; 85 | background-position: 0 -15px; 86 | } 87 | .btn-success:active, 88 | .btn-success.active { 89 | background-color: #419641; 90 | border-color: #3e8f3e; 91 | } 92 | .btn-info { 93 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 94 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 95 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 96 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 97 | background-repeat: repeat-x; 98 | border-color: #28a4c9; 99 | } 100 | .btn-info:hover, 101 | .btn-info:focus { 102 | background-color: #2aabd2; 103 | background-position: 0 -15px; 104 | } 105 | .btn-info:active, 106 | .btn-info.active { 107 | background-color: #2aabd2; 108 | border-color: #28a4c9; 109 | } 110 | .btn-warning { 111 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 112 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 113 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 114 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 115 | background-repeat: repeat-x; 116 | border-color: #e38d13; 117 | } 118 | .btn-warning:hover, 119 | .btn-warning:focus { 120 | background-color: #eb9316; 121 | background-position: 0 -15px; 122 | } 123 | .btn-warning:active, 124 | .btn-warning.active { 125 | background-color: #eb9316; 126 | border-color: #e38d13; 127 | } 128 | .btn-danger { 129 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 130 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 131 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 132 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 133 | background-repeat: repeat-x; 134 | border-color: #b92c28; 135 | } 136 | .btn-danger:hover, 137 | .btn-danger:focus { 138 | background-color: #c12e2a; 139 | background-position: 0 -15px; 140 | } 141 | .btn-danger:active, 142 | .btn-danger.active { 143 | background-color: #c12e2a; 144 | border-color: #b92c28; 145 | } 146 | .thumbnail, 147 | .img-thumbnail { 148 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 149 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 150 | } 151 | .dropdown-menu > li > a:hover, 152 | .dropdown-menu > li > a:focus { 153 | background-color: #e8e8e8; 154 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 155 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 156 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 157 | background-repeat: repeat-x; 158 | } 159 | .dropdown-menu > .active > a, 160 | .dropdown-menu > .active > a:hover, 161 | .dropdown-menu > .active > a:focus { 162 | background-color: #357ebd; 163 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 164 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 165 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 166 | background-repeat: repeat-x; 167 | } 168 | .navbar-default { 169 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 170 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 171 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 172 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 173 | background-repeat: repeat-x; 174 | border-radius: 4px; 175 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 176 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 177 | } 178 | .navbar-default .navbar-nav > .active > a { 179 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 180 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); 181 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); 182 | background-repeat: repeat-x; 183 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 184 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 185 | } 186 | .navbar-brand, 187 | .navbar-nav > li > a { 188 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 189 | } 190 | .navbar-inverse { 191 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 192 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 193 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 194 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 195 | background-repeat: repeat-x; 196 | } 197 | .navbar-inverse .navbar-nav > .active > a { 198 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); 199 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%); 200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); 201 | background-repeat: repeat-x; 202 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 203 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 204 | } 205 | .navbar-inverse .navbar-brand, 206 | .navbar-inverse .navbar-nav > li > a { 207 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 208 | } 209 | .navbar-static-top, 210 | .navbar-fixed-top, 211 | .navbar-fixed-bottom { 212 | border-radius: 0; 213 | } 214 | .alert { 215 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 216 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 217 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 218 | } 219 | .alert-success { 220 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 221 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 222 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 223 | background-repeat: repeat-x; 224 | border-color: #b2dba1; 225 | } 226 | .alert-info { 227 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 228 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 230 | background-repeat: repeat-x; 231 | border-color: #9acfea; 232 | } 233 | .alert-warning { 234 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 235 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 236 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 237 | background-repeat: repeat-x; 238 | border-color: #f5e79e; 239 | } 240 | .alert-danger { 241 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 242 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 243 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 244 | background-repeat: repeat-x; 245 | border-color: #dca7a7; 246 | } 247 | .progress { 248 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 249 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 250 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 251 | background-repeat: repeat-x; 252 | } 253 | .progress-bar { 254 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 255 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 256 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 257 | background-repeat: repeat-x; 258 | } 259 | .progress-bar-success { 260 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 261 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 262 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 263 | background-repeat: repeat-x; 264 | } 265 | .progress-bar-info { 266 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 267 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 268 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 269 | background-repeat: repeat-x; 270 | } 271 | .progress-bar-warning { 272 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 273 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 274 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 275 | background-repeat: repeat-x; 276 | } 277 | .progress-bar-danger { 278 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 279 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 280 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 281 | background-repeat: repeat-x; 282 | } 283 | .list-group { 284 | border-radius: 4px; 285 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 286 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 287 | } 288 | .list-group-item.active, 289 | .list-group-item.active:hover, 290 | .list-group-item.active:focus { 291 | text-shadow: 0 -1px 0 #3071a9; 292 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 293 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 294 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 295 | background-repeat: repeat-x; 296 | border-color: #3278b3; 297 | } 298 | .panel { 299 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 300 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 301 | } 302 | .panel-default > .panel-heading { 303 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 304 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 306 | background-repeat: repeat-x; 307 | } 308 | .panel-primary > .panel-heading { 309 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 310 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 311 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 312 | background-repeat: repeat-x; 313 | } 314 | .panel-success > .panel-heading { 315 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 316 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 317 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 318 | background-repeat: repeat-x; 319 | } 320 | .panel-info > .panel-heading { 321 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 322 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 323 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 324 | background-repeat: repeat-x; 325 | } 326 | .panel-warning > .panel-heading { 327 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 328 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 329 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 330 | background-repeat: repeat-x; 331 | } 332 | .panel-danger > .panel-heading { 333 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 334 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 336 | background-repeat: repeat-x; 337 | } 338 | .well { 339 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 340 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 341 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 342 | background-repeat: repeat-x; 343 | border-color: #dcdcdc; 344 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 345 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 346 | } 347 | /*# sourceMappingURL=bootstrap-theme.css.map */ 348 | -------------------------------------------------------------------------------- /_site/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /_site/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /_site/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /_site/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /_site/css/main.css: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* 3 | /* Common 4 | /* 5 | /*****************************************************************************/ 6 | 7 | /* Global Reset */ 8 | * { 9 | margin: 0; 10 | padding: 0; 11 | } 12 | 13 | html, body { height: 100%; } 14 | 15 | body { 16 | background-color: #FFF; 17 | font: 13.34px Helvetica, Arial, sans-serif; 18 | font-size: small; 19 | text-align: center; 20 | } 21 | 22 | h1, h2, h3, h4, h5, h6 { 23 | font-size: 100%; } 24 | 25 | h1 { margin-bottom: 1em; } 26 | p { margin: 1em 0; } 27 | 28 | a { color: #00a; } 29 | a:hover { color: #000; } 30 | a:visited { color: #a0a; } 31 | 32 | /*****************************************************************************/ 33 | /* 34 | /* Home 35 | /* 36 | /*****************************************************************************/ 37 | .posts { 38 | list-style-type: none; 39 | margin-bottom: 2em; 40 | } 41 | 42 | .posts li { 43 | line-height: 1.75em; 44 | } 45 | 46 | .posts span { 47 | color: #aaa; 48 | font-family: Monaco, "Courier New", monospace; 49 | font-size: 80%; 50 | } 51 | 52 | /*****************************************************************************/ 53 | /* 54 | /* Site 55 | /* 56 | /*****************************************************************************/ 57 | 58 | .site { 59 | font-size: 115%; 60 | text-align: justify; 61 | width: 42em; 62 | margin: 3em auto 2em; 63 | line-height: 1.5em; 64 | } 65 | 66 | .header a { 67 | font-weight: bold; 68 | text-decoration: none; 69 | } 70 | 71 | .title { 72 | display: inline-block; 73 | margin-bottom: 2em; 74 | } 75 | 76 | .title a { 77 | color: #a00; 78 | } 79 | 80 | .title a:hover { 81 | color: #000; 82 | } 83 | 84 | .header a.extra { 85 | color: #aaa; 86 | margin-left: 1em; 87 | } 88 | 89 | .header a.extra:hover { 90 | color: #000; 91 | } 92 | 93 | .meta { 94 | color: #aaa; 95 | } 96 | 97 | .footer { 98 | font-size: 80%; 99 | color: #666; 100 | border-top: 4px solid #eee; 101 | margin-top: 2em; 102 | overflow: hidden; 103 | } 104 | 105 | .footer .contact { 106 | float: left; 107 | margin-right: 3em; 108 | } 109 | 110 | .footer .contact a { 111 | color: #8085C1; 112 | } 113 | 114 | .footer .rss { 115 | margin-top: 1.1em; 116 | margin-right: -.2em; 117 | float: right; 118 | } 119 | 120 | .footer .rss img { 121 | border: 0; 122 | } 123 | 124 | /*****************************************************************************/ 125 | /* 126 | /* Posts 127 | /* 128 | /*****************************************************************************/ 129 | 130 | /* standard */ 131 | .post pre { 132 | border: 1px solid #ddd; 133 | background-color: #eef; 134 | padding: 0 .4em; 135 | } 136 | 137 | .post ul, .post ol { 138 | margin-left: 1.35em; 139 | } 140 | 141 | .post code { 142 | border: 1px solid #ddd; 143 | background-color: #eef; 144 | padding: 0 .2em; 145 | } 146 | 147 | .post pre code { 148 | border: none; 149 | } 150 | 151 | /* terminal */ 152 | .post pre.terminal { 153 | border: 1px solid #000; 154 | background-color: #333; 155 | color: #FFF; 156 | } 157 | 158 | .post pre.terminal code { 159 | background-color: #333; 160 | } 161 | -------------------------------------------------------------------------------- /_site/css/styles.css: -------------------------------------------------------------------------------- 1 | img { 2 | max-width: 100%; 3 | border: solid 1px #eee; 4 | } 5 | 6 | 7 | 8 | h1{ 9 | font-size: 32px; 10 | } 11 | 12 | 13 | blockquote { 14 | font-size: inherit; 15 | line-height: inherit; 16 | } 17 | .btn-lg { 18 | border-radius: 2px; 19 | background-color: #009CDF; 20 | } 21 | 22 | .jumbotron { 23 | margin-top: -20px; 24 | padding-bottom: 30px; 25 | padding-top: 30px; 26 | } 27 | 28 | .navbar { 29 | background-color: #01344e; 30 | } 31 | 32 | .navbar-default .navbar-nav>li>a, 33 | .navbar-default .navbar-brand { 34 | color: #fff; 35 | } 36 | 37 | .navbar-default .navbar-nav>li>a:hover, 38 | .navbar-default .navbar-brand:hover { 39 | color: #2ac2ff; 40 | color: #009CDF; 41 | } 42 | 43 | .right-nav { 44 | padding-top: 20px; 45 | } 46 | 47 | .right-nav ol { 48 | margin: 10px 10px 0 40px; 49 | } 50 | 51 | .right-nav ol > li { 52 | padding: 4px 0; 53 | } 54 | 55 | 56 | .list-group-item { 57 | } 58 | 59 | h3 { 60 | margin-top: 30px; 61 | margin-bottom: 20px; 62 | } 63 | 64 | li>ul { 65 | margin-bottom:20px; 66 | } 67 | 68 | li>ul>li { 69 | margin-bottom: 10px; 70 | } 71 | 72 | #footer { 73 | margin-top:50px; 74 | padding-bottom:20px; 75 | padding-top: 20px; 76 | border-top: solid 1px #eee; 77 | } 78 | 79 | blockquote { 80 | padding: 15px; 81 | margin-bottom: 20px; 82 | border: 1px solid transparent; 83 | border-radius: 4px; 84 | color: #31708f; 85 | background-color: #d9edf7; 86 | border-color: #bce8f1; 87 | } 88 | -------------------------------------------------------------------------------- /_site/css/syntax.css: -------------------------------------------------------------------------------- 1 | .highlight { background: #ffffff; } 2 | .highlight .c { color: #999988; font-style: italic } /* Comment */ 3 | .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 4 | .highlight .k { font-weight: bold } /* Keyword */ 5 | .highlight .o { font-weight: bold } /* Operator */ 6 | .highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 10 | .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 11 | .highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #aa0000 } /* Generic.Error */ 14 | .highlight .gh { color: #999999 } /* Generic.Heading */ 15 | .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 16 | .highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ 17 | .highlight .go { color: #888888 } /* Generic.Output */ 18 | .highlight .gp { color: #555555 } /* Generic.Prompt */ 19 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 20 | .highlight .gu { color: #aaaaaa } /* Generic.Subheading */ 21 | .highlight .gt { color: #aa0000 } /* Generic.Traceback */ 22 | .highlight .kc { font-weight: bold } /* Keyword.Constant */ 23 | .highlight .kd { font-weight: bold } /* Keyword.Declaration */ 24 | .highlight .kp { font-weight: bold } /* Keyword.Pseudo */ 25 | .highlight .kr { font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 27 | .highlight .m { color: #009999 } /* Literal.Number */ 28 | .highlight .s { color: #d14 } /* Literal.String */ 29 | .highlight .na { color: #008080 } /* Name.Attribute */ 30 | .highlight .nb { color: #0086B3 } /* Name.Builtin */ 31 | .highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #008080 } /* Name.Constant */ 33 | .highlight .ni { color: #800080 } /* Name.Entity */ 34 | .highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ 35 | .highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ 36 | .highlight .nn { color: #555555 } /* Name.Namespace */ 37 | .highlight .nt { color: #000080 } /* Name.Tag */ 38 | .highlight .nv { color: #008080 } /* Name.Variable */ 39 | .highlight .ow { font-weight: bold } /* Operator.Word */ 40 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 41 | .highlight .mf { color: #009999 } /* Literal.Number.Float */ 42 | .highlight .mh { color: #009999 } /* Literal.Number.Hex */ 43 | .highlight .mi { color: #009999 } /* Literal.Number.Integer */ 44 | .highlight .mo { color: #009999 } /* Literal.Number.Oct */ 45 | .highlight .sb { color: #d14 } /* Literal.String.Backtick */ 46 | .highlight .sc { color: #d14 } /* Literal.String.Char */ 47 | .highlight .sd { color: #d14 } /* Literal.String.Doc */ 48 | .highlight .s2 { color: #d14 } /* Literal.String.Double */ 49 | .highlight .se { color: #d14 } /* Literal.String.Escape */ 50 | .highlight .sh { color: #d14 } /* Literal.String.Heredoc */ 51 | .highlight .si { color: #d14 } /* Literal.String.Interpol */ 52 | .highlight .sx { color: #d14 } /* Literal.String.Other */ 53 | .highlight .sr { color: #009926 } /* Literal.String.Regex */ 54 | .highlight .s1 { color: #d14 } /* Literal.String.Single */ 55 | .highlight .ss { color: #990073 } /* Literal.String.Symbol */ 56 | .highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ 57 | .highlight .vc { color: #008080 } /* Name.Variable.Class */ 58 | .highlight .vg { color: #008080 } /* Name.Variable.Global */ 59 | .highlight .vi { color: #008080 } /* Name.Variable.Instance */ 60 | .highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ 61 | -------------------------------------------------------------------------------- /_site/images/api.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/api.jpg -------------------------------------------------------------------------------- /_site/images/app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/app.jpg -------------------------------------------------------------------------------- /_site/images/conference-app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/conference-app.jpg -------------------------------------------------------------------------------- /_site/images/connected-app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/connected-app.jpg -------------------------------------------------------------------------------- /_site/images/consumer-key.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/consumer-key.jpg -------------------------------------------------------------------------------- /_site/images/custom-object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/custom-object.jpg -------------------------------------------------------------------------------- /_site/images/devconsole.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/devconsole.jpg -------------------------------------------------------------------------------- /_site/images/doublebooking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/doublebooking.jpg -------------------------------------------------------------------------------- /_site/images/hotel-tab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/hotel-tab.jpg -------------------------------------------------------------------------------- /_site/images/hotelmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/hotelmap.jpg -------------------------------------------------------------------------------- /_site/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/logo.png -------------------------------------------------------------------------------- /_site/images/lookup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/lookup.jpg -------------------------------------------------------------------------------- /_site/images/marriott.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/marriott.jpg -------------------------------------------------------------------------------- /_site/images/new-field.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/new-field.jpg -------------------------------------------------------------------------------- /_site/images/queryeditor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/queryeditor.jpg -------------------------------------------------------------------------------- /_site/images/salesforce1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/salesforce1.png -------------------------------------------------------------------------------- /_site/images/schema.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/schema.jpg -------------------------------------------------------------------------------- /_site/images/search-schema.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/search-schema.jpg -------------------------------------------------------------------------------- /_site/images/session-detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/session-detail.jpg -------------------------------------------------------------------------------- /_site/images/session-field.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/session-field.jpg -------------------------------------------------------------------------------- /_site/images/session-layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/session-layout.jpg -------------------------------------------------------------------------------- /_site/images/session-object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/session-object.jpg -------------------------------------------------------------------------------- /_site/images/setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/setup.jpg -------------------------------------------------------------------------------- /_site/images/speaker-layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/speaker-layout.jpg -------------------------------------------------------------------------------- /_site/images/speaker-lookup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/speaker-lookup.jpg -------------------------------------------------------------------------------- /_site/images/speaker-lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/speaker-lookup.png -------------------------------------------------------------------------------- /_site/images/sysadmin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/sysadmin.jpg -------------------------------------------------------------------------------- /_site/images/test1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/test1.jpg -------------------------------------------------------------------------------- /_site/images/test2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/test2.jpg -------------------------------------------------------------------------------- /_site/images/upload.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/_site/images/upload.jpg -------------------------------------------------------------------------------- /_site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 |
62 |
63 | 64 |

Salesforce Developer Workshop

65 |

Fast-Track to Salesforce Application Development

66 |

Start Now

67 |
68 | 69 | 70 |
71 |
72 |
73 |
74 | 75 |
76 |

In this workshop, you use the Salesforce Platform to build a conference management application that allows conference administrators to manage all the 77 | aspects of a conference: sessions, speakers, hotels, etc. You also create a simple consumer-facing application that allows conference attendees to view the conference schedule, and learn more about sessions and speakers.

78 | 79 |

What You Will learn

80 | 81 | 95 | 96 |

Prerequisites

97 | 98 | 103 | 104 |

Browser Requirements

105 | 106 | 112 | 113 |

Issues

114 | 115 |

Please create an issue here if you run into any problem or if you have a suggestion to make this workshop better.

116 | 117 |
118 | 119 |
120 | 123 |
124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /_site/jekyll/update/2014/06/07/welcome-to-jekyll.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Welcome to Jekyll! 6 | 7 | 8 | 9 | 10 |

Welcome to Jekyll!

11 | 12 |

Welcome to Jekyll!

13 |

07 Jun 2014

14 | 15 |
16 |

You'll find this post in your _posts directory - edit this post and re-build (or run with the -w switch) to see your changes! 17 | To add new posts, simply add a file in the _posts directory that follows the convention: YYYY-MM-DD-name-of-post.ext.

18 | 19 |

Jekyll also offers powerful support for code snippets:

20 | 21 |
def print_hi(name)
22 |   puts "Hi, #{name}"
23 | end
24 | print_hi('Tom')
25 | #=> prints 'Hi, Tom' to STDOUT.
26 | 
27 | 28 |

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll's GitHub repo.

29 | 30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /_site/signup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Salesforce Developer Workshop 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 60 |
61 |
62 |

Module 1: Creating a Developer Edition Account

63 |
64 |

In this module, you create a Developer Edition Account that provides you with a full-featured but isolated Salesforce environment to perform the exercises in this workshop.

65 | 66 |

Steps

67 | 68 |
    69 |
  1. Open a browser and access the following URL: http://developer.salesforce.com/join

  2. 70 |
  3. Fill in the signup form:

    71 | 72 |
      73 |
    • Enter your First Name and Last Name.
    • 74 |
    • For Email, enter an email address you can access now (you will need to open an activation email).
    • 75 |
    • For Username, specify a unique user name in the form of an email address. for example: firsname.lastname@s1workshop.com (The user name doesn't have to be an existing email address: it is is not used to send you emails).
    • 76 |
    • Enter the captcha value, check the Master Subscription Agreement checkbox and click the Sign Me Up button.
    • 77 |
  4. 78 |
  5. Check your email. You will receive an activation email for your Developer Edition account.

  6. 79 |
  7. Click the link in the activation email. Enter your new password information, and click Save.

  8. 80 |
81 | 82 |
83 | 96 |
97 | 98 |
99 | 102 |
103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /client/css/styles.css: -------------------------------------------------------------------------------- 1 | .session-list { 2 | margin-top: 0 !important; 3 | border-top:none; 4 | } -------------------------------------------------------------------------------- /client/fonts/ratchicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/client/fonts/ratchicons.eot -------------------------------------------------------------------------------- /client/fonts/ratchicons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (C) 2014 by original authors @ fontello.com 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 | -------------------------------------------------------------------------------- /client/fonts/ratchicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/client/fonts/ratchicons.ttf -------------------------------------------------------------------------------- /client/fonts/ratchicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/salesforce-developer-workshop/566f87e8fd7ce001f62e1ba564b8661a299754b4/client/fonts/ratchicons.woff -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

Sessions

14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /client/js/app.js: -------------------------------------------------------------------------------- 1 | // App code goes here -------------------------------------------------------------------------------- /client/oauthcallback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "express": "~4.4.1", 4 | "request": "~2.36.0", 5 | "body-parser": "~1.3.0", 6 | "method-override": "~2.0.1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | http = require('http'), 3 | path = require('path'), 4 | bodyParser = require('body-parser'), 5 | methodOverride = require('method-override'), 6 | request = require('request'), 7 | app = express(); 8 | 9 | app.use(bodyParser()); // pull information from html in POST 10 | app.use(methodOverride()); // simulate DELETE and PUT 11 | 12 | app.use(express.static(__dirname + '/client')); 13 | 14 | app.all('/proxy', function(req, res) { 15 | var url = req.header('SalesforceProxy-Endpoint'); 16 | console.log("proxying: " + url); 17 | request({ url: url, method: req.method, json: req.body, headers: {'Authorization': req.header('X-Authorization')} }).pipe(res); 18 | }); 19 | 20 | app.set('port', process.env.PORT || 3000); 21 | 22 | app.listen(app.get('port'), function () { 23 | console.log('Express server listening on port ' + app.get('port')); 24 | }); --------------------------------------------------------------------------------