Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Oracle Service Cloud Developing Custom Functionality with Customer Portal Widgets
Chris Fellows Senior Manager North America Solutions Consulting April 1, 2015
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Agenda
Widget Architecture Overview
Files in a Widget
Creating a new Widget
Extending a Widget
1
2
3
4
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
“Any part of a page that is dynamic or may be reused on other pages should be modeled as a widget.”
– A very wise CP Developer
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Backend
Widget Architecture
Database
Widget View
JS Event Bus
Services
Browser
Web Server
Widget Client View
Widget Logic
Widget Controller
Page View
Page Controller
Models
AJAX Controller
Template
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Backend
Widget Architecture
Database
Widget View
JS Event Bus
Services
Browser
Web Server
Widget Client View
Widget Logic
Widget Controller
Page View
Page Controller
Models
AJAX Controller
Template
Initial page render (HTML) on server
combines PHP views from template, page,
and widgets.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Backend
Widget Architecture
Database
Widget View
JS Event Bus
Services
Browser
Web Server
Widget Client View
Widget Logic
Widget Controller
Page View
Page Controller
Models
AJAX Controller
Template After initial load, HTML
changes use the EJS widget view and are
controlled by the widget logic.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• info.yml
– Configuration for the widget, versioning, extension info, etc.
• controller.php
– Loads any data from models and stores it in structures available to the PHP view and / or to JavaScript.
– Also can be an ajax endpoint for this widget.
• logic.js
– Essentially the controller on the browser side of things. Setup events, handle changes and ajax results, etc.
• view.ejs and view.php
– HTML for this widget
Widget Files SearchSuggestions Widget
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget info.yml file
Version
• Version Number
Dependencies
• Framework Version
• YUI Components
• JS Module (mobile/desktop)
Extensions
• Widget to extend from
• Components to extend
Attributes
• Names
• Descriptions
• Default Values
• Etc
Documentation
• Description
• URL Parameters
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget info.yml
version: "2.0.1" requires: framework: ["3.1", "3.2"] jsModule: [standard, mobile] attributes: label_renew_button: name: rn:msg:LABEL_RENEW_LBL description: rn:msg:LABEL_TO_USE_FOR_RENEW_BUTTON_LBL default: rn:msg:RENEW_CMD type: STRING url: name: rn:msg:URL_LBL description: rn:msg:URL_PG_REF_LINK_ACTIVATED_DEF_VAL_MSG default: rn:php:'/app/' . \RightNow\Utils\Config::getConfig(CP_ANSWERS_DETAIL_URL) type: STRING renew_notification_ajax: name: rn:msg:RENEW_ANSWER_NOTIFICATION_AJAX_CMD type: ajax description: rn:msg:ENDPOINT_RENEW_ANS_NOTIFICATIONS_LBL default: /ci/ajaxRequest/addOrRenewNotification info: description: rn:msg:WIDGET_DISP_ANS_NOTIF_LOGGED_ALLOWS_MSG
Example
But you don’t really need to know the syntax
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget info.yml file
Supported tagging
• rn:msg – Message base strings
• rn:cfg – Config base values
• rn:def – Value of system define
• rn:php – Any valid PHP code
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Building Your Own Widget
1. Are you sure a stock widget won’t work? • Stick to stock widgets when you can. Many are more generic than you think or have
attributes to do what you need. Check for this first to accelerate development and reduce maintenance costs.
• Example: The MultiLine and Grid widgets will display results from any specified reports.
2. Is the functionality you need similar to a stock widget? • If so, then you should extend the stock widget rather than creating a new one from
scratch.
3. Is this totally unique for functionality and data? • Alright, build your own widget from scratch... It’s easy.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Go to Widgets > Create a New Widget
–Note: use this to extend widgets, too.
Use the Widget Builder
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Go to Widgets > Create a New Widget
–Note: use this to extend widgets, too.
• Select Create a brand new widget from scratch
• Name it and specify a folder
Use the Widget Builder
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Go to Widgets > Create a New Widget
– Note: use this to extend widgets, too.
• Select Create a brand new widget from scratch
• Name it and specify a folder
• Choose your components
– If you’re using data, you need a controller
– Nearly all widgets have views*
– Interactive widgets should have JavaScript
Use the Widget Builder
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• When you finish, new files will be added for you. Navigate to the widgets/custom folder in WebDAV to see the new files. – Your choices have determined what
files are there and have filled out the info.yml file
– You might have to force WebDrive (or whatever) to refresh to see the new directory.
• You now have a new (so far useless) widget
Use the Widget Builder
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Use the controller to fetch data from a model. This should be done in the most important function: getData().
• Everything is in $this->data – $this->data[‘attrs’]
• Contains any attributes that have been set
– $this->data[‘js’][‘your_key’] • Store data you want to make available to JS
and JS views
– $this->data[‘your_key’] • Store data made available to PHP view
<?php
namespace Custom\Widgets\test;
class test extends \RightNow\Libraries\Widget\Base {
function __construct($attrs) {
parent::__construct($attrs);
}
function getData() {
// good stuff with $this->data go here
$this->data[‘name’] = “World”;
return parent::getData();
}
}
Widget First Steps: controller.php
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• The view is just HTML with optional variables and control flow for iterating on variables or conditions.
• Leave the default template with the wrapping div and default ID and class.
• Add whatever you want in the middle.
• Use PHP syntax for vars and control:
– <?= $variable ?>
– <? if ($variable): ?> something to show if $var is true <? endif; ?>
<div id="rn_<?= $this->instanceID ?>" class="<?= $this->classList ?>">
<!– Put what you want here -->
Hello, <?=$this->data[‘name’]?>
</div>
Widget First Steps: view.php
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Constructor
– Generally sets up local variables as references to DOM elements
– Adds any event handlers
– May kick off an ajax request
• Other functions
– Arbitrary. Generally used for event handling, launching AJAX requests and handling return values, etc.
RightNow.namespace('Custom.Widgets.test.test'); Custom.Widgets.test.test = RightNow.Widgets.extend({ /** * Widget constructor. */ constructor: function() { // Typical constructor body this._container = this.Y.one(this.baseSelector); this._form = this.Y.one(this.baseSelector + ‘ form’); this._form.on(‘submit’, this.onSave, this); }, onSave: function(e) { // Typical event handler skeleton e.preventDefault(); this._form.addClass(this.data.attrs.loading_class); // ... } });
Widget First Steps: logic.js
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Events
• JavaScript is event driven. Standard events include button clicks or mouse over. Subscribing to an event involves registering a function to run when that event happens.
• Custom events can be created with an arbitrary name, like, “NeedData” and anything registered to run when that event happens can respond to that event.
• In practice, data can be passed and returned with events. In this way, a collection of widgets can keep their state synchronized and share data with loose coupling.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widgets and YUI Modules
To add charts, drag and drop features, or other modules to YUI, your widget’s info.yml file needs to declare the modules in the requires section.
requires:
jsModule:
- standard
- mobile
yui:
- io-form
CP Documentation
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension Points
• Override functions / call parent Controller.php
• Override view blocks
• Completely replace Views
• Override functions / call parent
• Completely replace Logic.js
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
• Each standard widget has multiple <rn:block> tags – These represent insertion points or, in
some cases, blocks of HTML that can be overwritten by extending widgets.
– For elements that JavaScript needs to find in order to function, we do not allow overriding or replacing of the HTML (no wrapping block).
<rn:block id="top"/>
<rn:block id="preImage"/>
<rn:block id="staticSection">
...
</rn:block>
Widget Extension – view.php and view.ejs
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – view
Standard Widget
<rn:block id="preFeedbackInput"/>
<label>Your Feedback</label>
<textarea></textarea>
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – view
Custom Widget
<rn:block id="preFeedbackInput">
<label>How did you find this answer?</label>
<input id="findAnswer" class="rn_EmailField" type="text" value=""/>
</rn:block>
Adds a new label and
input box to the
AnswerFeedback
dialog.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – view
Inserted at the insertion point preFeedbackInput.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – view
When you extend a widget’s view: •You can add content at the location of any <rn:block>
tag •Any *.ejs files your widget contains will be consumed •The parent widget’s CSS (both base and presentation)
are conditionally included –The class="<?= $this->classList ?>" generated by the
wizard does this for you by including the classes of the parents.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – controller.php <?php
namespace Custom\Widgets\sample;
class SampleWidget extends \RightNow\Widgets\AnswerFeedback {
function getData(){
parent::getData();
$referrer = $_SERVER['HTTP_REFERER'];
if($referrer && stringContains($referrer, 'google')){
$this->data['source'] = "Google Search";
}
}
}
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widget Extension – logic.js
RightNow.namespace('Custom.Widgets.sample');
Custom.Widgets.sample.SampleWidget = RightNow.Widgets.AnswerFeedback.extend({
_submitFeedback: function() {
//Code to add new field data to textarea
this.parent()._submitFeedback();
}
});
Copyright © 2015, Oracle and/or its affiliates. All rights reserved.
Widgets - Ajax
Can use common controller endpoints
Now can call widget controller directly
Routing is handled and widget knows its attributes
Better encapsulation and better extensibility