Version Notes
You can manage the look and feel of your button. You can schedule call backs to suit your business hours.
Download this release
Release Info
Developer | cloud.IQ |
Extension | cloudiq |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/Cloudiq/Callme/Block/Adminhtml/Config/Edit/Tab/Callme.php +340 -0
- app/code/community/Cloudiq/Callme/Block/Button.php +151 -0
- app/code/community/Cloudiq/Callme/Helper/Data.php +63 -0
- app/code/community/Cloudiq/Callme/Helper/Options.php +78 -0
- app/code/community/Cloudiq/Callme/Model/Api/Callme.php +155 -0
- app/code/community/Cloudiq/Callme/Model/Config.php +168 -0
- app/code/community/Cloudiq/Callme/Model/Observer.php +97 -0
- app/code/community/Cloudiq/Callme/Model/Resource/Config.php +8 -0
- app/code/community/Cloudiq/Callme/Model/Resource/Config/Collection.php +7 -0
- app/code/community/Cloudiq/Callme/Test/Config/Base.php +26 -0
- app/code/community/Cloudiq/Callme/Test/Controller/Block.php +46 -0
- app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testCallmeDisabled.yaml +43 -0
- app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testCoreDisabled.yaml +43 -0
- app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testDisplayOnAllPages.yaml +41 -0
- app/code/community/Cloudiq/Callme/Test/Controller/Block/providers/testDisplayOnAllPages.yaml +3 -0
- app/code/community/Cloudiq/Callme/Test/Helper/Options.php +61 -0
- app/code/community/Cloudiq/Callme/Test/Model/Config.php +97 -0
- app/code/community/Cloudiq/Callme/Test/Model/Config/fixtures/validConfigObject.yaml +38 -0
- app/code/community/Cloudiq/Callme/Test/Model/Config/providers/testOptionalField.yaml +3 -0
- app/code/community/Cloudiq/Callme/Test/Model/Config/providers/testRequiredField.yaml +34 -0
- app/code/community/Cloudiq/Callme/Varien/Data/Form/Element/Colourpicker.php +19 -0
- app/code/community/Cloudiq/Callme/Varien/Data/Form/Element/Openinghours.php +42 -0
- app/code/community/Cloudiq/Callme/controllers/Adminhtml/CallmeController.php +35 -0
- app/code/community/Cloudiq/Callme/controllers/CallmeController.php +36 -0
- app/code/community/Cloudiq/Callme/etc/config.xml +115 -0
- app/code/community/Cloudiq/Callme/sql/cloudiq_callme_setup/mysql4-install-1.0.0.php +53 -0
- app/code/community/Cloudiq/Core/.gitkeep +0 -0
- app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit.php +15 -0
- app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Form.php +12 -0
- app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tab/Frame.php +39 -0
- app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tab/Global.php +87 -0
- app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tabs.php +20 -0
- app/code/community/Cloudiq/Core/Helper/Config.php +58 -0
- app/code/community/Cloudiq/Core/Helper/Data.php +5 -0
- app/code/community/Cloudiq/Core/Model/Api/Abstract.php +10 -0
- app/code/community/Cloudiq/Core/Model/Api/Core.php +67 -0
- app/code/community/Cloudiq/Core/Model/Api/Request.php +109 -0
- app/code/community/Cloudiq/Core/Model/Api/Response.php +170 -0
- app/code/community/Cloudiq/Core/Test/Config/Base.php +26 -0
- app/code/community/Cloudiq/Core/Test/Model/Api/Response.php +55 -0
- app/code/community/Cloudiq/Core/Test/Model/Api/TestCase.php +47 -0
- app/code/community/Cloudiq/Core/Test/Model/Api/data/Response/testWasSuccessfulBadResponseAttribute.txt +15 -0
- app/code/community/Cloudiq/Core/Test/Model/Api/data/Response/testWasSuccessfulStatusCodeAndResponseAttribute.txt +16 -0
- app/code/community/Cloudiq/Core/controllers/Adminhtml/CloudiqController.php +93 -0
- app/code/community/Cloudiq/Core/etc/adminhtml.xml +31 -0
- app/code/community/Cloudiq/Core/etc/config.xml +70 -0
- app/design/adminhtml/default/default/layout/cloudiq/callme.xml +24 -0
- app/design/adminhtml/default/default/layout/cloudiq/core.xml +47 -0
- app/design/adminhtml/default/default/template/cloudiq/core/tab/frame/iframe.phtml +1 -0
- app/design/adminhtml/default/default/template/cloudiq/core/tab/frame/submitter.phtml +11 -0
- app/design/adminhtml/default/default/template/cloudiq/core/tabs.phtml +39 -0
- app/design/adminhtml/default/default/template/cloudiq/global/tab.phtml +1 -0
- app/design/adminhtml/default/default/template/cloudiq/global/widget/form.phtml +15 -0
- app/design/frontend/base/default/template/cloudiq/callme/button.phtml +36 -0
- app/etc/modules/Cloudiq_Callme.xml +12 -0
- app/etc/modules/Cloudiq_Core.xml +9 -0
- app/locale/en_GB/Cloudiq_Callme.csv +1 -0
- js/cloudiq/callme-button.js +58 -0
- js/cloudiq/callme-jscolor/arrow.gif +0 -0
- js/cloudiq/callme-jscolor/cross.gif +0 -0
- js/cloudiq/callme-jscolor/demo.html +12 -0
- js/cloudiq/callme-jscolor/hs.png +0 -0
- js/cloudiq/callme-jscolor/hv.png +0 -0
- js/cloudiq/callme-jscolor/jscolor.js +840 -0
- package.xml +22 -0
- skin/adminhtml/default/default/cloudiq/callme.css +17 -0
- skin/adminhtml/default/default/cloudiq/core.css +41 -0
- skin/adminhtml/default/default/cloudiq/js/callme.js +55 -0
- skin/frontend/base/default/cloudiq/css/callme-button.css +198 -0
app/code/community/Cloudiq/Callme/Block/Adminhtml/Config/Edit/Tab/Callme.php
ADDED
@@ -0,0 +1,340 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Callme_Block_Adminhtml_Config_Edit_Tab_Callme extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface {
|
3 |
+
/** @var $_helper Cloudiq_Callme_Helper_Data */
|
4 |
+
protected $_helper;
|
5 |
+
/** @var $_config_helper Cloudiq_Core_Helper_Config */
|
6 |
+
protected $_config_helper;
|
7 |
+
/** @var $_options_helper Cloudiq_Callme_Helper_Options */
|
8 |
+
protected $_options_helper;
|
9 |
+
/** @var $_config_model Cloudiq_Callme_Model_Config */
|
10 |
+
protected $_config_model;
|
11 |
+
/** @var $_input_data Varien_Object */
|
12 |
+
protected $_input_data;
|
13 |
+
|
14 |
+
public function __construct() {
|
15 |
+
parent::__construct();
|
16 |
+
|
17 |
+
$this->_helper = Mage::helper('cloudiq_core');
|
18 |
+
$this->_config_helper = Mage::helper('cloudiq_core/config');
|
19 |
+
|
20 |
+
$this->_options_helper = Mage::helper('cloudiq_callme/options');
|
21 |
+
|
22 |
+
$this->_config_model = Mage::getModel('cloudiq_callme/config');
|
23 |
+
|
24 |
+
$_input_data = Mage::getSingleton("adminhtml/session")->getData("callme_form_data", true);
|
25 |
+
if ($_input_data && count($_input_data->getData()) > 0) {
|
26 |
+
$this->_input_data = $_input_data;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
protected function _prepareForm() {
|
31 |
+
$form = new Varien_Data_Form();
|
32 |
+
|
33 |
+
$this->_addServiceFieldset($form);
|
34 |
+
$this->_addButtonFieldset($form);
|
35 |
+
$this->_addPopupFieldset($form);
|
36 |
+
$this->_addCallbackFieldset($form);
|
37 |
+
$this->_addPublishedFieldset($form);
|
38 |
+
}
|
39 |
+
|
40 |
+
protected function _addPublishedFieldset($form) {
|
41 |
+
$fieldset = $form->addFieldset('published', array('legend' => $this->_helper->__('Published')));
|
42 |
+
|
43 |
+
$fieldset->addField('callme[published][all]', 'checkbox', array(
|
44 |
+
'label' => $this->_helper->__('Display on all pages'),
|
45 |
+
'title' => $this->_helper->__('Display on all pages'),
|
46 |
+
'name' => 'callme[published][all]',
|
47 |
+
'value' => true,
|
48 |
+
'checked' => ($this->_input_data) ? $this->_input_data->getData("published/all") : $this->_config_model->getDisplayOnAll()
|
49 |
+
));
|
50 |
+
|
51 |
+
$published_pages_value = $this->_config_model->getDisplayOnPages();
|
52 |
+
if ($this->_input_data) {
|
53 |
+
$published_pages_value = ($this->_input_data->getData("published/pages")) ? implode(",", $this->_input_data->getData("published/pages")) : "";
|
54 |
+
}
|
55 |
+
|
56 |
+
$fieldset->addField('callme[published][pages]', 'multiselect', array(
|
57 |
+
'label' => $this->_helper->__('Display on selected pages'),
|
58 |
+
'title' => $this->_helper->__('Display on selected pages'),
|
59 |
+
'name' => 'callme[published][pages]',
|
60 |
+
'note' => 'To select multiple pages hold the CTRL button (on Windows) or CMD button (on Mac) down on your keyboard.',
|
61 |
+
'value' => $published_pages_value,
|
62 |
+
'values' => $this->_options_helper->getPagesOptions(),
|
63 |
+
'disabled' => ($this->_input_data) ? $this->_input_data->getData("published/all") : $this->_config_model->getDisplayOnAll()
|
64 |
+
));
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function _addCallbackFieldset($form) {
|
68 |
+
$fieldset = $form->addFieldset('callback', array('legend' => $this->_helper->__('Callback settings')));
|
69 |
+
|
70 |
+
$fieldset->addField('callme[callback][number]', 'text', array(
|
71 |
+
'label' => $this->_helper->__('Your number'),
|
72 |
+
'title' => $this->_helper->__('Your number'),
|
73 |
+
'name' => 'callme[callback][number]',
|
74 |
+
'note' => 'This is the number called when the consumer makes a request. It should be a landline number. Once answered you will be connected to the consumer.',
|
75 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("callback/number") : $this->_config_model->getCallbackCallcentreNumber(),
|
76 |
+
'required' => true,
|
77 |
+
));
|
78 |
+
|
79 |
+
$fieldset->addField('callme[callback][dtmf]', 'text', array(
|
80 |
+
'label' => $this->_helper->__('IVR Menu'),
|
81 |
+
'title' => $this->_helper->__('IVR Menu'),
|
82 |
+
'name' => 'callme[callback][dtmf]',
|
83 |
+
'note' => 'Indicate which options should be selected to route the call to the right person if you have an IVR menu in place.',
|
84 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("callback/dtmf") : $this->_config_model->getCallbackDtmfTunnel(),
|
85 |
+
));
|
86 |
+
|
87 |
+
$fieldset->addField('callme[callback][time_zone]', 'select', array(
|
88 |
+
'label' => $this->_helper->__('Call centre time zone'),
|
89 |
+
'title' => $this->_helper->__('Call centre time zone'),
|
90 |
+
'name' => 'callme[callback][time_zone]',
|
91 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("callback/time_zone") : $this->_config_model->getCallCentreTimeZone(),
|
92 |
+
'values' => Mage::getSingleton("adminhtml/system_config_source_locale_timezone")->toOptionArray()
|
93 |
+
));
|
94 |
+
|
95 |
+
$fieldset->addField('callme[callback][open_hours_label]', 'label', array(
|
96 |
+
'label' => $this->_helper->__('Open Hours'),
|
97 |
+
'title' => $this->_helper->__('Open Hours'),
|
98 |
+
'name' => 'callme[callback][open_hours_label]',
|
99 |
+
));
|
100 |
+
|
101 |
+
$fieldset->addType('openinghours', 'Cloudiq_Callme_Varien_Data_Form_Element_Openinghours');
|
102 |
+
|
103 |
+
$fieldset->addField('callme[callback][monday]', 'openinghours', array(
|
104 |
+
'label' => $this->_helper->__('Monday'),
|
105 |
+
'title' => $this->_helper->__('Monday'),
|
106 |
+
'name' => 'callme[callback][monday]',
|
107 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/monday")) : array(
|
108 |
+
$this->_config_model->getMondayFrom(),
|
109 |
+
$this->_config_model->getMondayTo(),
|
110 |
+
),
|
111 |
+
'required' => true,
|
112 |
+
));
|
113 |
+
|
114 |
+
$fieldset->addField('callme[callback][tuesday]', 'openinghours', array(
|
115 |
+
'label' => $this->_helper->__('Tuesday'),
|
116 |
+
'title' => $this->_helper->__('Tuesday'),
|
117 |
+
'name' => 'callme[callback][tuesday]',
|
118 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/tuesday")) : array(
|
119 |
+
$this->_config_model->getTuesdayFrom(),
|
120 |
+
$this->_config_model->getTuesdayTo(),
|
121 |
+
),
|
122 |
+
'required' => true,
|
123 |
+
));
|
124 |
+
|
125 |
+
$fieldset->addField('callme[callback][wednesday]', 'openinghours', array(
|
126 |
+
'label' => $this->_helper->__('Wednesday'),
|
127 |
+
'title' => $this->_helper->__('Wednesday'),
|
128 |
+
'name' => 'callme[callback][wednesday]',
|
129 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/wednesday")) : array(
|
130 |
+
$this->_config_model->getWednesdayFrom(),
|
131 |
+
$this->_config_model->getWednesdayTo(),
|
132 |
+
),
|
133 |
+
'required' => true,
|
134 |
+
));
|
135 |
+
|
136 |
+
$fieldset->addField('callme[callback][thursday]', 'openinghours', array(
|
137 |
+
'label' => $this->_helper->__('Thursday'),
|
138 |
+
'title' => $this->_helper->__('Thursday'),
|
139 |
+
'name' => 'callme[callback][thursday]',
|
140 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/thursday")) : array(
|
141 |
+
$this->_config_model->getThursdayFrom(),
|
142 |
+
$this->_config_model->getThursdayTo(),
|
143 |
+
),
|
144 |
+
'required' => true,
|
145 |
+
));
|
146 |
+
|
147 |
+
$fieldset->addField('callme[callback][friday]', 'openinghours', array(
|
148 |
+
'label' => $this->_helper->__('Friday'),
|
149 |
+
'title' => $this->_helper->__('Friday'),
|
150 |
+
'name' => 'callme[callback][friday]',
|
151 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/friday")) : array(
|
152 |
+
$this->_config_model->getFridayFrom(),
|
153 |
+
$this->_config_model->getFridayTo(),
|
154 |
+
),
|
155 |
+
'required' => true,
|
156 |
+
));
|
157 |
+
|
158 |
+
$fieldset->addField('callme[callback][saturday]', 'openinghours', array(
|
159 |
+
'label' => $this->_helper->__('Saturday'),
|
160 |
+
'title' => $this->_helper->__('Saturday'),
|
161 |
+
'name' => 'callme[callback][saturday]',
|
162 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/saturday")) : array(
|
163 |
+
$this->_config_model->getSaturdayFrom(),
|
164 |
+
$this->_config_model->getSaturdayTo(),
|
165 |
+
),
|
166 |
+
'required' => true,
|
167 |
+
));
|
168 |
+
|
169 |
+
$fieldset->addField('callme[callback][sunday]', 'openinghours', array(
|
170 |
+
'label' => $this->_helper->__('Sunday'),
|
171 |
+
'title' => $this->_helper->__('Sunday'),
|
172 |
+
'name' => 'callme[callback][sunday]',
|
173 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/sunday")) : array(
|
174 |
+
$this->_config_model->getSundayFrom(),
|
175 |
+
$this->_config_model->getSundayTo(),
|
176 |
+
),
|
177 |
+
'required' => true,
|
178 |
+
));
|
179 |
+
|
180 |
+
$fieldset->addField('callme[callback][bank_holiday]', 'openinghours', array(
|
181 |
+
'label' => $this->_helper->__('Bank Holiday'),
|
182 |
+
'title' => $this->_helper->__('Bank Holiday'),
|
183 |
+
'name' => 'callme[callback][bank_holiday]',
|
184 |
+
'value' => ($this->_input_data) ? array_values($this->_input_data->getData("callback/bank_holiday")) : array(
|
185 |
+
$this->_config_model->getBankHolidayFrom(),
|
186 |
+
$this->_config_model->getBankHolidayTo(),
|
187 |
+
),
|
188 |
+
'required' => true,
|
189 |
+
));
|
190 |
+
}
|
191 |
+
|
192 |
+
protected function _addPopupFieldset($form) {
|
193 |
+
$fieldset = $form->addFieldset('popup', array('legend' => $this->_helper->__('Popup Settings (Click the preview button to view changes)')));
|
194 |
+
|
195 |
+
$fieldset->addField('callme[popup][logo]', 'select', array(
|
196 |
+
'label' => $this->_helper->__('Show company logo?'),
|
197 |
+
'title' => $this->_helper->__('Show company logo?'),
|
198 |
+
'name' => 'callme[popup][logo]',
|
199 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("popup/logo") : $this->_config_model->getPopUpLogo(),
|
200 |
+
'values' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray(),
|
201 |
+
'required' => true,
|
202 |
+
));
|
203 |
+
|
204 |
+
$fieldset->addField('callme[popup][title]', 'text', array(
|
205 |
+
'label' => $this->_helper->__('Title'),
|
206 |
+
'title' => $this->_helper->__('Title'),
|
207 |
+
'name' => 'callme[popup][title]',
|
208 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("popup/title") : $this->_config_model->getPopUpTitle(),
|
209 |
+
'required' => true,
|
210 |
+
));
|
211 |
+
|
212 |
+
$fieldset->addField('callme[popup][strap_line]', 'text', array(
|
213 |
+
'label' => $this->_helper->__('Strap line'),
|
214 |
+
'title' => $this->_helper->__('Strap line'),
|
215 |
+
'name' => 'callme[popup][strap_line]',
|
216 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("popup/strap_line") : $this->_config_model->getPopUpStrapline(),
|
217 |
+
'required' => true,
|
218 |
+
));
|
219 |
+
|
220 |
+
$fieldset->addField('callme[popup][confirmation_open]', 'text', array(
|
221 |
+
'label' => $this->_helper->__('Confirmation - Open'),
|
222 |
+
'title' => $this->_helper->__('Confirmation - Open'),
|
223 |
+
'name' => 'callme[popup][confirmation_open]',
|
224 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("popup/confirmation_open") : $this->_config_model->getPopUpConfOpen(),
|
225 |
+
'required' => true,
|
226 |
+
));
|
227 |
+
|
228 |
+
$fieldset->addField('callme[popup][confirmation_closed]', 'text', array(
|
229 |
+
'label' => $this->_helper->__('Confirmation - Closed'),
|
230 |
+
'title' => $this->_helper->__('Confirmation - Closed'),
|
231 |
+
'name' => 'callme[popup][confirmation_closed]',
|
232 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("popup/confirmation_closed") : $this->_config_model->getPopUpConfClosed(),
|
233 |
+
'required' => true,
|
234 |
+
));
|
235 |
+
|
236 |
+
$this->setForm($form);
|
237 |
+
}
|
238 |
+
|
239 |
+
protected function _addButtonFieldset($form) {
|
240 |
+
$fieldset = $form->addFieldset('button', array('legend' => $this->_helper->__('Button Settings (Please see the preview shown on this page)')));
|
241 |
+
|
242 |
+
$fieldset->addField('callme[button][position]', 'select', array(
|
243 |
+
'label' => $this->_helper->__('Position'),
|
244 |
+
'title' => $this->_helper->__('Position'),
|
245 |
+
'name' => 'callme[button][position]',
|
246 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("button/position") : $this->_config_model->getButtonPosition(),
|
247 |
+
'values' => $this->_options_helper->getButtonPositionOptions(),
|
248 |
+
'required' => true,
|
249 |
+
));
|
250 |
+
|
251 |
+
$fieldset->addField('callme[button][template]', 'select', array(
|
252 |
+
'label' => $this->_helper->__('Template'),
|
253 |
+
'title' => $this->_helper->__('Template'),
|
254 |
+
'name' => 'callme[button][template]',
|
255 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("button/template") : $this->_config_model->getButtonTemplate(),
|
256 |
+
'values' => $this->_options_helper->getButtonTemplateOptions(),
|
257 |
+
'required' => true,
|
258 |
+
));
|
259 |
+
|
260 |
+
$fieldset->addType('colourpicker','Cloudiq_Callme_Varien_Data_Form_Element_Colourpicker');
|
261 |
+
$fieldset->addField('callme[button][colour]', 'colourpicker', array(
|
262 |
+
'label' => $this->_helper->__('Colour'),
|
263 |
+
'title' => $this->_helper->__('Colour'),
|
264 |
+
'name' => 'callme[button][colour]',
|
265 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("button/colour") : $this->_config_model->getButtonColour(),
|
266 |
+
'required' => true,
|
267 |
+
));
|
268 |
+
|
269 |
+
$fieldset->addField('callme[button][heading]', 'text', array(
|
270 |
+
'label' => $this->_helper->__('Button heading'),
|
271 |
+
'title' => $this->_helper->__('Button heading'),
|
272 |
+
'name' => 'callme[button][heading]',
|
273 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("button/heading") : $this->_config_model->getButtonHeading(),
|
274 |
+
'required' => true,
|
275 |
+
));
|
276 |
+
|
277 |
+
$fieldset->addField('callme[button][message]', 'text', array(
|
278 |
+
'label' => $this->_helper->__('Button message'),
|
279 |
+
'title' => $this->_helper->__('Button message'),
|
280 |
+
'name' => 'callme[button][message]',
|
281 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("button/message") : $this->_config_model->getButtonMessage(),
|
282 |
+
'required' => true,
|
283 |
+
));
|
284 |
+
|
285 |
+
$fieldset->addField('callme[button][preview_url]', 'hidden', array(
|
286 |
+
'label' => $this->_helper->__('Preview'),
|
287 |
+
'title' => $this->_helper->__('Preview'),
|
288 |
+
'name' => 'callme[button][preview]',
|
289 |
+
'value' => Mage::helper("adminhtml")->getUrl('*/callme/preview'),
|
290 |
+
));
|
291 |
+
}
|
292 |
+
|
293 |
+
protected function _addServiceFieldset($form) {
|
294 |
+
$fieldset = $form->addFieldset('service', array('legend' => $this->_helper->__('Service')));
|
295 |
+
$fieldset->addField('callme[enabled]', 'select', array(
|
296 |
+
'label' => $this->_helper->__('Enable?'),
|
297 |
+
'title' => $this->_helper->__('Enable?'),
|
298 |
+
'name' => 'callme[enabled]',
|
299 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("enabled") : $this->_config_model->getEnabled(),
|
300 |
+
'values' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray()
|
301 |
+
));
|
302 |
+
|
303 |
+
$fieldset->addField('callme[service][average_sale_value]', 'text', array(
|
304 |
+
'label' => $this->_helper->__('Average sale value'),
|
305 |
+
'title' => $this->_helper->__('Average sale value'),
|
306 |
+
'name' => 'callme[service][average_sale_value]',
|
307 |
+
'note' => 'Please estimate the average value of a sale on your site. This is used for reporting.',
|
308 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("service/average_sale_value") : $this->_config_model->getAverageSaleValue(),
|
309 |
+
'required' => true,
|
310 |
+
));
|
311 |
+
|
312 |
+
$fieldset->addField('callme[service][average_sales_call]', 'select', array(
|
313 |
+
'label' => $this->_helper->__('Average sales call duration'),
|
314 |
+
'title' => $this->_helper->__('Average sales call duration'),
|
315 |
+
'name' => 'callme[service][average_sales_call]',
|
316 |
+
'note' => 'Please estimate how long a sales call would usually take. This is used for reporting.',
|
317 |
+
'value' => ($this->_input_data) ? $this->_input_data->getData("service/average_sales_call") : $this->_config_model->getAverageSalesCall(),
|
318 |
+
'values' => $this->_options_helper->getSalesCallOptions(),
|
319 |
+
'required' => true,
|
320 |
+
));
|
321 |
+
}
|
322 |
+
|
323 |
+
public function getTabLabel() {
|
324 |
+
return $this->__('callMe Settings');
|
325 |
+
}
|
326 |
+
|
327 |
+
public function getTabTitle() {
|
328 |
+
return $this->__('callMe Settings');
|
329 |
+
}
|
330 |
+
|
331 |
+
public function canShowTab() {
|
332 |
+
// Show this if we have an API token
|
333 |
+
return $this->_config_helper->hasBeenSetUp();
|
334 |
+
}
|
335 |
+
|
336 |
+
public function isHidden() {
|
337 |
+
// Hide this if we don't have an API token
|
338 |
+
return !$this->_config_helper->hasBeenSetUp();
|
339 |
+
}
|
340 |
+
}
|
app/code/community/Cloudiq/Callme/Block/Button.php
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Block_Button extends Mage_Core_Block_Template {
|
4 |
+
|
5 |
+
const GRADIENT_COLOUR_STEP = 50;
|
6 |
+
|
7 |
+
public function _construct() {
|
8 |
+
parent::_construct();
|
9 |
+
|
10 |
+
$this->setArea("frontend");
|
11 |
+
$this->setTemplate("cloudiq/callme/button.phtml");
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return the config model.
|
16 |
+
*
|
17 |
+
* @return Varien_Object
|
18 |
+
*/
|
19 |
+
public function getConfig() {
|
20 |
+
if (is_null($this->getData("config"))) {
|
21 |
+
$this->setData("config", Mage::getModel("cloudiq_callme/config"));
|
22 |
+
}
|
23 |
+
|
24 |
+
return $this->getData("config");
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Fetch callMe button properties from the configuration.
|
29 |
+
*
|
30 |
+
* @param $key string The property to fetch.
|
31 |
+
*
|
32 |
+
* @return mixed
|
33 |
+
*/
|
34 |
+
protected function _getFromConfig($key) {
|
35 |
+
return $this->getConfig()->getData($key);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Return the css class representing the selected callMe template.
|
40 |
+
*
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
protected function _getTemplateClass() {
|
44 |
+
return "cloudiq-callme-template-" . strtolower($this->_getFromConfig("button_template"));
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Return the class string for the callMe button based on the config.
|
49 |
+
*
|
50 |
+
* @return string
|
51 |
+
*/
|
52 |
+
protected function _getButtonClass() {
|
53 |
+
$classes = array();
|
54 |
+
// Apply the button template
|
55 |
+
$classes[] = $this->_getTemplateClass();
|
56 |
+
// Position the button
|
57 |
+
$classes[] = "cloudiq-callme-position-" . strtolower($this->_getFromConfig("button_position"));
|
58 |
+
return implode(" ", $classes);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Return the class string for the callMe pop up based on the config.
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
protected function _getPopupClass() {
|
67 |
+
$classes = array();
|
68 |
+
// Apply the template
|
69 |
+
$classes[] = $this->_getTemplateClass();
|
70 |
+
|
71 |
+
return implode(" ", $classes);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Return user selected colour for the button in hex form.
|
76 |
+
*
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
protected function _getColour() {
|
80 |
+
return $this->_getFromConfig("button_colour");
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Return the starting colour for a gradient based on user selected button colour.
|
85 |
+
*
|
86 |
+
* @return string
|
87 |
+
*/
|
88 |
+
protected function _getGradientStartColour() {
|
89 |
+
$base_colour = $this->_getColour();
|
90 |
+
$colour = "";
|
91 |
+
foreach (array(0, 2, 4) as $pos) {
|
92 |
+
$rgb_val = hexdec(substr($base_colour, $pos, 2));
|
93 |
+
$rgb_val = max(0, min(255, $rgb_val + (self::GRADIENT_COLOUR_STEP / 2)));
|
94 |
+
$colour .= str_pad(dechex($rgb_val), 2, "0", STR_PAD_LEFT);
|
95 |
+
}
|
96 |
+
return $colour;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Return the ending colour for a gradient based on user selected button colour.
|
101 |
+
*
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
protected function _getGradientEndColour() {
|
105 |
+
$base_colour = $this->_getColour();
|
106 |
+
$colour = "";
|
107 |
+
foreach (array(0, 2, 4) as $pos) {
|
108 |
+
$rgb_val = hexdec(substr($base_colour, $pos, 2));
|
109 |
+
$rgb_val = max(0, min(255, $rgb_val - (self::GRADIENT_COLOUR_STEP / 2)));
|
110 |
+
$colour .= str_pad(dechex($rgb_val), 2, "0", STR_PAD_LEFT);
|
111 |
+
}
|
112 |
+
return $colour;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Return black or white to contrast the given colour.
|
117 |
+
*
|
118 |
+
* @param $colour string Colour to contrast in hex form.
|
119 |
+
*
|
120 |
+
* @return string
|
121 |
+
*/protected function _getContrastColourBW($colour) {
|
122 |
+
// Count the perceptive luminance (human eye favours green colour)
|
123 |
+
// Source: http://stackoverflow.com/questions/1855884/determine-font-color-based-on-background-color
|
124 |
+
$alpha = 1 - (0.299 * hexdec(substr($colour, 0, 2)) + 0.587 * hexdec(substr($colour, 2, 2)) + 0.114 * hexdec(substr($colour, 4, 2))) / 255;
|
125 |
+
|
126 |
+
if ($alpha < 0.5) {
|
127 |
+
// Bright colour, return black to contrast
|
128 |
+
return "000000";
|
129 |
+
} else {
|
130 |
+
return "FFFFFF";
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Return the submit URL for the callMe callback request form.
|
136 |
+
*
|
137 |
+
* @return string
|
138 |
+
*/
|
139 |
+
protected function _getFormUrl() {
|
140 |
+
return $this->getUrl('cloudiq/callme/request');
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Return the logo to be displayed on the popup if the logo has been enabled.
|
145 |
+
*
|
146 |
+
* @return string Full URL to the logo or an empty string.
|
147 |
+
*/
|
148 |
+
protected function _getLogoUrl() {
|
149 |
+
return ($this->_getFromConfig('pop_up_logo')) ? $this->getSkinUrl(Mage::getStoreConfig('design/header/logo_src'), array("_area" => "frontend")) : "";
|
150 |
+
}
|
151 |
+
}
|
app/code/community/Cloudiq/Callme/Helper/Data.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Callme_Helper_Data extends Mage_Core_Helper_Abstract {
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Update the provided config model with the data from the provided
|
6 |
+
* form model. Used for easy translation between form field names and
|
7 |
+
* config model property names. Updates the config model in place.
|
8 |
+
*
|
9 |
+
* @param Varien_Object $config Config object to update.
|
10 |
+
* @param Varien_Object $form Object containing form data.
|
11 |
+
*/
|
12 |
+
public function updateConfigFromForm(Varien_Object &$config, Varien_Object $form) {
|
13 |
+
$config->addData(array(
|
14 |
+
"enabled" => $form->getData("enabled"),
|
15 |
+
|
16 |
+
"average_sale_value" => $form->getData("service/average_sale_value"),
|
17 |
+
"average_sales_call" => $form->getData("service/average_sales_call"),
|
18 |
+
|
19 |
+
"button_position" => $form->getData("button/position"),
|
20 |
+
"button_template" => $form->getData("button/template"),
|
21 |
+
"button_colour" => $form->getData("button/colour"),
|
22 |
+
"button_heading" => $form->getData("button/heading"),
|
23 |
+
"button_message" => $form->getData("button/message"),
|
24 |
+
|
25 |
+
"pop_up_logo" => $form->getData("popup/logo"),
|
26 |
+
"pop_up_title" => $form->getData("popup/title"),
|
27 |
+
"pop_up_strapline" => $form->getData("popup/strap_line"),
|
28 |
+
"pop_up_conf_open" => $form->getData("popup/confirmation_open"),
|
29 |
+
"pop_up_conf_closed" => $form->getData("popup/confirmation_closed"),
|
30 |
+
|
31 |
+
"callback_callcentre_number" => $form->getData("callback/number"),
|
32 |
+
"callback_dtmf_tunnel" => $form->getData("callback/dtmf"),
|
33 |
+
"call_centre_time_zone" => $form->getData("callback/time_zone"),
|
34 |
+
|
35 |
+
"monday_from" => $form->getData("callback/monday/from"),
|
36 |
+
"monday_to" => $form->getData("callback/monday/to"),
|
37 |
+
|
38 |
+
"tuesday_from" => $form->getData("callback/tuesday/from"),
|
39 |
+
"tuesday_to" => $form->getData("callback/tuesday/to"),
|
40 |
+
|
41 |
+
"wednesday_from" => $form->getData("callback/wednesday/from"),
|
42 |
+
"wednesday_to" => $form->getData("callback/wednesday/to"),
|
43 |
+
|
44 |
+
"thursday_from" => $form->getData("callback/thursday/from"),
|
45 |
+
"thursday_to" => $form->getData("callback/thursday/to"),
|
46 |
+
|
47 |
+
"friday_from" => $form->getData("callback/friday/from"),
|
48 |
+
"friday_to" => $form->getData("callback/friday/to"),
|
49 |
+
|
50 |
+
"saturday_from" => $form->getData("callback/saturday/from"),
|
51 |
+
"saturday_to" => $form->getData("callback/saturday/to"),
|
52 |
+
|
53 |
+
"sunday_from" => $form->getData("callback/sunday/from"),
|
54 |
+
"sunday_to" => $form->getData("callback/sunday/to"),
|
55 |
+
|
56 |
+
"bank_holiday_from" => $form->getData("callback/bank_holiday/from"),
|
57 |
+
"bank_holiday_to" => $form->getData("callback/bank_holiday/to"),
|
58 |
+
|
59 |
+
"display_on_all" => ($form->getData("published/all")) ? 1 : 0,
|
60 |
+
"display_on_pages" => ($form->getData("published/pages")) ? implode(",", $form->getData("published/pages")) : ""
|
61 |
+
));
|
62 |
+
}
|
63 |
+
}
|
app/code/community/Cloudiq/Callme/Helper/Options.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Helper_Options extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
const DAY_START_HOUR = 7;
|
6 |
+
const DAY_START_MINUTE = 0;
|
7 |
+
const DAY_END_HOUR = 23;
|
8 |
+
const DAY_END_MINUTE = 30;
|
9 |
+
const MINUTE_INCREMENT = 15;
|
10 |
+
|
11 |
+
public function getButtonPositionOptions() {
|
12 |
+
return array(
|
13 |
+
array("value" => "leftBottom", "label" => $this->__("Left Bottom")),
|
14 |
+
array("value" => "leftMiddle", "label" => $this->__("Left Middle")),
|
15 |
+
array("value" => "leftTop", "label" => $this->__("Left Top")),
|
16 |
+
array("value" => "topLeft", "label" => $this->__("Top Left")),
|
17 |
+
array("value" => "topMiddle", "label" => $this->__("Top Middle")),
|
18 |
+
array("value" => "topRight", "label" => $this->__("Top Right")),
|
19 |
+
array("value" => "rightTop", "label" => $this->__("Right Top")),
|
20 |
+
array("value" => "rightMiddle", "label" => $this->__("Right Middle")),
|
21 |
+
array("value" => "rightBottom", "label" => $this->__("Right Bottom")),
|
22 |
+
array("value" => "bottomRight", "label" => $this->__("Bottom Right")),
|
23 |
+
array("value" => "bottomMiddle", "label" => $this->__("Bottom Middle")),
|
24 |
+
array("value" => "bottomLeft", "label" => $this->__("Bottom Left")),
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getButtonTemplateOptions() {
|
29 |
+
return array(
|
30 |
+
array("value" => "1", "label" => $this->__("Squared corners no fill")),
|
31 |
+
array("value" => "2", "label" => $this->__("Squared corners with fill")),
|
32 |
+
array("value" => "3", "label" => $this->__("Lozenge with fill")),
|
33 |
+
array("value" => "4", "label" => $this->__("Rounded corners no fill")),
|
34 |
+
array("value" => "5", "label" => $this->__("Rounded corners with fill")),
|
35 |
+
);
|
36 |
+
}
|
37 |
+
|
38 |
+
public function getHoursOptions() {
|
39 |
+
$values = array();
|
40 |
+
|
41 |
+
$values[] = array("value" => "--", "label" => "--");
|
42 |
+
|
43 |
+
for ($i = self::DAY_START_HOUR; $i <= self::DAY_END_HOUR; $i++) {
|
44 |
+
for ($j = 0; $j < 60; $j = $j + self::MINUTE_INCREMENT) {
|
45 |
+
if (($i == self::DAY_START_HOUR && $j < self::DAY_START_MINUTE)
|
46 |
+
|| ($i == self::DAY_END_HOUR && $j > self::DAY_END_MINUTE)) {
|
47 |
+
continue;
|
48 |
+
}
|
49 |
+
$value = (($i < 10) ? "0" . $i : $i) . ":" . (($j < 10) ? "0" . $j : $j);
|
50 |
+
$values[] = array("value" => $value, "label" => $this->__($value));
|
51 |
+
}
|
52 |
+
}
|
53 |
+
return $values;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getPagesOptions() {
|
57 |
+
return array(
|
58 |
+
array("value" => "cms_index_index", "label" => $this->__("Home page")),
|
59 |
+
array("value" => "cms_page", "label" => $this->__("All CMS pages")),
|
60 |
+
array("value" => "catalog_category_view", "label" => $this->__("Category pages")),
|
61 |
+
array("value" => "catalog_product_view", "label" => $this->__("Product pages")),
|
62 |
+
array("value" => "catalogsearch_result_index", "label" => $this->__("Search page")),
|
63 |
+
array("value" => "checkout_cart_index", "label" => $this->__("Cart page")),
|
64 |
+
array("value" => "checkout_onepage_index", "label" => $this->__("Checkout page")),
|
65 |
+
array("value" => "customer_account", "label" => $this->__("Account Area pages")),
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getSalesCallOptions() {
|
70 |
+
return array(
|
71 |
+
array("value" => "1", "label" => $this->__("1 minutes")),
|
72 |
+
array("value" => "2", "label" => $this->__("2 minutes")),
|
73 |
+
array("value" => "3", "label" => $this->__("3 minutes")),
|
74 |
+
array("value" => "4", "label" => $this->__("4 minutes")),
|
75 |
+
array("value" => "5", "label" => $this->__("5 minutes or more")),
|
76 |
+
);
|
77 |
+
}
|
78 |
+
}
|
app/code/community/Cloudiq/Callme/Model/Api/Callme.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Model_Api_Callme extends Cloudiq_Core_Model_Api_Abstract {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Submit callMe configuration changes to the callMe API. Sends a request
|
7 |
+
* to the API with mode="store" and action="callMe". If the request results
|
8 |
+
* in a new app being created, the configuration model passed to
|
9 |
+
* the method will be updated with a new app ID, but not saved. Returns
|
10 |
+
* true if the action was successful or an array of error messages if it
|
11 |
+
* failed.
|
12 |
+
*
|
13 |
+
* @param Cloudiq_Callme_Model_Config &$config Configuration to submit to the API
|
14 |
+
* @return bool|array
|
15 |
+
*/
|
16 |
+
public function storeCallme(Cloudiq_Callme_Model_Config &$config) {
|
17 |
+
$parameters = $this->_convertConfigToParameters($config);
|
18 |
+
|
19 |
+
$parameters["mode"] = "store";
|
20 |
+
$parameters["action"] = "callme";
|
21 |
+
|
22 |
+
/** @var Cloudiq_Core_Model_Api_Request $request */
|
23 |
+
$request = $this->_getRequestObject()->setParameters($parameters);
|
24 |
+
|
25 |
+
$errors = array();
|
26 |
+
|
27 |
+
$response = $request->send(Zend_Http_Client::POST);
|
28 |
+
|
29 |
+
if ($response) {
|
30 |
+
if ($response->wasSuccessful()) {
|
31 |
+
$callme_response = $response->getResponse()->callMe;
|
32 |
+
|
33 |
+
if (!is_null($callme_response)) {
|
34 |
+
if ($callme_response['status'] == Cloudiq_Core_Model_Api_Response::STATUS_SUCCESS) {
|
35 |
+
// Successful callMe response, check if a new app ID was created
|
36 |
+
$app_id = (int) $callme_response->appId;
|
37 |
+
if (!is_null($app_id)) {
|
38 |
+
$config->setAppId($app_id);
|
39 |
+
}
|
40 |
+
} else {
|
41 |
+
// Unsuccessful callMe response, build an appropriate error message
|
42 |
+
$error_message = "Unsuccessful callMe response: " . $response->getApiStatusCodeDescription($callme_response['status']);
|
43 |
+
if ($callme_response->description) {
|
44 |
+
$error_message .= ": " . $callme_response->description;
|
45 |
+
}
|
46 |
+
$errors[] = $error_message;
|
47 |
+
}
|
48 |
+
} else {
|
49 |
+
$errors[] = "Unknown callMe response status.";
|
50 |
+
}
|
51 |
+
} else {
|
52 |
+
// Unsuccessful response
|
53 |
+
$errors[] = $response->getErrorMessage();
|
54 |
+
}
|
55 |
+
} else {
|
56 |
+
$errors[] = "Failed to connect to cloud.IQ API";
|
57 |
+
}
|
58 |
+
|
59 |
+
if (empty($errors)) {
|
60 |
+
return true;
|
61 |
+
}
|
62 |
+
return $errors;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Submit a callback request to the API. Returns an array with two elements:
|
67 |
+
* status - boolean flag, true if the callback request was successful, false otherwise
|
68 |
+
* message - response message or error message if the request was unsuccessful
|
69 |
+
*
|
70 |
+
* @param $app_id string The id of the app to assign the request to.
|
71 |
+
* @param $consumer_number string The phone number for the callback.
|
72 |
+
*
|
73 |
+
* @return array
|
74 |
+
*/
|
75 |
+
public function requestCallback($app_id, $consumer_number) {
|
76 |
+
$parameters = array(
|
77 |
+
"mode" => "send",
|
78 |
+
"action" => "callback",
|
79 |
+
"appId" => $app_id,
|
80 |
+
"consumerNumber" => $consumer_number,
|
81 |
+
"consumerIp" => Mage::helper("core/http")->getRemoteAddr()
|
82 |
+
);
|
83 |
+
|
84 |
+
$result = array(
|
85 |
+
"status" => false,
|
86 |
+
"message" => ""
|
87 |
+
);
|
88 |
+
|
89 |
+
$response = null;
|
90 |
+
$request = $this->_getRequestObject()->setParameters($parameters);
|
91 |
+
|
92 |
+
$response = $request->send(Zend_Http_Client::POST);
|
93 |
+
|
94 |
+
if ($response) {
|
95 |
+
if ($response->wasSuccessful()) {
|
96 |
+
$callback_response = $response->getResponse()->callback;
|
97 |
+
|
98 |
+
if (!is_null($callback_response)) {
|
99 |
+
if($callback_response['status'] == Cloudiq_Core_Model_Api_Response::STATUS_SUCCESS) {
|
100 |
+
// Successfully submitted a callback request, fetch the response message
|
101 |
+
$result["status"] = true;
|
102 |
+
$result["message"] = sprintf("%s", $callback_response->description);
|
103 |
+
} else {
|
104 |
+
// Unsuccessful callback response, fetch the error message
|
105 |
+
$result["message"] = $response->getApiStatusCodeDescription($callback_response['status']);
|
106 |
+
if ($callback_response->description) {
|
107 |
+
$result["message"] .= sprintf(": %s", $callback_response->description);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
} else {
|
112 |
+
// Unsuccessful response
|
113 |
+
$result["message"] = $response->getErrorMessage();
|
114 |
+
}
|
115 |
+
} else {
|
116 |
+
$result["message"] = "Failed to connect to cloud.IQ API";
|
117 |
+
}
|
118 |
+
|
119 |
+
return $result;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Convert Cloudiq_Callme_Model_Config into an array of parameters used by the API
|
124 |
+
*
|
125 |
+
* @param Cloudiq_Callme_Model_Config $config
|
126 |
+
* @return array
|
127 |
+
*/
|
128 |
+
protected function _convertConfigToParameters(Cloudiq_Callme_Model_Config $config) {
|
129 |
+
$parameters = $config->toCamelCaseArray();
|
130 |
+
|
131 |
+
// Remove parameters not used by the API
|
132 |
+
unset($parameters["id"],
|
133 |
+
$parameters["enabled"],
|
134 |
+
$parameters["displayOnAll"],
|
135 |
+
$parameters["displayOnPages"]
|
136 |
+
);
|
137 |
+
|
138 |
+
// Set constant parameters
|
139 |
+
// FIXME: Should only send the logo url to the API if it is enabled in the config
|
140 |
+
// but at the moment the API request fails if the logo is empty.
|
141 |
+
$parameters["popUpLogo"] = Mage::getDesign()->getSkinUrl(Mage::getStoreConfig('design/header/logo_src'), array("_area" => "frontend"));
|
142 |
+
|
143 |
+
// FIXME: New requirements say there should only be one set of opening hours per day, but the API still uses the period notation
|
144 |
+
$parameter_names = array_keys($parameters);
|
145 |
+
foreach ($parameter_names as $name) {
|
146 |
+
if (preg_match("/^(monday|tuesday|wednesday|thursday|friday|saturday|sunday|bankHoliday)(.*)$/", $name, $matches)) {
|
147 |
+
$new_name = $matches[1] . "Period1" . $matches[2];
|
148 |
+
$parameters[$new_name] = $parameters[$name];
|
149 |
+
unset($parameters[$name]);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
return $parameters;
|
154 |
+
}
|
155 |
+
}
|
app/code/community/Cloudiq/Callme/Model/Config.php
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Cloudiq_Callme_Model_Config
|
5 |
+
*
|
6 |
+
* @method bool getEnabled()
|
7 |
+
* @method bool getDisplayOnAll()
|
8 |
+
* @method string getDisplayOnPages()
|
9 |
+
*/
|
10 |
+
|
11 |
+
class Cloudiq_Callme_Model_Config extends Mage_Core_Model_Abstract {
|
12 |
+
|
13 |
+
protected $_helper;
|
14 |
+
|
15 |
+
protected function _construct() {
|
16 |
+
$this->_init('cloudiq_callme/config');
|
17 |
+
|
18 |
+
$this->_helper = Mage::helper("cloudiq_callme/options");
|
19 |
+
|
20 |
+
$this->load(1);
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Validate attribute values, returning true if all fields pass validation or
|
25 |
+
* a "field_name => message" array of error messages.
|
26 |
+
*
|
27 |
+
* @return bool|array
|
28 |
+
*/
|
29 |
+
public function validate() {
|
30 |
+
$errors = array();
|
31 |
+
|
32 |
+
// Enabled 0/1
|
33 |
+
if (!Zend_Validate::is($this->getEnabled(), "InArray", array("haystack" => array("0", "1")))) {
|
34 |
+
$errors["Enabled"] = "Enabled must be set to 0 or 1.";
|
35 |
+
}
|
36 |
+
|
37 |
+
// Average sales values must be present
|
38 |
+
if (!Zend_Validate::is(trim($this->getAverageSaleValue()), "NotEmpty")) {
|
39 |
+
$errors["AverageSaleValue"] = "Average sale value can not be empty.";
|
40 |
+
}
|
41 |
+
|
42 |
+
// Average sales call must match a set of values defined in the API
|
43 |
+
if (!Zend_Validate::is($this->getAverageSalesCall(), "InArray", array("haystack" => array_map(function ($el) { return $el["value"]; }, $this->_helper->getSalesCallOptions())))) {
|
44 |
+
$errors["AverageSalesCall"] = "Invalid average sales call value.";
|
45 |
+
}
|
46 |
+
|
47 |
+
// Button Position must match a set of values defined in the API
|
48 |
+
if (!Zend_Validate::is($this->getButtonPosition(), "InArray", array("haystack" => array_map(function ($el) { return $el["value"]; }, $this->_helper->getButtonPositionOptions())))) {
|
49 |
+
$errors["ButtonPosition"] = "Invalid button position value.";
|
50 |
+
}
|
51 |
+
|
52 |
+
// Button Template must match a set of values defined in the API
|
53 |
+
if (!Zend_Validate::is($this->getButtonTemplate(), "InArray", array("haystack" => array_map(function ($el) { return $el["value"]; }, $this->_helper->getButtonTemplateOptions())))) {
|
54 |
+
$errors["ButtonTemplate"] = "Invalid button template value.";
|
55 |
+
}
|
56 |
+
|
57 |
+
// Button Colour must be a hex colour definition
|
58 |
+
if (!Zend_Validate::is($this->getButtonColour(), "Regex", array("pattern" => "/^[0-9A-F]{6}$/i"))) {
|
59 |
+
$errors["ButtonColour"] = "Button colour must be a hex colour definition.";
|
60 |
+
}
|
61 |
+
|
62 |
+
// Button Heading is required
|
63 |
+
if (!Zend_Validate::is(trim($this->getButtonHeading()), "NotEmpty")) {
|
64 |
+
$errors["ButtonHeading"] = "Button heading can not be empty.";
|
65 |
+
}
|
66 |
+
|
67 |
+
// Button Message is required
|
68 |
+
if (!Zend_Validate::is(trim($this->getButtonMessage()), "NotEmpty")) {
|
69 |
+
$errors["ButtonMessage"] = "Button message can not be empty.";
|
70 |
+
}
|
71 |
+
|
72 |
+
// Pop up logo enabled/disabled
|
73 |
+
if (!Zend_Validate::is($this->getPopUpLogo(), "InArray", array("haystack" => array("0", "1")))) {
|
74 |
+
$errors["PopUpLogo"] = "Pop up logo must be set to 0 or 1.";
|
75 |
+
}
|
76 |
+
|
77 |
+
// Pop up title is required
|
78 |
+
if (!Zend_Validate::is(trim($this->getPopUpTitle()), "NotEmpty")) {
|
79 |
+
$errors["PopUpTitle"] = "Pop up title can not be empty.";
|
80 |
+
}
|
81 |
+
|
82 |
+
// Pop up strapline is required
|
83 |
+
if (!Zend_Validate::is(trim($this->getPopUpStrapline()), "NotEmpty")) {
|
84 |
+
$errors["PopUpStrapline"] = "Pop up strap line can not be empty.";
|
85 |
+
}
|
86 |
+
|
87 |
+
// Pop up confirmations are required
|
88 |
+
if (!Zend_Validate::is(trim($this->getPopUpConfOpen()), "NotEmpty")) {
|
89 |
+
$errors["PopUpConfOpen"] = "Pop up confirmation (open) can not be empty.";
|
90 |
+
}
|
91 |
+
if (!Zend_Validate::is(trim($this->getPopUpConfClosed()), "NotEmpty")) {
|
92 |
+
$errors["PopUpConfClosed"] = "Pop up confirmation (closed) can not be empty.";
|
93 |
+
}
|
94 |
+
|
95 |
+
// Callback phone number is required
|
96 |
+
if (!Zend_Validate::is(trim($this->getCallbackCallcentreNumber()), "NotEmpty")) {
|
97 |
+
$errors["CallbackCallcentreNumber"] = "Callback telephone number can not be empty.";
|
98 |
+
}
|
99 |
+
|
100 |
+
// DTMF Tunnel is numeric
|
101 |
+
if (Zend_Validate::is(trim($this->getCallbackDtmfTunnel()), "NotEmpty") && !Zend_Validate::is(trim($this->getCallbackDtmfTunnel()), "Int")) {
|
102 |
+
$errors["CallbackDtmfTunnel"] = "Callback DTMF tunnel can only contain numbers.";
|
103 |
+
}
|
104 |
+
|
105 |
+
// Call centre time zone must match one of the provided options
|
106 |
+
if (!Zend_Validate::is(trim($this->getCallCentreTimeZone()), "InArray", array("haystack" => array_map(function ($el) { return $el["value"]; }, Mage::getSingleton("adminhtml/system_config_source_locale_timezone")->toOptionArray())))) {
|
107 |
+
$errors["CallCentreTimeZone"] = "Invalid call centre time zone value.";
|
108 |
+
}
|
109 |
+
|
110 |
+
// All values in Opening Hours must be times
|
111 |
+
foreach (array("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday", "bank_holiday") as $day) {
|
112 |
+
$openhours_errors = 0;
|
113 |
+
foreach (array("from", "to") as $period) {
|
114 |
+
$value = $this->getData($day . "_" . $period);
|
115 |
+
if ($value !== "--" && !Zend_Validate::is($value, "Regex", array("pattern" => "/^\d{2}:\d{2}$/"))) {
|
116 |
+
$openhours_errors++;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
if ($openhours_errors > 0) {
|
120 |
+
$errors[$day] = sprintf("%s Open Hours fields must contain a time value.", ucfirst($day));
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
// Display pages values must match a defined set or be empty
|
125 |
+
if (trim($this->getDisplayOnPages()) != "") {
|
126 |
+
$displaypages_errors = 0;
|
127 |
+
foreach (explode(",",$this->getDisplayOnPages()) as $page) {
|
128 |
+
if (!Zend_Validate::is($page, "InArray", array("haystack" => array_map(function ($el) { return $el["value"]; }, $this->_helper->getPagesOptions())))) {
|
129 |
+
$displaypages_errors++;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
if ($displaypages_errors > 0) {
|
133 |
+
$errors["DisplayOnPages"] = '"Display on selected pages" contains invalid values.';
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
if (empty($errors)) {
|
138 |
+
return true;
|
139 |
+
}
|
140 |
+
return $errors;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Convert object attributes to an array with camelCase names
|
145 |
+
*
|
146 |
+
* @param array $attributes array of required attributes
|
147 |
+
* @return array
|
148 |
+
*/
|
149 |
+
public function toCamelCaseArray(array $attributes = array()) {
|
150 |
+
$data = $this->__toArray($attributes);
|
151 |
+
$camelData = array();
|
152 |
+
foreach ($data as $key => $value) {
|
153 |
+
$camelData[lcfirst($this->_camelize($key))] = $value;
|
154 |
+
}
|
155 |
+
return $camelData;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Check if the module is enabled and has been configured.
|
160 |
+
*
|
161 |
+
* @return bool
|
162 |
+
*/
|
163 |
+
public function isConfigured() {
|
164 |
+
$core_helper = Mage::helper("cloudiq_core/config");
|
165 |
+
|
166 |
+
return ($core_helper->isEnabled() && $core_helper->hasBeenSetUp() && $this->getEnabled() && !is_null($this->getAppId()));
|
167 |
+
}
|
168 |
+
}
|
app/code/community/Cloudiq/Callme/Model/Observer.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Model_Observer extends Varien_Object {
|
4 |
+
|
5 |
+
public function observeCloudiqCoreConfigSave($observer) {
|
6 |
+
$request = $observer->getRequest();
|
7 |
+
|
8 |
+
|
9 |
+
/** @var $helper Cloudiq_Callme_Helper_Data */
|
10 |
+
$helper = Mage::helper("cloudiq_callme");
|
11 |
+
|
12 |
+
/** @var $config_model Cloudiq_Callme_Model_Config */
|
13 |
+
$config_model = Mage::getModel("cloudiq_callme/config");
|
14 |
+
|
15 |
+
$form_data = new Varien_Object($request->getParam("callme"));
|
16 |
+
|
17 |
+
if (count($form_data->getData()) == 0) {
|
18 |
+
// Don't save the config model if the callMe tab was not present
|
19 |
+
return;
|
20 |
+
}
|
21 |
+
|
22 |
+
// Save form data in the admin session to repopulate the form in case of errors while saving
|
23 |
+
Mage::getSingleton("adminhtml/session")->setData("callme_form_data", $form_data);
|
24 |
+
|
25 |
+
$helper->updateConfigFromForm($config_model, $form_data);
|
26 |
+
|
27 |
+
// Validate the data, show an error for each field that doesn't pass
|
28 |
+
$result = $config_model->validate();
|
29 |
+
if (is_array($result)) {
|
30 |
+
foreach($result as $field => $message) {
|
31 |
+
Mage::getSingleton("adminhtml/session")->addError($helper->__("callMe: " . $message));
|
32 |
+
}
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
// Submit the config changes to the API
|
37 |
+
$api = Mage::getModel("cloudiq_callme/api_callme");
|
38 |
+
$api_result = $api->storeCallme($config_model);
|
39 |
+
if (is_array($api_result)) {
|
40 |
+
foreach ($api_result as $message) {
|
41 |
+
Mage::getSingleton("adminhtml/session")->addError($helper->__("callMe API error: " . $message));
|
42 |
+
}
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
|
46 |
+
$config_model->save();
|
47 |
+
Mage::getSingleton("adminhtml/session")->addSuccess($helper->__("callMe: Configuration saved."));
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Insert our callMe block if we are on the correct layout handle.
|
52 |
+
*
|
53 |
+
* @param Varien_Event_Observer $observer
|
54 |
+
*/
|
55 |
+
public function observeControllerActionLayoutGenerateBlocksAfter(Varien_Event_Observer $observer) {
|
56 |
+
/** @var Mage_Core_Model_Layout $layout */
|
57 |
+
$layout = Mage::app()->getLayout();
|
58 |
+
|
59 |
+
if ($layout->getArea() != Mage_Core_Model_App_Area::AREA_FRONTEND) {
|
60 |
+
return;
|
61 |
+
}
|
62 |
+
|
63 |
+
/** @var array $layout_handles */
|
64 |
+
$layout_handles = $layout->getUpdate()->getHandles();
|
65 |
+
|
66 |
+
/** @var Cloudiq_Callme_Model_Config $callme_config */
|
67 |
+
$callme_config = Mage::getModel('cloudiq_callme/config');
|
68 |
+
|
69 |
+
/** @var Cloudiq_Core_Helper_Config $core_helper */
|
70 |
+
$core_helper = Mage::helper('cloudiq_core/config');
|
71 |
+
|
72 |
+
$core_enabled = $core_helper->hasBeenSetUp() && $core_helper->isEnabled();
|
73 |
+
|
74 |
+
if (!$core_enabled || !$callme_config->isConfigured()) {
|
75 |
+
return;
|
76 |
+
}
|
77 |
+
|
78 |
+
$callme_handles = explode(',', $callme_config->getDisplayOnPages());
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Only render the block if we've checked the "Display on all pages" checkbox, or at least one of our current
|
82 |
+
* page handles matches the configured handles.
|
83 |
+
*/
|
84 |
+
$should_render_block = (
|
85 |
+
$callme_config->getDisplayOnAll() ||
|
86 |
+
count(array_intersect($callme_handles, $layout_handles)) > 0
|
87 |
+
);
|
88 |
+
|
89 |
+
if ($should_render_block) {
|
90 |
+
// TODO: convert this into a layout update that gets applied through a handle
|
91 |
+
$callme_block = $layout->createBlock('cloudiq_callme/button', 'cloudiq_callme.button_js');
|
92 |
+
$layout->getBlock('before_body_end')->insert($callme_block);
|
93 |
+
$layout->getBlock('head')->addItem("skin_css", "cloudiq/css/callme-button.css");
|
94 |
+
$layout->getBlock('head')->addItem("js", "cloudiq/callme-button.js");
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
app/code/community/Cloudiq/Callme/Model/Resource/Config.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Model_Resource_Config extends Mage_Core_Model_Mysql4_Abstract {
|
4 |
+
|
5 |
+
protected function _construct() {
|
6 |
+
$this->_init('cloudiq_callme/config', 'id');
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Cloudiq/Callme/Model/Resource/Config/Collection.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Model_Resource_Config_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
|
4 |
+
protected function _construct() {
|
5 |
+
$this->_init('cloudiq_callme/config');
|
6 |
+
}
|
7 |
+
}
|
app/code/community/Cloudiq/Callme/Test/Config/Base.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Callme_Test_Config_Base extends EcomDev_PHPUnit_Test_Case_Config {
|
3 |
+
/**
|
4 |
+
* @test
|
5 |
+
*/
|
6 |
+
public function testBasicConfiguration() {
|
7 |
+
$this->assertModuleCodePool('community');
|
8 |
+
$this->assertModuleVersion('1.0.0');
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @test
|
13 |
+
*/
|
14 |
+
public function testClassAliases() {
|
15 |
+
$this->assertHelperAlias('cloudiq_callme', 'Cloudiq_Callme_Helper_Data');
|
16 |
+
$this->assertModelAlias('cloudiq_callme/test', 'Cloudiq_Callme_Model_Test');
|
17 |
+
$this->assertBlockAlias('cloudiq_callme/test', 'Cloudiq_Callme_Block_Test');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @test
|
22 |
+
*/
|
23 |
+
public function testDataHelperExists() {
|
24 |
+
$this->assertInstanceOf('Cloudiq_Callme_Helper_Data', Mage::helper('cloudiq_callme'));
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Cloudiq/Callme/Test/Controller/Block.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Test_Controller_Block extends EcomDev_PHPUnit_Test_Case_Controller {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*
|
8 |
+
* @loadFixture
|
9 |
+
* @dataProvider dataProvider
|
10 |
+
*/
|
11 |
+
public function testDisplayOnAllPages($path, $handle) {
|
12 |
+
$this->dispatch($path);
|
13 |
+
$this->assertModuleConfigured();
|
14 |
+
$this->assertLayoutHandleLoaded($handle);
|
15 |
+
$this->assertLayoutBlockRendered('cloudiq_callme.button_js');
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @test
|
20 |
+
*
|
21 |
+
* @loadFixture
|
22 |
+
*/
|
23 |
+
public function testCallmeDisabled() {
|
24 |
+
$this->dispatch('');
|
25 |
+
$this->assertModuleConfigured();
|
26 |
+
$this->assertLayoutHandleLoaded('cms_index_index');
|
27 |
+
$this->assertLayoutBlockNotRendered('cloudiq_callme.button_js');
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @test
|
32 |
+
*
|
33 |
+
* @loadFixture
|
34 |
+
*/
|
35 |
+
public function testCoreDisabled() {
|
36 |
+
$this->dispatch('');
|
37 |
+
$this->assertModuleConfigured();
|
38 |
+
$this->assertLayoutHandleLoaded('cms_index_index');
|
39 |
+
$this->assertLayoutBlockNotRendered('cloudiq_callme.button_js');
|
40 |
+
}
|
41 |
+
|
42 |
+
public function assertModuleConfigured() {
|
43 |
+
$this->assertNotNull(Mage::helper('cloudiq_core/config')->isEnabled(), 'Expected core module to be set');
|
44 |
+
$this->assertTrue(Mage::helper('cloudiq_core/config')->hasBeenSetUp(), 'Expected core module to be setup correctly');
|
45 |
+
}
|
46 |
+
}
|
app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testCallmeDisabled.yaml
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/cloudiq_core/global/account_id: 123
|
3 |
+
default/cloudiq_core/global/token: 123
|
4 |
+
default/cloudiq_core/global/enabled: 1
|
5 |
+
tables:
|
6 |
+
cloudiq_callme/config:
|
7 |
+
-
|
8 |
+
id: 1
|
9 |
+
app_id: 123
|
10 |
+
enabled: 0
|
11 |
+
average_sale_value: 1.00
|
12 |
+
average_sales_call: 3
|
13 |
+
button_position: "leftBottom"
|
14 |
+
button_template: "1"
|
15 |
+
button_colour: "FFFFFF"
|
16 |
+
button_heading: 1
|
17 |
+
button_message: 1
|
18 |
+
pop_up_logo: "http://test"
|
19 |
+
pop_up_title: 1
|
20 |
+
pop_up_strapline: 1
|
21 |
+
pop_up_conf_open: 1
|
22 |
+
pop_up_conf_closed: 1
|
23 |
+
callback_callcentre_number: 1
|
24 |
+
callback_dtmf_tunnel: 1
|
25 |
+
call_centre_time_zone: "Europe/London"
|
26 |
+
monday_from: "00:00"
|
27 |
+
monday_to: "00:00"
|
28 |
+
tuesday_from: "00:00"
|
29 |
+
tuesday_to: "00:00"
|
30 |
+
wednesday_from: "00:00"
|
31 |
+
wednesday_to: "00:00"
|
32 |
+
thursday_from: "00:00"
|
33 |
+
thursday_to: "00:00"
|
34 |
+
friday_from: "00:00"
|
35 |
+
friday_to: "00:00"
|
36 |
+
saturday_from: "00:00"
|
37 |
+
saturday_to: "00:00"
|
38 |
+
sunday_from: "00:00"
|
39 |
+
sunday_to: "00:00"
|
40 |
+
bank_holiday_from: "00:00"
|
41 |
+
bank_holiday_to: "00:00"
|
42 |
+
display_on_all: 1
|
43 |
+
display_on_pages: ""
|
app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testCoreDisabled.yaml
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/cloudiq_core/global/account_id: 123
|
3 |
+
default/cloudiq_core/global/token: 123
|
4 |
+
default/cloudiq_core/global/enabled: 0
|
5 |
+
tables:
|
6 |
+
cloudiq_callme/config:
|
7 |
+
-
|
8 |
+
id: 1
|
9 |
+
app_id: 123
|
10 |
+
enabled: 1
|
11 |
+
average_sale_value: 1.00
|
12 |
+
average_sales_call: 3
|
13 |
+
button_position: "leftBottom"
|
14 |
+
button_template: "1"
|
15 |
+
button_colour: "FFFFFF"
|
16 |
+
button_heading: 1
|
17 |
+
button_message: 1
|
18 |
+
pop_up_logo: "http://test"
|
19 |
+
pop_up_title: 1
|
20 |
+
pop_up_strapline: 1
|
21 |
+
pop_up_conf_open: 1
|
22 |
+
pop_up_conf_closed: 1
|
23 |
+
callback_callcentre_number: 1
|
24 |
+
callback_dtmf_tunnel: 1
|
25 |
+
call_centre_time_zone: "Europe/London"
|
26 |
+
monday_from: "00:00"
|
27 |
+
monday_to: "00:00"
|
28 |
+
tuesday_from: "00:00"
|
29 |
+
tuesday_to: "00:00"
|
30 |
+
wednesday_from: "00:00"
|
31 |
+
wednesday_to: "00:00"
|
32 |
+
thursday_from: "00:00"
|
33 |
+
thursday_to: "00:00"
|
34 |
+
friday_from: "00:00"
|
35 |
+
friday_to: "00:00"
|
36 |
+
saturday_from: "00:00"
|
37 |
+
saturday_to: "00:00"
|
38 |
+
sunday_from: "00:00"
|
39 |
+
sunday_to: "00:00"
|
40 |
+
bank_holiday_from: "00:00"
|
41 |
+
bank_holiday_to: "00:00"
|
42 |
+
display_on_all: 1
|
43 |
+
display_on_pages: ""
|
app/code/community/Cloudiq/Callme/Test/Controller/Block/fixtures/testDisplayOnAllPages.yaml
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/cloudiq_core/global/account_id: 123
|
3 |
+
default/cloudiq_core/global/token: 123
|
4 |
+
default/cloudiq_core/global/enabled: 1
|
5 |
+
tables:
|
6 |
+
cloudiq_callme/config:
|
7 |
+
-
|
8 |
+
id: 1
|
9 |
+
app_id: 123
|
10 |
+
enabled: 1
|
11 |
+
button_position: "leftBottom"
|
12 |
+
button_template: "1"
|
13 |
+
button_colour: "FFFFFF"
|
14 |
+
button_heading: 1
|
15 |
+
button_message: 1
|
16 |
+
pop_up_logo: "http://test"
|
17 |
+
pop_up_title: 1
|
18 |
+
pop_up_strapline: 1
|
19 |
+
pop_up_conf_open: 1
|
20 |
+
pop_up_conf_closed: 1
|
21 |
+
callback_callcentre_number: 1
|
22 |
+
callback_dtmf_tunnel: 1
|
23 |
+
call_centre_time_zone: "Europe/London"
|
24 |
+
monday_from: "00:00"
|
25 |
+
monday_to: "00:00"
|
26 |
+
tuesday_from: "00:00"
|
27 |
+
tuesday_to: "00:00"
|
28 |
+
wednesday_from: "00:00"
|
29 |
+
wednesday_to: "00:00"
|
30 |
+
thursday_from: "00:00"
|
31 |
+
thursday_to: "00:00"
|
32 |
+
friday_from: "00:00"
|
33 |
+
friday_to: "00:00"
|
34 |
+
saturday_from: "00:00"
|
35 |
+
saturday_to: "00:00"
|
36 |
+
sunday_from: "00:00"
|
37 |
+
sunday_to: "00:00"
|
38 |
+
bank_holiday_from: "00:00"
|
39 |
+
bank_holiday_to: "00:00"
|
40 |
+
display_on_all: 1
|
41 |
+
display_on_pages: ""
|
app/code/community/Cloudiq/Callme/Test/Controller/Block/providers/testDisplayOnAllPages.yaml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
path: ''
|
3 |
+
handle: cms_index_index
|
app/code/community/Cloudiq/Callme/Test/Helper/Options.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Test_Helper_Options extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
/** @var Cloudiq_Callme_Helper_Options */
|
5 |
+
protected $_helper;
|
6 |
+
|
7 |
+
protected function setUp() {
|
8 |
+
parent::setUp();
|
9 |
+
|
10 |
+
$this->_helper = Mage::helper('cloudiq_callme/options');
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function tearDown() {
|
14 |
+
$this->_helper = null;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @test
|
19 |
+
*/
|
20 |
+
public function testClassConstruction() {
|
21 |
+
$this->assertInstanceOf('Cloudiq_Callme_Helper_Options', $this->_helper);
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @test
|
26 |
+
*/
|
27 |
+
public function testGetButtonPositionOptionsValidSourceModel() {
|
28 |
+
$this->_assertValidSourceModel($this->_helper->getButtonPositionOptions());
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @test
|
33 |
+
*/
|
34 |
+
public function testGetButtonTemplateOptionsValidSourceModel() {
|
35 |
+
$this->_assertValidSourceModel($this->_helper->getButtonTemplateOptions());
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @test
|
40 |
+
*/
|
41 |
+
public function testGetHoursOptionsValidSourceModel() {
|
42 |
+
$this->_assertValidSourceModel($this->_helper->getHoursOptions());
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @test
|
47 |
+
*/
|
48 |
+
public function testGetPagesOptionsValidSourceModel() {
|
49 |
+
$this->_assertValidSourceModel($this->_helper->getPagesOptions());
|
50 |
+
}
|
51 |
+
|
52 |
+
protected function _assertValidSourceModel($array) {
|
53 |
+
$this->assertTrue(is_array($array));
|
54 |
+
$this->assertTrue(count($array) > 0);
|
55 |
+
|
56 |
+
foreach ($array as $child) {
|
57 |
+
$this->assertArrayHasKey('label', $child);
|
58 |
+
$this->assertArrayHasKey('value', $child);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
app/code/community/Cloudiq/Callme/Test/Model/Config.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Test_Model_Config extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/** @var Cloudiq_Callme_Model_Config */
|
6 |
+
protected $_model;
|
7 |
+
|
8 |
+
protected function setUp() {
|
9 |
+
parent::setUp();
|
10 |
+
|
11 |
+
$this->_model = Mage::getModel('cloudiq_callme/config');
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function tearDown() {
|
15 |
+
$this->_model = null;
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @test
|
20 |
+
*/
|
21 |
+
public function testClassConstruction() {
|
22 |
+
$this->assertInstanceOf('Cloudiq_Callme_Model_Config', $this->_model);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @test
|
27 |
+
* @loadFixture validConfigObject.yaml
|
28 |
+
*/
|
29 |
+
public function testModelIsLoadedAfterConstruct() {
|
30 |
+
/**
|
31 |
+
* Test the fixture loaded
|
32 |
+
*/
|
33 |
+
$this->assertGreaterThan(0, $this->_model->getCollection()->count());
|
34 |
+
|
35 |
+
$this->assertEquals(1, $this->_model->getId());
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @test
|
40 |
+
* @depends testModelIsLoadedAfterConstruct
|
41 |
+
* @loadFixture validConfigObject.yaml
|
42 |
+
*/
|
43 |
+
public function testFixtureIsValid() {
|
44 |
+
$this->assertTrue($this->_model->validate());
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @test
|
49 |
+
* @depends testFixtureIsValid
|
50 |
+
* @dataProvider dataProviderSingleValue
|
51 |
+
* @loadFixture validConfigObject.yaml
|
52 |
+
*/
|
53 |
+
public function testRequiredField($fieldname) {
|
54 |
+
$this->_model->unsetData($fieldname);
|
55 |
+
|
56 |
+
$validation_result = $this->_model->validate();
|
57 |
+
|
58 |
+
$this->assertThat($validation_result, $this->logicalNot($this->equalTo(true)));
|
59 |
+
$this->assertTrue(is_array($validation_result));
|
60 |
+
$this->assertEquals(1, count($validation_result));
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @test
|
65 |
+
* @depends testFixtureIsValid
|
66 |
+
* @dataProvider dataProviderSingleValue
|
67 |
+
* @loadFixture validConfigObject.yaml
|
68 |
+
*/
|
69 |
+
public function testOptionalField($fieldname) {
|
70 |
+
$this->_model->unsetData($fieldname);
|
71 |
+
|
72 |
+
$validation_result = $this->_model->validate();
|
73 |
+
|
74 |
+
$this->assertTrue($validation_result);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* The standard dataProvider requires an array of arrays in the yaml file. This data provider allows us to just
|
79 |
+
* use an array and, therefore, assumes that the test method using this dataProviderSingleValue accepts only one
|
80 |
+
* argument.
|
81 |
+
*
|
82 |
+
* @param $testname
|
83 |
+
* @return array
|
84 |
+
*/
|
85 |
+
public function dataProviderSingleValue($testname) {
|
86 |
+
$raw_data = parent::dataProvider($testname);
|
87 |
+
$data = array();
|
88 |
+
|
89 |
+
foreach ($raw_data as $item) {
|
90 |
+
$data[] = array(
|
91 |
+
$item
|
92 |
+
);
|
93 |
+
}
|
94 |
+
|
95 |
+
return $data;
|
96 |
+
}
|
97 |
+
}
|
app/code/community/Cloudiq/Callme/Test/Model/Config/fixtures/validConfigObject.yaml
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
tables:
|
2 |
+
cloudiq_callme/config:
|
3 |
+
-
|
4 |
+
id: 1
|
5 |
+
enabled: 1
|
6 |
+
average_sale_value: 1.00
|
7 |
+
average_sales_call: 3
|
8 |
+
button_position: "leftBottom"
|
9 |
+
button_template: "1"
|
10 |
+
button_colour: "FFFFFF"
|
11 |
+
button_heading: 1
|
12 |
+
button_message: 1
|
13 |
+
pop_up_logo: 1
|
14 |
+
pop_up_title: 1
|
15 |
+
pop_up_strapline: 1
|
16 |
+
pop_up_conf_open: 1
|
17 |
+
pop_up_conf_closed: 1
|
18 |
+
callback_callcentre_number: 1
|
19 |
+
callback_dtmf_tunnel: 1
|
20 |
+
call_centre_time_zone: "Europe/London"
|
21 |
+
monday_from: "00:00"
|
22 |
+
monday_to: "00:00"
|
23 |
+
tuesday_from: "00:00"
|
24 |
+
tuesday_to: "00:00"
|
25 |
+
wednesday_from: "00:00"
|
26 |
+
wednesday_to: "00:00"
|
27 |
+
thursday_from: "00:00"
|
28 |
+
thursday_to: "00:00"
|
29 |
+
friday_from: "00:00"
|
30 |
+
friday_to: "00:00"
|
31 |
+
saturday_from: "00:00"
|
32 |
+
saturday_to: "00:00"
|
33 |
+
sunday_from: "00:00"
|
34 |
+
sunday_to: "00:00"
|
35 |
+
bank_holiday_from: "00:00"
|
36 |
+
bank_holiday_to: "00:00"
|
37 |
+
display_on_all: 1
|
38 |
+
display_on_pages: "cms_index_index,cms_page"
|
app/code/community/Cloudiq/Callme/Test/Model/Config/providers/testOptionalField.yaml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
- callback_dtmf_tunnel
|
2 |
+
- display_on_all
|
3 |
+
- display_on_pages
|
app/code/community/Cloudiq/Callme/Test/Model/Config/providers/testRequiredField.yaml
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
- enabled
|
2 |
+
- average_sale_value
|
3 |
+
- average_sales_call
|
4 |
+
- button_position
|
5 |
+
- button_template
|
6 |
+
- button_colour
|
7 |
+
- button_heading
|
8 |
+
- button_message
|
9 |
+
- pop_up_logo
|
10 |
+
- pop_up_title
|
11 |
+
- pop_up_strapline
|
12 |
+
- pop_up_conf_open
|
13 |
+
- pop_up_conf_closed
|
14 |
+
- callback_callcentre_number
|
15 |
+
#- callback_dtmf_tunnel
|
16 |
+
- call_centre_time_zone
|
17 |
+
- monday_from
|
18 |
+
- monday_to
|
19 |
+
- tuesday_from
|
20 |
+
- tuesday_to
|
21 |
+
- wednesday_from
|
22 |
+
- wednesday_to
|
23 |
+
- thursday_from
|
24 |
+
- thursday_to
|
25 |
+
- friday_from
|
26 |
+
- friday_to
|
27 |
+
- saturday_from
|
28 |
+
- saturday_to
|
29 |
+
- sunday_from
|
30 |
+
- sunday_to
|
31 |
+
- bank_holiday_from
|
32 |
+
- bank_holiday_to
|
33 |
+
#- display_on_all
|
34 |
+
#- display_on_pages
|
app/code/community/Cloudiq/Callme/Varien/Data/Form/Element/Colourpicker.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Callme_Varien_Data_Form_Element_Colourpicker extends Varien_Data_Form_Element_Abstract {
|
3 |
+
|
4 |
+
public function __construct($attributes=array()) {
|
5 |
+
parent::__construct($attributes);
|
6 |
+
$this->setType('colourpicker');
|
7 |
+
}
|
8 |
+
|
9 |
+
public function getElementHtml() {
|
10 |
+
$html = sprintf('<input id="%s" name="%s" class="color input-text" value="%s"/>',
|
11 |
+
$this->getHtmlId(),
|
12 |
+
$this->getName(),
|
13 |
+
$this->getEscapedValue()
|
14 |
+
);
|
15 |
+
return $html;
|
16 |
+
}
|
17 |
+
|
18 |
+
|
19 |
+
}
|
app/code/community/Cloudiq/Callme/Varien/Data/Form/Element/Openinghours.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_Varien_Data_Form_Element_Openinghours extends Varien_Data_Form_Element_Abstract {
|
4 |
+
|
5 |
+
protected $_helper;
|
6 |
+
|
7 |
+
public function __construct($attributes = array()) {
|
8 |
+
parent::__construct($attributes);
|
9 |
+
$this->setType("openinghours");
|
10 |
+
|
11 |
+
$this->_helper = Mage::helper("cloudiq_callme/options");
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getElementHtml() {
|
15 |
+
$parts = array("from", "to");
|
16 |
+
$values = $this->getValue();
|
17 |
+
|
18 |
+
$this->addClass("opening_hours_select");
|
19 |
+
$html = '<div id="' . $this->getHtmlId() . '" ' . $this->serialize($this->getHtmlAttributes()) . '>' . "\n";
|
20 |
+
|
21 |
+
for ($i = 0; $i < count($parts); $i++) {
|
22 |
+
$name = $this->getName() . "[" . $parts[$i] . "]";
|
23 |
+
$html .= $this->_helper->__($parts[$i]);
|
24 |
+
$html .= $this->getSelectHtml($name, $this->_helper->getHoursOptions(), $values[$i]);
|
25 |
+
}
|
26 |
+
|
27 |
+
$html .= "</div>\n";
|
28 |
+
$html .= $this->getAfterElementHtml();
|
29 |
+
return $html;
|
30 |
+
}
|
31 |
+
|
32 |
+
protected function getSelectHtml($name, $values, $selected) {
|
33 |
+
$html = '<select name="' . $name . '">' . "\n";
|
34 |
+
foreach ($values as $value) {
|
35 |
+
$html .= '<option value="' . $value["value"] . '"' . (($value["value"] == $selected) ? ' selected="selected"' : '') . '>';
|
36 |
+
$html .= $this->_helper->__($value["label"]);
|
37 |
+
$html .= "</option>\n";
|
38 |
+
}
|
39 |
+
$html .= "</select>\n";
|
40 |
+
return $html;
|
41 |
+
}
|
42 |
+
}
|
app/code/community/Cloudiq/Callme/controllers/Adminhtml/CallmeController.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Cloudiq_Callme_Adminhtml_CallmeController
|
4 |
+
*
|
5 |
+
* @package Cloudiq_Callme
|
6 |
+
* @author Meanbee <hello@meanbee.com>
|
7 |
+
*/
|
8 |
+
class Cloudiq_Callme_Adminhtml_CallmeController extends Mage_Adminhtml_Controller_Action {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Generate and display a preview of the callMe button from the submitted data.
|
12 |
+
* Returns only the button specific, incomplete html as this action is meant to
|
13 |
+
* be requested through AJAX.
|
14 |
+
*/
|
15 |
+
public function previewAction() {
|
16 |
+
$helper = Mage::helper("cloudiq_callme");
|
17 |
+
|
18 |
+
$form = new Varien_Object($this->getRequest()->getParam("callme"));
|
19 |
+
|
20 |
+
// Only display the button if config data has been submitted
|
21 |
+
if (count($form->getData()) == 0) {
|
22 |
+
return;
|
23 |
+
}
|
24 |
+
|
25 |
+
$config = new Varien_Object();
|
26 |
+
$helper->updateConfigFromForm($config, $form);
|
27 |
+
|
28 |
+
/** @var $button Cloudiq_Callme_Block_Button */
|
29 |
+
$button = Mage::app()->getLayout()->createBlock("cloudiq_callme/button", "cloudiq_callme.button");
|
30 |
+
$button->setConfig($config);
|
31 |
+
$button->setDisabled(true);
|
32 |
+
|
33 |
+
$this->getResponse()->setBody($button->toHtml());
|
34 |
+
}
|
35 |
+
}
|
app/code/community/Cloudiq/Callme/controllers/CallmeController.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Callme_CallmeController extends Mage_Core_Controller_Front_Action {
|
4 |
+
public function requestAction() {
|
5 |
+
/** @var Cloudiq_Callme_Model_Config $_config_model */
|
6 |
+
$_config_model = Mage::getModel("cloudiq_callme/config");
|
7 |
+
|
8 |
+
$result = array(
|
9 |
+
"status" => false,
|
10 |
+
"message" => "Request status unknown"
|
11 |
+
);
|
12 |
+
|
13 |
+
if ($_config_model->isConfigured()) {
|
14 |
+
$phone_number = $this->getRequest()->getParam("phone_number");
|
15 |
+
if (!empty($phone_number)) {
|
16 |
+
$app_id = $_config_model->getAppId();
|
17 |
+
|
18 |
+
$api_result = Mage::getModel("cloudiq_callme/api_callme")->requestCallback($app_id, $phone_number);
|
19 |
+
|
20 |
+
if (is_array($api_result) && is_bool($api_result["status"])) {
|
21 |
+
$result = $api_result;
|
22 |
+
} else {
|
23 |
+
$result["message"] = "API call result unknown";
|
24 |
+
}
|
25 |
+
} else {
|
26 |
+
$result["message"] = "Must specify a phone number to call";
|
27 |
+
}
|
28 |
+
} else {
|
29 |
+
$result["message"] = "callMe module is not available";
|
30 |
+
}
|
31 |
+
|
32 |
+
$this->getResponse()
|
33 |
+
->setHeader('Content-type', 'application/json')
|
34 |
+
->setBody(Zend_Json::encode($result));
|
35 |
+
}
|
36 |
+
}
|
app/code/community/Cloudiq/Callme/etc/config.xml
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
|
4 |
+
<modules>
|
5 |
+
<Cloudiq_Callme>
|
6 |
+
<version>1.0.0</version>
|
7 |
+
</Cloudiq_Callme>
|
8 |
+
</modules>
|
9 |
+
|
10 |
+
<global>
|
11 |
+
<blocks>
|
12 |
+
<cloudiq_callme>
|
13 |
+
<class>Cloudiq_Callme_Block</class>
|
14 |
+
</cloudiq_callme>
|
15 |
+
</blocks>
|
16 |
+
<models>
|
17 |
+
<cloudiq_callme>
|
18 |
+
<class>Cloudiq_Callme_Model</class>
|
19 |
+
<resourceModel>cloudiq_callme_resource</resourceModel>
|
20 |
+
</cloudiq_callme>
|
21 |
+
<cloudiq_callme_resource>
|
22 |
+
<class>Cloudiq_Callme_Model_Resource</class>
|
23 |
+
<entities>
|
24 |
+
<config>
|
25 |
+
<table>cloudiq_callme_config</table>
|
26 |
+
</config>
|
27 |
+
</entities>
|
28 |
+
</cloudiq_callme_resource>
|
29 |
+
</models>
|
30 |
+
<helpers>
|
31 |
+
<cloudiq_callme>
|
32 |
+
<class>Cloudiq_Callme_Helper</class>
|
33 |
+
</cloudiq_callme>
|
34 |
+
</helpers>
|
35 |
+
<resources>
|
36 |
+
<cloudiq_callme_setup>
|
37 |
+
<setup>
|
38 |
+
<module>Cloudiq_Callme</module>
|
39 |
+
</setup>
|
40 |
+
</cloudiq_callme_setup>
|
41 |
+
</resources>
|
42 |
+
<events>
|
43 |
+
<cloudiq_core_config_save>
|
44 |
+
<observers>
|
45 |
+
<cloudiq_callme>
|
46 |
+
<type>singleton</type>
|
47 |
+
<class>cloudiq_callme/observer</class>
|
48 |
+
<method>observeCloudiqCoreConfigSave</method>
|
49 |
+
</cloudiq_callme>
|
50 |
+
</observers>
|
51 |
+
</cloudiq_core_config_save>
|
52 |
+
<controller_action_layout_generate_blocks_after>
|
53 |
+
<observers>
|
54 |
+
<cloudiq_callme_insert_block>
|
55 |
+
<type>singleton</type>
|
56 |
+
<class>cloudiq_callme/observer</class>
|
57 |
+
<method>observeControllerActionLayoutGenerateBlocksAfter</method>
|
58 |
+
</cloudiq_callme_insert_block>
|
59 |
+
</observers>
|
60 |
+
</controller_action_layout_generate_blocks_after>
|
61 |
+
</events>
|
62 |
+
</global>
|
63 |
+
|
64 |
+
<frontend>
|
65 |
+
<routers>
|
66 |
+
<cloudiq>
|
67 |
+
<args>
|
68 |
+
<modules>
|
69 |
+
<cloudiq_callme before="Cloudiq_Core">Cloudiq_Callme</cloudiq_callme>
|
70 |
+
</modules>
|
71 |
+
</args>
|
72 |
+
</cloudiq>
|
73 |
+
</routers>
|
74 |
+
</frontend>
|
75 |
+
|
76 |
+
<admin>
|
77 |
+
<routers>
|
78 |
+
<adminhtml>
|
79 |
+
<args>
|
80 |
+
<modules>
|
81 |
+
<cloudiq_callme before="Mage_Adminhtml">Cloudiq_Callme_Adminhtml</cloudiq_callme>
|
82 |
+
</modules>
|
83 |
+
</args>
|
84 |
+
</adminhtml>
|
85 |
+
</routers>
|
86 |
+
</admin>
|
87 |
+
|
88 |
+
<adminhtml>
|
89 |
+
<layout>
|
90 |
+
<updates>
|
91 |
+
<cloudiq_callme>
|
92 |
+
<file>cloudiq/callme.xml</file>
|
93 |
+
</cloudiq_callme>
|
94 |
+
</updates>
|
95 |
+
</layout>
|
96 |
+
<translate>
|
97 |
+
<modules>
|
98 |
+
<Cloudiq_Callme>
|
99 |
+
<files>
|
100 |
+
<default>Cloudiq_Callme.csv</default>
|
101 |
+
</files>
|
102 |
+
</Cloudiq_Callme>
|
103 |
+
</modules>
|
104 |
+
</translate>
|
105 |
+
</adminhtml>
|
106 |
+
|
107 |
+
<phpunit>
|
108 |
+
<suite>
|
109 |
+
<modules>
|
110 |
+
<Cloudiq_Callme/>
|
111 |
+
</modules>
|
112 |
+
</suite>
|
113 |
+
</phpunit>
|
114 |
+
|
115 |
+
</config>
|
app/code/community/Cloudiq/Callme/sql/cloudiq_callme_setup/mysql4-install-1.0.0.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$installer = $this;
|
4 |
+
|
5 |
+
$installer->startSetup();
|
6 |
+
|
7 |
+
$installer->run("
|
8 |
+
CREATE TABLE `{$installer->getTable('cloudiq_callme/config')}` (
|
9 |
+
`id` INT(11) NOT NULL auto_increment,
|
10 |
+
`enabled` BOOLEAN NOT NULL DEFAULT FALSE,
|
11 |
+
`app_id` INT(11) DEFAULT NULL,
|
12 |
+
`average_sale_value` VARCHAR(65) DEFAULT NULL,
|
13 |
+
`average_sales_call` VARCHAR(16) DEFAULT '3',
|
14 |
+
`button_position` VARCHAR(64) DEFAULT 'rightMiddle',
|
15 |
+
`button_template` VARCHAR(65) DEFAULT NULL,
|
16 |
+
`button_colour` VARCHAR(6) NOT NULL DEFAULT 'EB5E00',
|
17 |
+
`button_heading` VARCHAR(64) DEFAULT 'Free Call Back',
|
18 |
+
`button_message` VARCHAR(128) DEFAULT 'We\'d love to talk',
|
19 |
+
`pop_up_logo` BOOLEAN DEFAULT FALSE,
|
20 |
+
`pop_up_title` VARCHAR(64) DEFAULT 'Free Call Back',
|
21 |
+
`pop_up_strapline` VARCHAR(256) DEFAULT 'Call back is a free service',
|
22 |
+
`pop_up_conf_open` VARCHAR(512) DEFAULT 'Thank you. We\'re open and will be in touch soon',
|
23 |
+
`pop_up_conf_closed` VARCHAR(512) DEFAULT 'Thank you. We\'re closed right now, but will call you when we open',
|
24 |
+
`callback_callcentre_number` VARCHAR(13) DEFAULT NULL,
|
25 |
+
`callback_dtmf_tunnel` VARCHAR(16) DEFAULT NULL,
|
26 |
+
`call_centre_time_zone` VARCHAR(32) DEFAULT 'Europe/London',
|
27 |
+
`monday_from` VARCHAR(5) DEFAULT '09:00',
|
28 |
+
`monday_to` VARCHAR(5) DEFAULT '17:00',
|
29 |
+
`tuesday_from` VARCHAR(5) DEFAULT '09:00',
|
30 |
+
`tuesday_to` VARCHAR(5) DEFAULT '17:00',
|
31 |
+
`wednesday_from` VARCHAR(5) DEFAULT '09:00',
|
32 |
+
`wednesday_to` VARCHAR(5) DEFAULT '17:00',
|
33 |
+
`thursday_from` VARCHAR(5) DEFAULT '09:00',
|
34 |
+
`thursday_to` VARCHAR(5) DEFAULT '17:00',
|
35 |
+
`friday_from` VARCHAR(5) DEFAULT '09:00',
|
36 |
+
`friday_to` VARCHAR(5) DEFAULT '17:00',
|
37 |
+
`saturday_from` VARCHAR(5) DEFAULT '09:00',
|
38 |
+
`saturday_to` VARCHAR(5) DEFAULT '17:00',
|
39 |
+
`sunday_from` VARCHAR(5) DEFAULT '09:00',
|
40 |
+
`sunday_to` VARCHAR(5) DEFAULT '17:00',
|
41 |
+
`bank_holiday_from` VARCHAR(5) DEFAULT '09:00',
|
42 |
+
`bank_holiday_to` VARCHAR(5) DEFAULT '17:00',
|
43 |
+
`display_on_all` BOOLEAN NOT NULL DEFAULT TRUE,
|
44 |
+
`display_on_pages` TEXT DEFAULT NULL,
|
45 |
+
PRIMARY KEY (`id`),
|
46 |
+
UNIQUE KEY `app_idx` (`app_id`)
|
47 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
48 |
+
|
49 |
+
-- Insert the default config values
|
50 |
+
INSERT INTO `{$installer->getTable('cloudiq_callme/config')}` (`id`) VALUES (1);
|
51 |
+
");
|
52 |
+
|
53 |
+
$installer->endSetup();
|
app/code/community/Cloudiq/Core/.gitkeep
ADDED
File without changes
|
app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Block_Adminhtml_Config_Edit extends Mage_Adminhtml_Block_Widget_Form_Container {
|
3 |
+
public function __construct() {
|
4 |
+
parent::__construct();
|
5 |
+
|
6 |
+
$this->_blockGroup = 'cloudiq_core';
|
7 |
+
$this->_controller = 'adminhtml_config';
|
8 |
+
$this->_mode = 'edit';
|
9 |
+
|
10 |
+
}
|
11 |
+
|
12 |
+
public function getHeaderText() {
|
13 |
+
return $this->__('cloud.IQ Settings');
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Form.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Block_Adminhtml_Config_Edit_Form extends Mage_Adminhtml_Block_Widget_Form {
|
3 |
+
|
4 |
+
public function _prepareForm() {
|
5 |
+
$url = Mage::helper('adminhtml')->getUrl('*/*/save');
|
6 |
+
$form = new Varien_Data_Form(array('id' => 'edit_form', 'action' => $url, 'method' => 'post'));
|
7 |
+
$form->setUseContainer(true);
|
8 |
+
$this->setForm($form);
|
9 |
+
return parent::_prepareForm();
|
10 |
+
}
|
11 |
+
|
12 |
+
}
|
app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tab/Frame.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Block_Adminhtml_Config_Edit_Tab_Frame extends Mage_Adminhtml_Block_Abstract implements Mage_Adminhtml_Block_Widget_Tab_Interface {
|
3 |
+
|
4 |
+
/** @var $_helper Cloudiq_Core_Helper_Config */
|
5 |
+
protected $_helper;
|
6 |
+
|
7 |
+
public function _construct() {
|
8 |
+
$this->_helper = Mage::helper("cloudiq_core/config");
|
9 |
+
|
10 |
+
$this->setTemplate("cloudiq/core/tab/frame/iframe.phtml");
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Return the URL to query for the iframe's content.
|
15 |
+
*
|
16 |
+
* @return string
|
17 |
+
*/
|
18 |
+
public function getSubmitterUrl() {
|
19 |
+
return $this->getUrl("adminhtml/cloudiq/frame", array(
|
20 |
+
"module" => $this->getModule()
|
21 |
+
));
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getTabLabel() {
|
25 |
+
return $this->__($this->getLabel());
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getTabTitle() {
|
29 |
+
return $this->__($this->getLabel());
|
30 |
+
}
|
31 |
+
|
32 |
+
public function canShowTab() {
|
33 |
+
return $this->_helper->hasBeenSetUp();
|
34 |
+
}
|
35 |
+
|
36 |
+
public function isHidden() {
|
37 |
+
return !$this->_helper->hasBeenSetUp();
|
38 |
+
}
|
39 |
+
}
|
app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tab/Global.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Block_Adminhtml_Config_Edit_Tab_Global extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface {
|
3 |
+
/** @var $_helper Cloudiq_Core_Helper_Data */
|
4 |
+
protected $_helper;
|
5 |
+
/** @var $_config_helper Cloudiq_Core_Helper_Config */
|
6 |
+
protected $_config_helper;
|
7 |
+
|
8 |
+
public function __construct() {
|
9 |
+
parent::__construct();
|
10 |
+
|
11 |
+
$this->_helper = Mage::helper('cloudiq_core');
|
12 |
+
$this->_config_helper = Mage::helper('cloudiq_core/config');
|
13 |
+
|
14 |
+
$this->setTemplate('cloudiq/global/widget/form.phtml');
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function _prepareForm() {
|
18 |
+
$form = new Varien_Data_Form();
|
19 |
+
$fieldset = $form->addFieldset('settings', array('legend'=>$this->_helper->__('Global Settings')));
|
20 |
+
|
21 |
+
$fieldset->addField('global[enabled]', 'select', array(
|
22 |
+
'label' => $this->_helper->__('Enable Account?'),
|
23 |
+
'title' => $this->_helper->__('Enable Account?'),
|
24 |
+
'name' => 'global[enabled]',
|
25 |
+
'value' => $this->_config_helper->isEnabled(),
|
26 |
+
'values' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray()
|
27 |
+
));
|
28 |
+
|
29 |
+
$fieldset->addField('global[account_id]', 'text', array(
|
30 |
+
'label' => $this->_helper->__('cloud.IQ Account ID'),
|
31 |
+
'title' => $this->_helper->__('cloud.IQ Account ID'),
|
32 |
+
'name' => 'global[account_id]',
|
33 |
+
'note' => "Cut and paste this from the cloud.IQ confirmation message.",
|
34 |
+
'value' => $this->_config_helper->getAccountId(),
|
35 |
+
'required' => true
|
36 |
+
));
|
37 |
+
|
38 |
+
$fieldset->addField('global[token]', 'text', array(
|
39 |
+
'label' => $this->_helper->__('cloud.IQ Token'),
|
40 |
+
'title' => $this->_helper->__('cloud.IQ Token'),
|
41 |
+
'name' => 'global[token]',
|
42 |
+
'note' => "Cut and paste this from the cloud.IQ confirmation message.",
|
43 |
+
'value' => $this->_config_helper->getToken(),
|
44 |
+
'required' => true
|
45 |
+
));
|
46 |
+
|
47 |
+
$this->setForm($form);
|
48 |
+
}
|
49 |
+
|
50 |
+
public function getTabLabel() {
|
51 |
+
$label = $this->hasBeenSetUp() ? "Global Settings" : "cloud.IQ Sign up";
|
52 |
+
return $this->__($label);
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getTabTitle() {
|
56 |
+
$label = $this->hasBeenSetUp() ? "Global Settings" : "cloud.IQ Sign up";
|
57 |
+
return $this->__($label);
|
58 |
+
}
|
59 |
+
|
60 |
+
public function canShowTab() {
|
61 |
+
// Always show the Global settings tab
|
62 |
+
return true;
|
63 |
+
}
|
64 |
+
|
65 |
+
public function isHidden() {
|
66 |
+
// Always show the Global settings tab
|
67 |
+
return false;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Check if the module has been setup with API access credentials.
|
72 |
+
*
|
73 |
+
* @return bool
|
74 |
+
*/
|
75 |
+
protected function hasBeenSetUp() {
|
76 |
+
return $this->_config_helper->hasBeenSetUp();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Return the URL used for the Setup iFrame.
|
81 |
+
*
|
82 |
+
* @return string
|
83 |
+
*/
|
84 |
+
protected function getSetupUrl() {
|
85 |
+
return $this->getUrl("adminhtml/cloudiq/frame", array("module" => "signUp", "profile_id" => 2));
|
86 |
+
}
|
87 |
+
}
|
app/code/community/Cloudiq/Core/Block/Adminhtml/Config/Edit/Tabs.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Block_Adminhtml_Config_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs {
|
3 |
+
|
4 |
+
protected $_config_helper;
|
5 |
+
|
6 |
+
public function __construct() {
|
7 |
+
parent::__construct();
|
8 |
+
$this->setId('cloudiq_config_edit_tabs');
|
9 |
+
$this->setDestElementId('edit_form');
|
10 |
+
$this->setTitle(Mage::helper('adminhtml')->__('cloud.IQ Configuration'));
|
11 |
+
$this->_config_helper = Mage::helper('cloudiq_core/config');
|
12 |
+
$this->setTemplate('cloudiq/core/tabs.phtml');
|
13 |
+
}
|
14 |
+
|
15 |
+
protected function _beforeToHtml() {
|
16 |
+
// Open the Global Settings form tab by default
|
17 |
+
$this->setActiveTab("global_section");
|
18 |
+
return parent::_beforeToHtml();
|
19 |
+
}
|
20 |
+
}
|
app/code/community/Cloudiq/Core/Helper/Config.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Helper_Config extends Mage_Core_Helper_Abstract {
|
3 |
+
|
4 |
+
const CLOUDIQ_BASE_URL = "https://platform.cloud-iq.com/";
|
5 |
+
|
6 |
+
public function hasBeenSetUp() {
|
7 |
+
return $this->getToken() != "";
|
8 |
+
}
|
9 |
+
|
10 |
+
public function getAccountId() {
|
11 |
+
return Mage::getStoreConfig('cloudiq_core/global/account_id');
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getToken() {
|
15 |
+
return Mage::getStoreConfig('cloudiq_core/global/token');
|
16 |
+
}
|
17 |
+
|
18 |
+
public function isEnabled() {
|
19 |
+
return Mage::getStoreConfig('cloudiq_core/global/enabled');
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Return a URL for the cloud.IQ service.
|
24 |
+
*
|
25 |
+
* @param $module
|
26 |
+
*
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
public function getCloudiqUrl($module, $profile_id = false) {
|
30 |
+
$url = self::CLOUDIQ_BASE_URL;
|
31 |
+
|
32 |
+
$parameters = array();
|
33 |
+
|
34 |
+
if ($module != "") {
|
35 |
+
$parameters[] = "module=" . $module;
|
36 |
+
}
|
37 |
+
|
38 |
+
if ($profile_id) {
|
39 |
+
$parameters[] = "profileId=" . $profile_id;
|
40 |
+
}
|
41 |
+
|
42 |
+
$parameters = implode("&", $parameters);
|
43 |
+
if ($parameters != "") {
|
44 |
+
$url .= "?" . $parameters;
|
45 |
+
}
|
46 |
+
|
47 |
+
return $url;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Return the URL for cloud.IQ API calls.
|
52 |
+
*
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
public function getCloudiqApiUrl() {
|
56 |
+
return self::CLOUDIQ_BASE_URL . "gateway";
|
57 |
+
}
|
58 |
+
}
|
app/code/community/Cloudiq/Core/Helper/Data.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Core_Helper_Data extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
}
|
app/code/community/Cloudiq/Core/Model/Api/Abstract.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Model_Api_Abstract extends Varien_Object {
|
3 |
+
/**
|
4 |
+
* @return Cloudiq_Core_Model_Api_Request
|
5 |
+
*/
|
6 |
+
protected function _getRequestObject() {
|
7 |
+
return Mage::getModel('cloudiq_core/api_request');
|
8 |
+
}
|
9 |
+
}
|
10 |
+
|
app/code/community/Cloudiq/Core/Model/Api/Core.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Core_Model_Api_Core extends Cloudiq_Core_Model_Api_Abstract {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Request account information from the cloud.IQ API for either the
|
7 |
+
* account provided or the account stored in the configuration (if none
|
8 |
+
* is provided). Returns an array with two elements:
|
9 |
+
* status - boolean flag, true if the request was successful, false otherwise
|
10 |
+
* content - the account information XML element, if the request was successful
|
11 |
+
* or the error message if it failed
|
12 |
+
*
|
13 |
+
* @param $account_id Account ID to lookup instead of the configured one.
|
14 |
+
* @param $token Account token to use instead of the configured one.
|
15 |
+
*
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
public function lookupAccount($account_id = NULL, $token = NULL) {
|
19 |
+
$parameters = array(
|
20 |
+
"mode" => "lookup",
|
21 |
+
"action" => "account"
|
22 |
+
);
|
23 |
+
|
24 |
+
if ($account_id != NULL && $token != NULL) {
|
25 |
+
// Lookup the account provided instead of the one saved
|
26 |
+
$parameters["id"] = $account_id;
|
27 |
+
$parameters["token"] = $token;
|
28 |
+
}
|
29 |
+
|
30 |
+
/** @var Cloudiq_Core_Model_Api_Request $request */
|
31 |
+
$request = $this->_getRequestObject()->setParameters($parameters);
|
32 |
+
$response = $request->send(Zend_Http_Client::GET);
|
33 |
+
|
34 |
+
$result = array(
|
35 |
+
"status" => false,
|
36 |
+
"content" => ""
|
37 |
+
);
|
38 |
+
|
39 |
+
if ($response) {
|
40 |
+
if ($response->wasSuccessful()) {
|
41 |
+
$account_response = $response->getResponse()->account;
|
42 |
+
|
43 |
+
if (!is_null($account_response)) {
|
44 |
+
if ($account_response["status"] == Cloudiq_Core_Model_Api_Response::STATUS_SUCCESS) {
|
45 |
+
$result["status"] = true;
|
46 |
+
$result["content"] = $account_response;
|
47 |
+
} else {
|
48 |
+
// Unsuccessful account response
|
49 |
+
$result["content"] = $response->getApiStatusCodeDescription($account_id["status"]);
|
50 |
+
if ($account_response->description) {
|
51 |
+
$result["content"] .= sprintf(": %s", $account_response->description);
|
52 |
+
}
|
53 |
+
}
|
54 |
+
} else {
|
55 |
+
$result["content"] = "Unkown API response status";
|
56 |
+
}
|
57 |
+
} else {
|
58 |
+
// Unsuccessful response
|
59 |
+
$result["content"] = $response->getErrorMessage();
|
60 |
+
}
|
61 |
+
} else {
|
62 |
+
$result["content"] = "Failed to connect to cloud.IQ API";
|
63 |
+
}
|
64 |
+
|
65 |
+
return $result;
|
66 |
+
}
|
67 |
+
}
|
app/code/community/Cloudiq/Core/Model/Api/Request.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @method setParameters(array $parameters)
|
4 |
+
* @method getParameters()
|
5 |
+
*/
|
6 |
+
class Cloudiq_Core_Model_Api_Request extends Varien_Object {
|
7 |
+
|
8 |
+
const LOG_LOCATION = "cloudiq_api.log";
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @param $method HTTP verb to use when making the request, e.g. GET, POST, DELETE, PUT.
|
12 |
+
*
|
13 |
+
* @throws Zend_Http_Exception
|
14 |
+
*
|
15 |
+
* @return Cloudiq_Core_Model_Api_Response
|
16 |
+
*/
|
17 |
+
public function send($method) {
|
18 |
+
$_config_helper = Mage::helper("cloudiq_core/config");
|
19 |
+
|
20 |
+
$parameters = $this->getParameters();
|
21 |
+
$get_params = array();
|
22 |
+
$post_params = array();
|
23 |
+
|
24 |
+
if (!isset($parameters["token"])) {
|
25 |
+
// Authenticate through GET parameters
|
26 |
+
$get_params["id"] = $_config_helper->getAccountId();
|
27 |
+
$get_params["token"] = $_config_helper->getToken();
|
28 |
+
}
|
29 |
+
|
30 |
+
if ($method == Zend_Http_Client::GET) {
|
31 |
+
$get_params = array_merge($get_params, $parameters);
|
32 |
+
} else {
|
33 |
+
$post_params = array_merge($post_params, $parameters);
|
34 |
+
}
|
35 |
+
|
36 |
+
$client = new Zend_Http_Client();
|
37 |
+
$client
|
38 |
+
->setUri($this->getEndpoint())
|
39 |
+
->setParameterGet($get_params)
|
40 |
+
->setParameterPost($post_params)
|
41 |
+
->setMethod($method);
|
42 |
+
|
43 |
+
try {
|
44 |
+
/** @var $request_result Zend_Http_Response */
|
45 |
+
$request_result = $client->request();
|
46 |
+
} catch (Zend_Http_Client_Exception $e) {
|
47 |
+
$this->_log(Zend_Log::ERR, $e->getMessage(), $this->getEndpoint(), $method, $get_params, $post_params);
|
48 |
+
return null;
|
49 |
+
}
|
50 |
+
|
51 |
+
/** @var $response Cloudiq_Core_Model_Api_Response */
|
52 |
+
$response = Mage::getModel('cloudiq_core/api_response');
|
53 |
+
$response->populate($request_result);
|
54 |
+
|
55 |
+
$this->_log(Zend_Log::DEBUG, "Success", $this->getEndpoint(), $method, $get_params, $post_params, $response);
|
56 |
+
|
57 |
+
return $response;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Return the URI to make API calls against.
|
62 |
+
*
|
63 |
+
* @return string
|
64 |
+
*/
|
65 |
+
public function getEndpoint() {
|
66 |
+
return Mage::helper("cloudiq_core/config")->getCloudiqApiUrl();
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Print the API request details to a log file.
|
71 |
+
*
|
72 |
+
* @param $level
|
73 |
+
* @param $status
|
74 |
+
* @param $url
|
75 |
+
* @param $method
|
76 |
+
* @param array $get_params
|
77 |
+
* @param array $post_params
|
78 |
+
* @param Cloudiq_Core_Model_Api_Response $response
|
79 |
+
*/
|
80 |
+
protected function _log($level, $status, $url, $method, $get_params = array(), $post_params = array(), $response = NULL) {
|
81 |
+
$message = sprintf("%s\nMethod: %s\nEndpoint: %s\n", $status, $method, $url);
|
82 |
+
|
83 |
+
if (!empty($get_params)) {
|
84 |
+
array_walk($get_params, function (&$v, $k) { $v = sprintf("%s = %s", $k, $v); });
|
85 |
+
$message .= sprintf("GET Parameters:\n\t%s\n", implode("\n\t", $get_params));
|
86 |
+
}
|
87 |
+
|
88 |
+
if (!empty($post_params)) {
|
89 |
+
array_walk($post_params, function (&$v, $k) { $v = sprintf("%s = %s", $k, $v); });
|
90 |
+
$message .= sprintf("POST Parameters:\n\t%s\n", implode("\n\t", $post_params));
|
91 |
+
}
|
92 |
+
|
93 |
+
if (!is_null($response)) {
|
94 |
+
$message .= sprintf("Response status: %s\n", ($response->wasSuccessful() ? "Successful" : "Failed"));
|
95 |
+
if (!$response->wasSuccessful()) {
|
96 |
+
$message .= sprintf("Response error: %s\n", $response->getErrorMessage());
|
97 |
+
}
|
98 |
+
$raw_response = $response->getRawResponse();
|
99 |
+
if ($raw_response) {
|
100 |
+
$message .= sprintf("Raw response:\n\t%s\n\t%s\n",
|
101 |
+
$raw_response->getHeadersAsString(true, "\n\t"),
|
102 |
+
implode("\n\t", explode("\n", $raw_response->getBody()))
|
103 |
+
);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
Mage::log($message, $level, self::LOG_LOCATION);
|
108 |
+
}
|
109 |
+
}
|
app/code/community/Cloudiq/Core/Model/Api/Response.php
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @method setRawResponse(Zend_Http_Response $raw_response)
|
4 |
+
* @method Zend_Http_Response getRawResponse()
|
5 |
+
* @method setHttpStatusCode(int $status_code)
|
6 |
+
* @method int getHttpStatusCode()
|
7 |
+
* @method setXmlParseErrors(array $errors)
|
8 |
+
* @method array getXmlParseErrors()
|
9 |
+
* @method setResponse(SimpleXMLElement $data)
|
10 |
+
* @method SimpleXMLElement getResponse()
|
11 |
+
* @method bool hasResponse()
|
12 |
+
*/
|
13 |
+
class Cloudiq_Core_Model_Api_Response extends Varien_Object {
|
14 |
+
|
15 |
+
const STATUS_SUCCESS = 1;
|
16 |
+
const STATUS_AUTHENTICATION_FAILURE = 101;
|
17 |
+
const STATUS_REQUESTING_IP_NOT_VALID = 102;
|
18 |
+
const STATUS_INVALID_FUNCTION_REQUEST = 103;
|
19 |
+
const STATUS_REQUEST_MISSING_A_MANDATORY_PARAMETER = 104;
|
20 |
+
const STATUS_FORMAT_ERROR_IN_REQUEST_PARAMETERS = 105;
|
21 |
+
const STATUS_REQUEST_NOT_VALID_FOR_GIVEN_ACCOUNT = 106;
|
22 |
+
const STATUS_INTERNAL_ERROR_WHILE_PROCESSING_YOUR_REQUEST = 107;
|
23 |
+
const STATUS_VALIDATION_FAILED = 200;
|
24 |
+
|
25 |
+
public static $status_code_descriptions = array(
|
26 |
+
self::STATUS_SUCCESS => "Success",
|
27 |
+
self::STATUS_AUTHENTICATION_FAILURE => "Authentication failure",
|
28 |
+
self::STATUS_REQUESTING_IP_NOT_VALID => "Requesting ip not valid",
|
29 |
+
self::STATUS_INVALID_FUNCTION_REQUEST => "Invalid function request",
|
30 |
+
self::STATUS_REQUEST_MISSING_A_MANDATORY_PARAMETER => "Request missing a mandatory parameter",
|
31 |
+
self::STATUS_FORMAT_ERROR_IN_REQUEST_PARAMETERS => "Format error in request parameters",
|
32 |
+
self::STATUS_REQUEST_NOT_VALID_FOR_GIVEN_ACCOUNT => "Request not valid for given account",
|
33 |
+
self::STATUS_INTERNAL_ERROR_WHILE_PROCESSING_YOUR_REQUEST => "Internal error while processing your request",
|
34 |
+
self::STATUS_VALIDATION_FAILED => "Validation failed"
|
35 |
+
);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Populate the response data from the given Zend_Http_Response object.
|
39 |
+
*
|
40 |
+
* @param Zend_Http_Response $raw_response
|
41 |
+
*
|
42 |
+
* @return $this
|
43 |
+
*/
|
44 |
+
public function populate(Zend_Http_Response $raw_response) {
|
45 |
+
$this->setRawResponse($raw_response);
|
46 |
+
|
47 |
+
$this->setHttpStatusCode((int) $raw_response->getStatus());
|
48 |
+
|
49 |
+
// Handle libxml errors internally
|
50 |
+
$this->setXmlParseErrors(NULL);
|
51 |
+
$xml_errors_setting = libxml_use_internal_errors(true);
|
52 |
+
|
53 |
+
// The XML API response gets sent with content type text/html,
|
54 |
+
// so decode the HTML entities before parsing
|
55 |
+
$decoded_data = simplexml_load_string(utf8_encode(html_entity_decode($raw_response->getBody())));
|
56 |
+
|
57 |
+
if ($decoded_data) {
|
58 |
+
$this->setResponse($decoded_data);
|
59 |
+
} else {
|
60 |
+
$xml_errors = array();
|
61 |
+
foreach (libxml_get_errors() as $error) {
|
62 |
+
$xml_errors[] = preg_replace("/\n/", " ", $error->message);
|
63 |
+
}
|
64 |
+
$this->setXmlParseErrors($xml_errors);
|
65 |
+
}
|
66 |
+
|
67 |
+
// Reset libxml error settings
|
68 |
+
libxml_clear_errors();
|
69 |
+
libxml_use_internal_errors($xml_errors_setting);
|
70 |
+
|
71 |
+
return $this;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function getResponseXPath($xpath) {
|
75 |
+
if ($this->hasResponse()) {
|
76 |
+
return $this->getResponse()->xpath($xpath);
|
77 |
+
} else {
|
78 |
+
return NULL;
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Get the API response status code. Return false if there
|
84 |
+
* is no status code.
|
85 |
+
*
|
86 |
+
* @return int
|
87 |
+
*/
|
88 |
+
public function getApiStatusCode() {
|
89 |
+
$status_attribute_xpath = $this->getResponseXPath('/response/@status[1]');
|
90 |
+
if (count($status_attribute_xpath) == 1) {
|
91 |
+
$status_attribute = (string) $status_attribute_xpath[0];
|
92 |
+
if (is_numeric($status_attribute)) {
|
93 |
+
return (int) $status_attribute;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
return false;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Return the description text for the given API response code. Returns
|
101 |
+
* "Unknown" for unknown codes.
|
102 |
+
*
|
103 |
+
* @param int $code API response code
|
104 |
+
*
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
public function getApiStatusCodeDescription($code) {
|
108 |
+
if (isset(self::$status_code_descriptions[$code])) {
|
109 |
+
return self::$status_code_descriptions[$code];
|
110 |
+
}
|
111 |
+
|
112 |
+
return "Unknown";
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Perform a check on the HTTP Status Code returned by the request and evaluate the status attribute of
|
117 |
+
* the wrapping <response> element for a valid status code.
|
118 |
+
*
|
119 |
+
* @return bool
|
120 |
+
*/
|
121 |
+
public function wasSuccessful() {
|
122 |
+
if ($this->getResponse()) {
|
123 |
+
$http_status_string = (string) $this->getHttpStatusCode();
|
124 |
+
|
125 |
+
if (substr($http_status_string, 0, 1) == "2") {
|
126 |
+
$api_status = $this->getApiStatusCode();
|
127 |
+
|
128 |
+
if ($api_status !== false) {
|
129 |
+
return $api_status == self::STATUS_SUCCESS;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
return false;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Choose and return the appropriate text error message for this request.
|
139 |
+
* Returns false if the request was successful.
|
140 |
+
*
|
141 |
+
* @return bool|string
|
142 |
+
*/
|
143 |
+
public function getErrorMessage() {
|
144 |
+
$message = false;
|
145 |
+
|
146 |
+
if (!$this->wasSuccessful()) {
|
147 |
+
// Check for API status errors
|
148 |
+
$api_status_code = $this->getApiStatusCode();
|
149 |
+
if ($api_status_code !== false) {
|
150 |
+
$message = $this->getApiStatusCodeDescription($api_status_code);
|
151 |
+
} else {
|
152 |
+
// Check for response parse errors
|
153 |
+
$xml_parse_errors = $this->getXmlParseErrors();
|
154 |
+
if (!empty($xml_parse_errors)) {
|
155 |
+
$message = "Failed to parse the API response: " . implode(", ", $xml_parse_errors);
|
156 |
+
} else {
|
157 |
+
// Check for HTTP errors
|
158 |
+
$http_status_code = $this->getHttpStatusCode();
|
159 |
+
if (!is_null($http_status_code)) {
|
160 |
+
$message = "HTTP Error: " . Zend_Http_Response::responseCodeAsText($http_status_code);
|
161 |
+
} else {
|
162 |
+
$message = "Unknown error";
|
163 |
+
}
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
return $message;
|
169 |
+
}
|
170 |
+
}
|
app/code/community/Cloudiq/Core/Test/Config/Base.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Test_Config_Base extends EcomDev_PHPUnit_Test_Case_Config {
|
3 |
+
/**
|
4 |
+
* @test
|
5 |
+
*/
|
6 |
+
public function testBasicConfiguration() {
|
7 |
+
$this->assertModuleCodePool('community');
|
8 |
+
$this->assertModuleVersion('1.0.0');
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @test
|
13 |
+
*/
|
14 |
+
public function testClassAliases() {
|
15 |
+
$this->assertHelperAlias('cloudiq_core', 'Cloudiq_Core_Helper_Data');
|
16 |
+
$this->assertModelAlias('cloudiq_core/test', 'Cloudiq_Core_Model_Test');
|
17 |
+
$this->assertBlockAlias('cloudiq_core/test', 'Cloudiq_Core_Block_Test');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @test
|
22 |
+
*/
|
23 |
+
public function testDataHelperExists() {
|
24 |
+
$this->assertInstanceOf('Cloudiq_Core_Helper_Data', Mage::helper('cloudiq_core'));
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Cloudiq/Core/Test/Model/Api/Response.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Cloudiq_Core_Test_Model_Api_Response extends Cloudiq_Core_Test_Model_Api_TestCase {
|
4 |
+
|
5 |
+
/** @var Cloudiq_Core_Model_Api_Response */
|
6 |
+
protected $_model;
|
7 |
+
|
8 |
+
protected function setUp() {
|
9 |
+
parent::setUp();
|
10 |
+
|
11 |
+
$this->_model = Mage::getModel('cloudiq_core/api_response');
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function tearDown() {
|
15 |
+
parent::tearDown();
|
16 |
+
|
17 |
+
$this->_model = null;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @test
|
22 |
+
*/
|
23 |
+
public function testClassConstruction() {
|
24 |
+
$this->assertInstanceOf('Cloudiq_Core_Model_Api_Response', $this->_model);
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
*/
|
30 |
+
public function testWasSuccessfulNoRequest() {
|
31 |
+
$this->assertFalse($this->_model->wasSuccessful());
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @test
|
36 |
+
*/
|
37 |
+
public function testWasSuccessfulStatusCodeAndResponseAttribute() {
|
38 |
+
$successful_response = Zend_Http_Response::fromString($this->_loadFileContents('Response/testWasSuccessfulStatusCodeAndResponseAttribute.txt'));
|
39 |
+
|
40 |
+
$this->_model->populate($successful_response);
|
41 |
+
|
42 |
+
$this->assertTrue($this->_model->wasSuccessful());
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @test
|
47 |
+
*/
|
48 |
+
public function testWasSuccessfulBadResponseAttribute() {
|
49 |
+
$bad_response = Zend_Http_Response::fromString($this->_loadFileContents('Response/testWasSuccessfulBadResponseAttribute.txt'));
|
50 |
+
|
51 |
+
$this->_model->populate($bad_response);
|
52 |
+
|
53 |
+
$this->assertFalse($this->_model->wasSuccessful());
|
54 |
+
}
|
55 |
+
}
|
app/code/community/Cloudiq/Core/Test/Model/Api/TestCase.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
abstract class Cloudiq_Core_Test_Model_Api_TestCase extends EcomDev_PHPUnit_Test_Case {
|
3 |
+
/**
|
4 |
+
* @param string $http_method
|
5 |
+
* @param int $status_code
|
6 |
+
* @param string $response_filename
|
7 |
+
*
|
8 |
+
* @return PHPUnit_Framework_MockObject_MockObject
|
9 |
+
*/
|
10 |
+
public function getRequestMock($http_method, $status_code, $response_filename) {
|
11 |
+
$file_contents = $this->_loadFileContents($response_filename);
|
12 |
+
|
13 |
+
$this->assertNotNull($file_contents);
|
14 |
+
$this->assertNotEmpty($file_contents);
|
15 |
+
|
16 |
+
/** @var $response Cloudiq_Core_Model_Api_Response */
|
17 |
+
$response = Mage::getModel('cloudiq_core/api_response');
|
18 |
+
$response
|
19 |
+
->setStatusCode($status_code)
|
20 |
+
->setRawResponse($file_contents);
|
21 |
+
|
22 |
+
$request_mock = $this->getModelMock('cloudiq_core/api_request', array('send'));
|
23 |
+
|
24 |
+
$request_mock
|
25 |
+
->expects($this->once())
|
26 |
+
->method('send')
|
27 |
+
->with($this->equalTo($http_method))
|
28 |
+
->will($this->returnValue($response));
|
29 |
+
|
30 |
+
return $request_mock;
|
31 |
+
}
|
32 |
+
|
33 |
+
protected function _loadFileContents($file) {
|
34 |
+
$directory_tree = array(
|
35 |
+
Mage::getModuleDir('', 'Cloudiq_Core'),
|
36 |
+
'Test',
|
37 |
+
'Model',
|
38 |
+
'Api',
|
39 |
+
'data',
|
40 |
+
$file
|
41 |
+
);
|
42 |
+
|
43 |
+
$file_path = join(DS, $directory_tree);
|
44 |
+
|
45 |
+
return file_get_contents($file_path);
|
46 |
+
}
|
47 |
+
}
|
app/code/community/Cloudiq/Core/Test/Model/Api/data/Response/testWasSuccessfulBadResponseAttribute.txt
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
HTTP/1.1 403 Forbidden
|
2 |
+
Date: Tue, 18 Jun 2013 11:46:25 GMT
|
3 |
+
Server: Apache-Coyote/1.1
|
4 |
+
X-powered-by: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
|
5 |
+
Content-type: text/xml;charset=ISO-8859-1
|
6 |
+
Content-length: 201
|
7 |
+
Via: 1.1 nimbus.cloud-iq.com
|
8 |
+
Connection: close
|
9 |
+
|
10 |
+
<?xml version="1.0" encoding="utf-8" ?>
|
11 |
+
<response status="101">
|
12 |
+
<description>Authentication failure</description>
|
13 |
+
<requestId>273025</requestId>
|
14 |
+
<dateTime>2013-06-18T11:46:25Z</dateTime>
|
15 |
+
</response>
|
app/code/community/Cloudiq/Core/Test/Model/Api/data/Response/testWasSuccessfulStatusCodeAndResponseAttribute.txt
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
HTTP/1.1 202 Accepted
|
2 |
+
Date: Tue, 18 Jun 2013 11:30:50 GMT
|
3 |
+
Server: Apache-Coyote/1.1
|
4 |
+
X-powered-by: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
|
5 |
+
Content-type: text/html;charset=ISO-8859-1
|
6 |
+
Content-length: 914
|
7 |
+
Via: 1.1 nimbus.cloud-iq.com
|
8 |
+
Connection: close
|
9 |
+
|
10 |
+
<?xml version="1.0" encoding="utf-8" ?>
|
11 |
+
<response status="1">
|
12 |
+
<description>Success</description>
|
13 |
+
<requestId>273005</requestId>
|
14 |
+
<dateTime>2013-06-18T11:30:50Z</dateTime>
|
15 |
+
<timeZone>GMT</timeZone>
|
16 |
+
</response>
|
app/code/community/Cloudiq/Core/controllers/Adminhtml/CloudiqController.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Cloudiq_Core_Adminhtml_CloudiqController extends Mage_Adminhtml_Controller_Action {
|
3 |
+
public function editAction() {
|
4 |
+
$this->loadLayout();
|
5 |
+
$this->_setActiveMenu('cloudiq');
|
6 |
+
$this->renderLayout();
|
7 |
+
}
|
8 |
+
|
9 |
+
public function saveAction() {
|
10 |
+
Mage::dispatchEvent("cloudiq_core_config_save", array('request'=>$this->getRequest()));
|
11 |
+
|
12 |
+
$request = $this->getRequest();
|
13 |
+
$form_data = new Varien_Object($request->getParam("global"));
|
14 |
+
|
15 |
+
if (count($form_data->getData()) > 0) {
|
16 |
+
// Save global Cloud.IQ config data to system config
|
17 |
+
|
18 |
+
$account_id = trim($form_data->getData("account_id"));
|
19 |
+
$token = trim($form_data->getData("token"));
|
20 |
+
$enabled = ($form_data->getData("enabled")) ? 1 : 0;
|
21 |
+
|
22 |
+
// Validate the form fields
|
23 |
+
$validation_errors = 0;
|
24 |
+
|
25 |
+
if ($account_id == "") {
|
26 |
+
$validation_errors++;
|
27 |
+
Mage::getSingleton("adminhtml/session")->addError($this->__("cloud.IQ: Account ID can not be empty."));
|
28 |
+
}
|
29 |
+
|
30 |
+
if ($token == "") {
|
31 |
+
$validation_errors++;
|
32 |
+
Mage::getSingleton("adminhtml/session")->addError($this->__("cloud.IQ: Token can not be empty."));
|
33 |
+
}
|
34 |
+
|
35 |
+
if ($validation_errors == 0 && $enabled) {
|
36 |
+
// Check if the account is valid using the API
|
37 |
+
$result = Mage::getModel("cloudiq_core/api_core")->lookupAccount($account_id, $token);
|
38 |
+
if ($result["status"] !== true) {
|
39 |
+
$validation_errors++;
|
40 |
+
Mage::getSingleton("adminhtml/session")->addError(sprintf("%s: %s", $this->__("cloud.IQ: The account credentials provided could not be verified"), $this->__($result["content"])));
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($validation_errors == 0) {
|
45 |
+
// Save configuration to system config
|
46 |
+
$_system_config = Mage::getConfig();
|
47 |
+
|
48 |
+
$_system_config->saveConfig("cloudiq_core/global/account_id", $account_id);
|
49 |
+
$_system_config->saveConfig("cloudiq_core/global/token", $token);
|
50 |
+
|
51 |
+
$_system_config->saveConfig("cloudiq_core/global/enabled", $enabled);
|
52 |
+
|
53 |
+
Mage::getSingleton("adminhtml/session")->addSuccess(Mage::helper("cloudiq_core")->__("Global configuration saved."));
|
54 |
+
|
55 |
+
// Reload system config, so changes are picked up
|
56 |
+
$_system_config->reinit();
|
57 |
+
Mage::app()->reinitStores();
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
// Redirect back to the form, preserving any params (such as active tab)
|
62 |
+
$this->_redirect("*/*/edit", array("_current" => true));
|
63 |
+
}
|
64 |
+
|
65 |
+
public function frameAction() {
|
66 |
+
$_config_helper = Mage::helper("cloudiq_core/config");
|
67 |
+
|
68 |
+
$module = $this->getRequest()->getParam("module");
|
69 |
+
$profile_id = $this->getRequest()->getParam("profile_id");
|
70 |
+
|
71 |
+
$destination = $_config_helper->getCloudiqUrl($module, ($profile_id != null) ? $profile_id : null);
|
72 |
+
|
73 |
+
$additional_parameters = array();
|
74 |
+
|
75 |
+
// Pre-populate the sign up form with current user details
|
76 |
+
if ($module == "signUp") {
|
77 |
+
/** @var $user Mage_Admin_Model_User */
|
78 |
+
$user = Mage::getSingleton('admin/session')->getUser();
|
79 |
+
$additional_parameters["username"] = $user->getEmail();
|
80 |
+
$additional_parameters["fullName"] = $user->getName();
|
81 |
+
}
|
82 |
+
|
83 |
+
$this->getResponse()->setBody(
|
84 |
+
$this->getLayout()->createBlock("core/template", "")
|
85 |
+
->setTemplate("cloudiq/core/tab/frame/submitter.phtml")
|
86 |
+
->setDestination($destination)
|
87 |
+
->setAccountId($_config_helper->getAccountId())
|
88 |
+
->setToken($_config_helper->getToken())
|
89 |
+
->setAdditionalParameters($additional_parameters)
|
90 |
+
->toHtml()
|
91 |
+
);
|
92 |
+
}
|
93 |
+
}
|
app/code/community/Cloudiq/Core/etc/adminhtml.xml
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<menu>
|
4 |
+
<cloudiq translate="title" module="cloudiq_core">
|
5 |
+
<title>cloud.IQ</title>
|
6 |
+
<sort_order>900</sort_order>
|
7 |
+
<action>adminhtml/cloudiq/edit</action>
|
8 |
+
</cloudiq>
|
9 |
+
</menu>
|
10 |
+
<acl>
|
11 |
+
<resources>
|
12 |
+
<admin>
|
13 |
+
<children>
|
14 |
+
<system>
|
15 |
+
<children>
|
16 |
+
<config>
|
17 |
+
<children>
|
18 |
+
<cloudiq_core translate="title">
|
19 |
+
<title>cloud.IQ Section</title>
|
20 |
+
<sort_order>60</sort_order>
|
21 |
+
</cloudiq_core>
|
22 |
+
</children>
|
23 |
+
</config>
|
24 |
+
</children>
|
25 |
+
</system>
|
26 |
+
</children>
|
27 |
+
</admin>
|
28 |
+
</resources>
|
29 |
+
</acl>
|
30 |
+
</config>
|
31 |
+
|
app/code/community/Cloudiq/Core/etc/config.xml
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
|
4 |
+
<modules>
|
5 |
+
<Cloudiq_Core>
|
6 |
+
<version>1.0.0</version>
|
7 |
+
</Cloudiq_Core>
|
8 |
+
</modules>
|
9 |
+
|
10 |
+
<global>
|
11 |
+
<blocks>
|
12 |
+
<cloudiq_core>
|
13 |
+
<class>Cloudiq_Core_Block</class>
|
14 |
+
</cloudiq_core>
|
15 |
+
</blocks>
|
16 |
+
<models>
|
17 |
+
<cloudiq_core>
|
18 |
+
<class>Cloudiq_Core_Model</class>
|
19 |
+
</cloudiq_core>
|
20 |
+
</models>
|
21 |
+
<helpers>
|
22 |
+
<cloudiq_core>
|
23 |
+
<class>Cloudiq_Core_Helper</class>
|
24 |
+
</cloudiq_core>
|
25 |
+
</helpers>
|
26 |
+
</global>
|
27 |
+
|
28 |
+
<frontend>
|
29 |
+
<routers>
|
30 |
+
<cloudiq>
|
31 |
+
<use>standard</use>
|
32 |
+
<args>
|
33 |
+
<frontName>cloudiq</frontName>
|
34 |
+
<module>Cloudiq_Core</module>
|
35 |
+
</args>
|
36 |
+
</cloudiq>
|
37 |
+
</routers>
|
38 |
+
</frontend>
|
39 |
+
|
40 |
+
<admin>
|
41 |
+
<routers>
|
42 |
+
<adminhtml>
|
43 |
+
<args>
|
44 |
+
<modules>
|
45 |
+
<cloudiq_core before="Mage_Adminhtml">Cloudiq_Core_Adminhtml</cloudiq_core>
|
46 |
+
</modules>
|
47 |
+
</args>
|
48 |
+
</adminhtml>
|
49 |
+
</routers>
|
50 |
+
</admin>
|
51 |
+
|
52 |
+
<adminhtml>
|
53 |
+
<layout>
|
54 |
+
<updates>
|
55 |
+
<cloudiq_core>
|
56 |
+
<file>cloudiq/core.xml</file>
|
57 |
+
</cloudiq_core>
|
58 |
+
</updates>
|
59 |
+
</layout>
|
60 |
+
</adminhtml>
|
61 |
+
|
62 |
+
<phpunit>
|
63 |
+
<suite>
|
64 |
+
<modules>
|
65 |
+
<Cloudiq_Core />
|
66 |
+
</modules>
|
67 |
+
</suite>
|
68 |
+
</phpunit>
|
69 |
+
|
70 |
+
</config>
|
app/design/adminhtml/default/default/layout/cloudiq/callme.xml
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
<adminhtml_cloudiq_edit>
|
4 |
+
<reference name="head">
|
5 |
+
<action method="addCss"><stylesheet>cloudiq/callme.css</stylesheet></action>
|
6 |
+
<action method="addItem"><type>skin_js</type><name>cloudiq/js/callme.js</name></action>
|
7 |
+
<action method="addJs"><script>cloudiq/callme-jscolor/jscolor.js</script></action>
|
8 |
+
<action method="addJs"><script>cloudiq/callme-button.js</script></action>
|
9 |
+
</reference>
|
10 |
+
<reference name="left">
|
11 |
+
<reference name="cloudiq.config.edit.tabs">
|
12 |
+
<block type="cloudiq_callme/adminhtml_config_edit_tab_callme" name="cloudiq.config.edit.tab.callme">
|
13 |
+
<action method="setAfter">
|
14 |
+
<after>global_section</after>
|
15 |
+
</action>
|
16 |
+
</block>
|
17 |
+
<action method="addTab">
|
18 |
+
<name>callme_section</name>
|
19 |
+
<block>cloudiq.config.edit.tab.callme</block>
|
20 |
+
</action>
|
21 |
+
</reference>
|
22 |
+
</reference>
|
23 |
+
</adminhtml_cloudiq_edit>
|
24 |
+
</layout>
|
app/design/adminhtml/default/default/layout/cloudiq/core.xml
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
<default>
|
4 |
+
<reference name="head">
|
5 |
+
<action method="addCss"><stylesheet>cloudiq/core.css</stylesheet></action>
|
6 |
+
</reference>
|
7 |
+
</default>
|
8 |
+
<adminhtml_cloudiq_edit>
|
9 |
+
<reference name="content">
|
10 |
+
<block type="cloudiq_core/adminhtml_config_edit" name="cloudiq.config.edit"/>
|
11 |
+
</reference>
|
12 |
+
<reference name="left">
|
13 |
+
<block type="cloudiq_core/adminhtml_config_edit_tabs" name="cloudiq.config.edit.tabs">
|
14 |
+
<block type="cloudiq_core/adminhtml_config_edit_tab_global" name="cloudiq.config.edit.tab.global"/>
|
15 |
+
<action method="addTab">
|
16 |
+
<name>global_section</name>
|
17 |
+
<block>cloudiq.config.edit.tab.global</block>
|
18 |
+
</action>
|
19 |
+
<block type="cloudiq_core/adminhtml_config_edit_tab_frame" name="cloudiq.config.edit.tab.dashboard">
|
20 |
+
<action method="setLabel"><label>Dashboard</label></action>
|
21 |
+
<action method="setModule"><module>dashboard</module></action>
|
22 |
+
</block>
|
23 |
+
<action method="addTab">
|
24 |
+
<name>dashboard_section</name>
|
25 |
+
<block>cloudiq.config.edit.tab.dashboard</block>
|
26 |
+
</action>
|
27 |
+
<block type="cloudiq_core/adminhtml_config_edit_tab_frame" name="cloudiq.config.edit.tab.account">
|
28 |
+
<action method="setLabel"><label>Account</label></action>
|
29 |
+
<action method="setModule"><module>account</module></action>
|
30 |
+
</block>
|
31 |
+
<action method="addTab">
|
32 |
+
<name>account_section</name>
|
33 |
+
<block>cloudiq.config.edit.tab.account</block>
|
34 |
+
</action>
|
35 |
+
<block type="cloudiq_core/adminhtml_config_edit_tab_frame" name="cloudiq.config.edit.tab.support">
|
36 |
+
<action method="setLabel"><label>Support</label></action>
|
37 |
+
<action method="setModule"><module>support</module></action>
|
38 |
+
</block>
|
39 |
+
<action method="addTab">
|
40 |
+
<name>support_section</name>
|
41 |
+
<block>cloudiq.config.edit.tab.support</block>
|
42 |
+
</action>
|
43 |
+
</block>
|
44 |
+
</reference>
|
45 |
+
</adminhtml_cloudiq_edit>
|
46 |
+
</layout>
|
47 |
+
|
app/design/adminhtml/default/default/template/cloudiq/core/tab/frame/iframe.phtml
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<iframe src="<?php echo $this->getSubmitterUrl(); ?>" frameborder="0" width="100%" height="787px"></iframe>
|
app/design/adminhtml/default/default/template/cloudiq/core/tab/frame/submitter.phtml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<form action="<?php echo $this->getDestination(); ?>" method="POST">
|
2 |
+
<input type="hidden" name="id" value="<?php echo $this->getAccountId(); ?>" />
|
3 |
+
<input type="hidden" name="token" value="<?php echo $this->getToken() ?>" />
|
4 |
+
<?php $additional_parameters = $this->getAdditionalParameters(); ?>
|
5 |
+
<?php foreach ($additional_parameters as $name => $value): ?>
|
6 |
+
<input type="hidden" name="<?php echo $name; ?>" value="<?php echo $value; ?>" />
|
7 |
+
<?php endforeach; ?>
|
8 |
+
</form>
|
9 |
+
<script type="text/javascript">
|
10 |
+
document.forms[0].submit();
|
11 |
+
</script>
|
app/design/adminhtml/default/default/template/cloudiq/core/tabs.phtml
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if($this->getTitle()): ?>
|
2 |
+
<h3><?php echo $this->getTitle() ?></h3>
|
3 |
+
<?php endif ?>
|
4 |
+
<?php if(!empty($tabs)): ?>
|
5 |
+
<ul id="<?php echo $this->getId() ?>" class="tabs">
|
6 |
+
<?php foreach ($tabs as $_tab): ?>
|
7 |
+
<?php if (!$this->canShowTab($_tab)): continue; endif; ?>
|
8 |
+
<li <?php if($this->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?>>
|
9 |
+
<a href="<?php echo $this->getTabUrl($_tab) ?>" id="<?php echo $this->getTabId($_tab) ?>" name="<?php echo $this->getTabId($_tab, false) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="tab-item-link <?php echo $this->getTabClass($_tab) ?><?php if (preg_match('/\s?ajax\s?/', $_tab->getClass())) {?> notloaded<?php }?>">
|
10 |
+
<span><span class="changed" title="<?php echo $this->__('The information in this tab has been changed.') ?>"></span><span class="error" title="<?php echo $this->__('This tab contains invalid data. Please solve the problem before saving.') ?>"></span><?php echo $this->getTabLabel($_tab); ?></span>
|
11 |
+
</a>
|
12 |
+
<div id="<?php echo $this->getTabId($_tab) ?>_content" style="display:none;"><?php echo $this->getTabContent($_tab) ?></div>
|
13 |
+
</li>
|
14 |
+
<?php endforeach; ?>
|
15 |
+
</ul>
|
16 |
+
<script type="text/javascript">
|
17 |
+
<?php echo $this->getJsObjectName() ?> = new varienTabs('<?php echo $this->getId() ?>', '<?php echo $this->getDestElementId() ?>', '<?php echo $this->getActiveTabId() ?>', <?php echo $this->getAllShadowTabs()?>);
|
18 |
+
</script>
|
19 |
+
<script type="text/javascript">
|
20 |
+
document.observe("dom:loaded", function() {
|
21 |
+
var varien_tabs = <?php echo $this->getJsObjectName() ?>;
|
22 |
+
var original_url = $('edit_form').action;
|
23 |
+
|
24 |
+
$$('.form-buttons .save').each(function(element) {
|
25 |
+
element.onclick = function (e) {
|
26 |
+
var new_url = original_url;
|
27 |
+
if (original_url.substr(-1,1) != "/") {
|
28 |
+
new_url = new_url + "/";
|
29 |
+
}
|
30 |
+
new_url = new_url + "active_tab/" + varien_tabs.activeTab.name + "/";
|
31 |
+
|
32 |
+
$('edit_form').action = new_url;
|
33 |
+
|
34 |
+
editForm.submit();
|
35 |
+
}
|
36 |
+
});
|
37 |
+
});
|
38 |
+
</script>
|
39 |
+
<?php endif; ?>
|
app/design/adminhtml/default/default/template/cloudiq/global/tab.phtml
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
TODO
|
app/design/adminhtml/default/default/template/cloudiq/global/widget/form.phtml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Form template for the Global Settings tab of the configuration
|
4 |
+
* form for Cloudiq_Core module.
|
5 |
+
*
|
6 |
+
* Based on default/default/template/widget/form.phtml
|
7 |
+
*/
|
8 |
+
?>
|
9 |
+
<div class="entry-edit">
|
10 |
+
<?php if (!$this->hasBeenSetUp()) : ?>
|
11 |
+
<iframe src="<?php echo $this->getSetupUrl() ?>" frameborder="0" width="100%" height="600"></iframe>
|
12 |
+
<?php endif; ?>
|
13 |
+
<?php echo $this->getFormHtml();?>
|
14 |
+
</div>
|
15 |
+
<?php echo $this->getChildHtml('form_after');?>
|
app/design/frontend/base/default/template/cloudiq/callme/button.phtml
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<style type="text/css">
|
2 |
+
.<?php echo $this->_getTemplateClass(); ?> {
|
3 |
+
background: -moz-linear-gradient(top, #<?php echo $this->_getGradientStartColour(); ?> 0%, #<?php echo $this->_getGradientEndColour(); ?> 100%); /* FF3.6+ */
|
4 |
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#<?php echo $this->_getGradientStartColour(); ?>), color-stop(100%,#<?php echo $this->_getGradientEndColour(); ?>)); /* Chrome,Safari4+ */
|
5 |
+
background: -webkit-linear-gradient(top, #<?php echo $this->_getGradientStartColour(); ?> 0%,#<?php echo $this->_getGradientEndColour(); ?> 100%); /* Chrome10+,Safari5.1+ */
|
6 |
+
background: -o-linear-gradient(top, #<?php echo $this->_getGradientStartColour(); ?> 0%,#<?php echo $this->_getGradientEndColour(); ?> 100%); /* Opera 11.10+ */
|
7 |
+
background: -ms-linear-gradient(top, #<?php echo $this->_getGradientStartColour(); ?> 0%,#<?php echo $this->_getGradientEndColour(); ?> 100%); /* IE10+ */
|
8 |
+
background: linear-gradient(to bottom, #<?php echo $this->_getGradientStartColour(); ?> 0%,#<?php echo $this->_getGradientEndColour(); ?> 100%); /* W3C */
|
9 |
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#<?php echo $this->_getGradientStartColour(); ?>', endColorstr='#<?php echo $this->_getGradientEndColour(); ?>',GradientType=0 ); /* IE6-8 */
|
10 |
+
color: #<?php echo $this->_getContrastColourBW($this->_getColour()); ?>;
|
11 |
+
border-color: #<?php echo $this->_getColour(); ?>;
|
12 |
+
}
|
13 |
+
#cloudiq-callme-popup.<?php echo $this->_getTemplateClass(); ?> button {
|
14 |
+
background-color: #<?php echo $this->_getColour(); ?>;
|
15 |
+
color: #<?php echo $this->_getContrastColourBW($this->_getColour()); ?>;
|
16 |
+
}
|
17 |
+
</style>
|
18 |
+
<div id="cloudiq-callme-button" class="<?php echo $this->_getButtonClass(); ?>">
|
19 |
+
<p id="cloudiq-callme-button-title"><?php echo $this->_getFromConfig("button_heading"); ?></p>
|
20 |
+
<p id="cloudiq-callme-button-message"><?php echo $this->_getFromConfig("button_message"); ?></p>
|
21 |
+
</div>
|
22 |
+
<div id="cloudiq-callme-popup" class="<?php echo $this->_getPopupClass(); ?>">
|
23 |
+
<div id="cloudiq-callme-popup-close">×</div>
|
24 |
+
<?php if ($this->_getLogoUrl()) : ?>
|
25 |
+
<img id="cloudiq-callme-popup-logo" src="<?php echo $this->_getLogoUrl(); ?>" alt="Logo" />
|
26 |
+
<?php endif; ?>
|
27 |
+
<p id="cloudiq-callme-popup-title"><?php echo $this->_getFromConfig("pop_up_title"); ?></p>
|
28 |
+
<p id="cloudiq-callme-popup-strapline"><?php echo $this->_getFromConfig("pop_up_strapline"); ?></p>
|
29 |
+
<form id="cloudiq-callme-popup-form" name="cloudiq-callme-popup-form" method="POST" action="<?php echo $this->_getFormUrl(); ?>">
|
30 |
+
<label for="cloudiq-callme-popup-form-number">Mobile number</label>
|
31 |
+
<input type="text" name="phone_number" id="cloudiq-callme-popup-form-number" />
|
32 |
+
<button type="submit" <?php if ($this->getDisabled()) echo "disabled"; ?>>Submit</button>
|
33 |
+
</form>
|
34 |
+
<div id="cloudiq-callme-popup-response"></div>
|
35 |
+
</div>
|
36 |
+
<script>cloudiqCallmeInit()</script>
|
app/etc/modules/Cloudiq_Callme.xml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Cloudiq_Callme>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
<depends>
|
8 |
+
<Cloudiq_Core/>
|
9 |
+
</depends>
|
10 |
+
</Cloudiq_Callme>
|
11 |
+
</modules>
|
12 |
+
</config>
|
app/etc/modules/Cloudiq_Core.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Cloudiq_Core>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Cloudiq_Core>
|
8 |
+
</modules>
|
9 |
+
</config>
|
app/locale/en_GB/Cloudiq_Callme.csv
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
"callMe API error: Authentication failure","callMe: Failed to log in. Please check that your account is up to date and the account credentials are correct."
|
js/cloudiq/callme-button.js
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function cloudiqCallmeInit() {
|
2 |
+
var callme_button = $('cloudiq-callme-button');
|
3 |
+
var callme_popup = $('cloudiq-callme-popup');
|
4 |
+
var callme_popup_close_button = $('cloudiq-callme-popup-close');
|
5 |
+
var callme_popup_form = $('cloudiq-callme-popup-form');
|
6 |
+
var callme_popup_response = $('cloudiq-callme-popup-response');
|
7 |
+
|
8 |
+
// Position the popup in the centre of the screen
|
9 |
+
callme_popup.setStyle({
|
10 |
+
top: "50%",
|
11 |
+
left: "50%",
|
12 |
+
marginTop: "-" + Math.ceil(callme_popup.getHeight() / 2) + "px",
|
13 |
+
marginLeft: "-" + Math.ceil(callme_popup.getWidth() / 2) + "px"
|
14 |
+
});
|
15 |
+
|
16 |
+
// Toggle the callMe popup when buttons are clicked
|
17 |
+
[callme_button, callme_popup_close_button].each(function (element) {
|
18 |
+
element.observe("click", function () {
|
19 |
+
var display_value = (callme_popup.getStyle("display") == "none") ? "inline-block" : "none";
|
20 |
+
|
21 |
+
// Reset popup elements before displaying it
|
22 |
+
if (display_value != "none") {
|
23 |
+
callme_popup_form.setStyle({display: "block"});
|
24 |
+
callme_popup_response.update("");
|
25 |
+
callme_popup_response.removeClassName("cloudiq-callme-status-success");
|
26 |
+
callme_popup_response.removeClassName("cloudiq-callme-status-failure");
|
27 |
+
}
|
28 |
+
|
29 |
+
callme_popup.setStyle({display: display_value});
|
30 |
+
});
|
31 |
+
});
|
32 |
+
|
33 |
+
// Submit callMe callback request through Ajax
|
34 |
+
callme_popup_form.observe("submit", function (e) {
|
35 |
+
callme_popup_form.request({
|
36 |
+
onComplete: function (transport) {
|
37 |
+
var result;
|
38 |
+
if (transport.request.success()) {
|
39 |
+
result = transport.responseJSON;
|
40 |
+
} else {
|
41 |
+
result = {
|
42 |
+
status: false,
|
43 |
+
message: transport.statusText
|
44 |
+
};
|
45 |
+
}
|
46 |
+
|
47 |
+
// Update the response box
|
48 |
+
var result_class = (result.status) ? "success" : "failure";
|
49 |
+
callme_popup_response.addClassName("cloudiq-callme-status-" + result_class);
|
50 |
+
callme_popup_response.update(result.message);
|
51 |
+
|
52 |
+
// Hide the form
|
53 |
+
callme_popup_form.setStyle({display: "none"});
|
54 |
+
}
|
55 |
+
});
|
56 |
+
e.stop();
|
57 |
+
});
|
58 |
+
}
|
js/cloudiq/callme-jscolor/arrow.gif
ADDED
Binary file
|
js/cloudiq/callme-jscolor/cross.gif
ADDED
Binary file
|
js/cloudiq/callme-jscolor/demo.html
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<html>
|
2 |
+
<head>
|
3 |
+
<title>jscolor demo</title>
|
4 |
+
</head>
|
5 |
+
<body>
|
6 |
+
|
7 |
+
<script type="text/javascript" src="jscolor.js"></script>
|
8 |
+
|
9 |
+
Click here: <input class="color" value="66ff00">
|
10 |
+
|
11 |
+
</body>
|
12 |
+
</html>
|
js/cloudiq/callme-jscolor/hs.png
ADDED
Binary file
|
js/cloudiq/callme-jscolor/hv.png
ADDED
Binary file
|
js/cloudiq/callme-jscolor/jscolor.js
ADDED
@@ -0,0 +1,840 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* jscolor, JavaScript Color Picker
|
3 |
+
*
|
4 |
+
* @version 1.3.1
|
5 |
+
* @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
|
6 |
+
* @author Jan Odvarko, http://odvarko.cz
|
7 |
+
* @created 2008-06-15
|
8 |
+
* @updated 2010-01-23
|
9 |
+
* @link http://jscolor.com
|
10 |
+
*/
|
11 |
+
|
12 |
+
|
13 |
+
var jscolor = {
|
14 |
+
|
15 |
+
|
16 |
+
dir : '', // location of jscolor directory (leave empty to autodetect)
|
17 |
+
bindClass : 'color', // class name
|
18 |
+
binding : true, // automatic binding via <input class="...">
|
19 |
+
preloading : true, // use image preloading?
|
20 |
+
|
21 |
+
|
22 |
+
install : function() {
|
23 |
+
jscolor.addEvent(window, 'load', jscolor.init);
|
24 |
+
},
|
25 |
+
|
26 |
+
|
27 |
+
init : function() {
|
28 |
+
if(jscolor.binding) {
|
29 |
+
jscolor.bind();
|
30 |
+
}
|
31 |
+
if(jscolor.preloading) {
|
32 |
+
jscolor.preload();
|
33 |
+
}
|
34 |
+
},
|
35 |
+
|
36 |
+
|
37 |
+
getDir : function() {
|
38 |
+
if(!jscolor.dir) {
|
39 |
+
var detected = jscolor.detectDir();
|
40 |
+
jscolor.dir = detected!==false ? detected : 'jscolor/';
|
41 |
+
}
|
42 |
+
return jscolor.dir;
|
43 |
+
},
|
44 |
+
|
45 |
+
|
46 |
+
detectDir : function() {
|
47 |
+
var base = location.href;
|
48 |
+
|
49 |
+
var e = document.getElementsByTagName('base');
|
50 |
+
for(var i=0; i<e.length; i+=1) {
|
51 |
+
if(e[i].href) { base = e[i].href; }
|
52 |
+
}
|
53 |
+
|
54 |
+
var e = document.getElementsByTagName('script');
|
55 |
+
for(var i=0; i<e.length; i+=1) {
|
56 |
+
if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
|
57 |
+
var src = new jscolor.URI(e[i].src);
|
58 |
+
var srcAbs = src.toAbsolute(base);
|
59 |
+
srcAbs.path = srcAbs.path.replace(/[^\/]+$/, ''); // remove filename
|
60 |
+
srcAbs.query = null;
|
61 |
+
srcAbs.fragment = null;
|
62 |
+
return srcAbs.toString();
|
63 |
+
}
|
64 |
+
}
|
65 |
+
return false;
|
66 |
+
},
|
67 |
+
|
68 |
+
|
69 |
+
bind : function() {
|
70 |
+
var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i');
|
71 |
+
var e = document.getElementsByTagName('input');
|
72 |
+
for(var i=0; i<e.length; i+=1) {
|
73 |
+
var m;
|
74 |
+
if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
|
75 |
+
var prop = {};
|
76 |
+
if(m[3]) {
|
77 |
+
try {
|
78 |
+
eval('prop='+m[3]);
|
79 |
+
} catch(eInvalidProp) {}
|
80 |
+
}
|
81 |
+
e[i].color = new jscolor.color(e[i], prop);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
},
|
85 |
+
|
86 |
+
|
87 |
+
preload : function() {
|
88 |
+
for(var fn in jscolor.imgRequire) {
|
89 |
+
if(jscolor.imgRequire.hasOwnProperty(fn)) {
|
90 |
+
jscolor.loadImage(fn);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
},
|
94 |
+
|
95 |
+
|
96 |
+
images : {
|
97 |
+
pad : [ 181, 101 ],
|
98 |
+
sld : [ 16, 101 ],
|
99 |
+
cross : [ 15, 15 ],
|
100 |
+
arrow : [ 7, 11 ]
|
101 |
+
},
|
102 |
+
|
103 |
+
|
104 |
+
imgRequire : {},
|
105 |
+
imgLoaded : {},
|
106 |
+
|
107 |
+
|
108 |
+
requireImage : function(filename) {
|
109 |
+
jscolor.imgRequire[filename] = true;
|
110 |
+
},
|
111 |
+
|
112 |
+
|
113 |
+
loadImage : function(filename) {
|
114 |
+
if(!jscolor.imgLoaded[filename]) {
|
115 |
+
jscolor.imgLoaded[filename] = new Image();
|
116 |
+
jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
|
117 |
+
}
|
118 |
+
},
|
119 |
+
|
120 |
+
|
121 |
+
fetchElement : function(mixed) {
|
122 |
+
return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
|
123 |
+
},
|
124 |
+
|
125 |
+
|
126 |
+
addEvent : function(el, evnt, func) {
|
127 |
+
if(el.addEventListener) {
|
128 |
+
el.addEventListener(evnt, func, false);
|
129 |
+
} else if(el.attachEvent) {
|
130 |
+
el.attachEvent('on'+evnt, func);
|
131 |
+
}
|
132 |
+
},
|
133 |
+
|
134 |
+
|
135 |
+
fireEvent : function(el, evnt) {
|
136 |
+
if(!el) {
|
137 |
+
return;
|
138 |
+
}
|
139 |
+
if(document.createEventObject) {
|
140 |
+
var ev = document.createEventObject();
|
141 |
+
el.fireEvent('on'+evnt, ev);
|
142 |
+
} else if(document.createEvent) {
|
143 |
+
var ev = document.createEvent('HTMLEvents');
|
144 |
+
ev.initEvent(evnt, true, true);
|
145 |
+
el.dispatchEvent(ev);
|
146 |
+
} else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
|
147 |
+
el['on'+evnt]();
|
148 |
+
}
|
149 |
+
},
|
150 |
+
|
151 |
+
|
152 |
+
getElementPos : function(e) {
|
153 |
+
var e1=e, e2=e;
|
154 |
+
var x=0, y=0;
|
155 |
+
if(e1.offsetParent) {
|
156 |
+
do {
|
157 |
+
x += e1.offsetLeft;
|
158 |
+
y += e1.offsetTop;
|
159 |
+
} while(e1 = e1.offsetParent);
|
160 |
+
}
|
161 |
+
while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
|
162 |
+
x -= e2.scrollLeft;
|
163 |
+
y -= e2.scrollTop;
|
164 |
+
}
|
165 |
+
return [x, y];
|
166 |
+
},
|
167 |
+
|
168 |
+
|
169 |
+
getElementSize : function(e) {
|
170 |
+
return [e.offsetWidth, e.offsetHeight];
|
171 |
+
},
|
172 |
+
|
173 |
+
|
174 |
+
getMousePos : function(e) {
|
175 |
+
if(!e) { e = window.event; }
|
176 |
+
if(typeof e.pageX === 'number') {
|
177 |
+
return [e.pageX, e.pageY];
|
178 |
+
} else if(typeof e.clientX === 'number') {
|
179 |
+
return [
|
180 |
+
e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
|
181 |
+
e.clientY + document.body.scrollTop + document.documentElement.scrollTop
|
182 |
+
];
|
183 |
+
}
|
184 |
+
},
|
185 |
+
|
186 |
+
|
187 |
+
getViewPos : function() {
|
188 |
+
if(typeof window.pageYOffset === 'number') {
|
189 |
+
return [window.pageXOffset, window.pageYOffset];
|
190 |
+
} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
|
191 |
+
return [document.body.scrollLeft, document.body.scrollTop];
|
192 |
+
} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
|
193 |
+
return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
|
194 |
+
} else {
|
195 |
+
return [0, 0];
|
196 |
+
}
|
197 |
+
},
|
198 |
+
|
199 |
+
|
200 |
+
getViewSize : function() {
|
201 |
+
if(typeof window.innerWidth === 'number') {
|
202 |
+
return [window.innerWidth, window.innerHeight];
|
203 |
+
} else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
|
204 |
+
return [document.body.clientWidth, document.body.clientHeight];
|
205 |
+
} else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
|
206 |
+
return [document.documentElement.clientWidth, document.documentElement.clientHeight];
|
207 |
+
} else {
|
208 |
+
return [0, 0];
|
209 |
+
}
|
210 |
+
},
|
211 |
+
|
212 |
+
|
213 |
+
URI : function(uri) { // See RFC3986
|
214 |
+
|
215 |
+
this.scheme = null;
|
216 |
+
this.authority = null;
|
217 |
+
this.path = '';
|
218 |
+
this.query = null;
|
219 |
+
this.fragment = null;
|
220 |
+
|
221 |
+
this.parse = function(uri) {
|
222 |
+
var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
|
223 |
+
this.scheme = m[3] ? m[2] : null;
|
224 |
+
this.authority = m[5] ? m[6] : null;
|
225 |
+
this.path = m[7];
|
226 |
+
this.query = m[9] ? m[10] : null;
|
227 |
+
this.fragment = m[12] ? m[13] : null;
|
228 |
+
return this;
|
229 |
+
};
|
230 |
+
|
231 |
+
this.toString = function() {
|
232 |
+
var result = '';
|
233 |
+
if(this.scheme !== null) { result = result + this.scheme + ':'; }
|
234 |
+
if(this.authority !== null) { result = result + '//' + this.authority; }
|
235 |
+
if(this.path !== null) { result = result + this.path; }
|
236 |
+
if(this.query !== null) { result = result + '?' + this.query; }
|
237 |
+
if(this.fragment !== null) { result = result + '#' + this.fragment; }
|
238 |
+
return result;
|
239 |
+
};
|
240 |
+
|
241 |
+
this.toAbsolute = function(base) {
|
242 |
+
var base = new jscolor.URI(base);
|
243 |
+
var r = this;
|
244 |
+
var t = new jscolor.URI;
|
245 |
+
|
246 |
+
if(base.scheme === null) { return false; }
|
247 |
+
|
248 |
+
if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
|
249 |
+
r.scheme = null;
|
250 |
+
}
|
251 |
+
|
252 |
+
if(r.scheme !== null) {
|
253 |
+
t.scheme = r.scheme;
|
254 |
+
t.authority = r.authority;
|
255 |
+
t.path = removeDotSegments(r.path);
|
256 |
+
t.query = r.query;
|
257 |
+
} else {
|
258 |
+
if(r.authority !== null) {
|
259 |
+
t.authority = r.authority;
|
260 |
+
t.path = removeDotSegments(r.path);
|
261 |
+
t.query = r.query;
|
262 |
+
} else {
|
263 |
+
if(r.path === '') { // TODO: == or === ?
|
264 |
+
t.path = base.path;
|
265 |
+
if(r.query !== null) {
|
266 |
+
t.query = r.query;
|
267 |
+
} else {
|
268 |
+
t.query = base.query;
|
269 |
+
}
|
270 |
+
} else {
|
271 |
+
if(r.path.substr(0,1) === '/') {
|
272 |
+
t.path = removeDotSegments(r.path);
|
273 |
+
} else {
|
274 |
+
if(base.authority !== null && base.path === '') { // TODO: == or === ?
|
275 |
+
t.path = '/'+r.path;
|
276 |
+
} else {
|
277 |
+
t.path = base.path.replace(/[^\/]+$/,'')+r.path;
|
278 |
+
}
|
279 |
+
t.path = removeDotSegments(t.path);
|
280 |
+
}
|
281 |
+
t.query = r.query;
|
282 |
+
}
|
283 |
+
t.authority = base.authority;
|
284 |
+
}
|
285 |
+
t.scheme = base.scheme;
|
286 |
+
}
|
287 |
+
t.fragment = r.fragment;
|
288 |
+
|
289 |
+
return t;
|
290 |
+
};
|
291 |
+
|
292 |
+
function removeDotSegments(path) {
|
293 |
+
var out = '';
|
294 |
+
while(path) {
|
295 |
+
if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
|
296 |
+
path = path.replace(/^\.+/,'').substr(1);
|
297 |
+
} else if(path.substr(0,3)==='/./' || path==='/.') {
|
298 |
+
path = '/'+path.substr(3);
|
299 |
+
} else if(path.substr(0,4)==='/../' || path==='/..') {
|
300 |
+
path = '/'+path.substr(4);
|
301 |
+
out = out.replace(/\/?[^\/]*$/, '');
|
302 |
+
} else if(path==='.' || path==='..') {
|
303 |
+
path = '';
|
304 |
+
} else {
|
305 |
+
var rm = path.match(/^\/?[^\/]*/)[0];
|
306 |
+
path = path.substr(rm.length);
|
307 |
+
out = out + rm;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
return out;
|
311 |
+
}
|
312 |
+
|
313 |
+
if(uri) {
|
314 |
+
this.parse(uri);
|
315 |
+
}
|
316 |
+
|
317 |
+
},
|
318 |
+
|
319 |
+
|
320 |
+
/*
|
321 |
+
* Usage example:
|
322 |
+
* var myColor = new jscolor.color(myInputElement)
|
323 |
+
*/
|
324 |
+
|
325 |
+
color : function(target, prop) {
|
326 |
+
|
327 |
+
|
328 |
+
this.required = true; // refuse empty values?
|
329 |
+
this.adjust = true; // adjust value to uniform notation?
|
330 |
+
this.hash = false; // prefix color with # symbol?
|
331 |
+
this.caps = true; // uppercase?
|
332 |
+
this.valueElement = target; // value holder
|
333 |
+
this.styleElement = target; // where to reflect current color
|
334 |
+
this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1
|
335 |
+
this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1
|
336 |
+
|
337 |
+
this.pickerOnfocus = true; // display picker on focus?
|
338 |
+
this.pickerMode = 'HSV'; // HSV | HVS
|
339 |
+
this.pickerPosition = 'bottom'; // left | right | top | bottom
|
340 |
+
this.pickerFace = 10; // px
|
341 |
+
this.pickerFaceColor = 'ThreeDFace'; // CSS color
|
342 |
+
this.pickerBorder = 1; // px
|
343 |
+
this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
|
344 |
+
this.pickerInset = 1; // px
|
345 |
+
this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
|
346 |
+
this.pickerZIndex = 10000;
|
347 |
+
|
348 |
+
|
349 |
+
for(var p in prop) {
|
350 |
+
if(prop.hasOwnProperty(p)) {
|
351 |
+
this[p] = prop[p];
|
352 |
+
}
|
353 |
+
}
|
354 |
+
|
355 |
+
|
356 |
+
this.hidePicker = function() {
|
357 |
+
if(isPickerOwner()) {
|
358 |
+
removePicker();
|
359 |
+
}
|
360 |
+
};
|
361 |
+
|
362 |
+
|
363 |
+
this.showPicker = function() {
|
364 |
+
if(!isPickerOwner()) {
|
365 |
+
var tp = jscolor.getElementPos(target); // target pos
|
366 |
+
var ts = jscolor.getElementSize(target); // target size
|
367 |
+
var vp = jscolor.getViewPos(); // view pos
|
368 |
+
var vs = jscolor.getViewSize(); // view size
|
369 |
+
var ps = [ // picker size
|
370 |
+
2*this.pickerBorder + 4*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0],
|
371 |
+
2*this.pickerBorder + 2*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[1]
|
372 |
+
];
|
373 |
+
var a, b, c;
|
374 |
+
switch(this.pickerPosition.toLowerCase()) {
|
375 |
+
case 'left': a=1; b=0; c=-1; break;
|
376 |
+
case 'right':a=1; b=0; c=1; break;
|
377 |
+
case 'top': a=0; b=1; c=-1; break;
|
378 |
+
default: a=0; b=1; c=1; break;
|
379 |
+
}
|
380 |
+
var l = (ts[b]+ps[b])/2;
|
381 |
+
var pp = [ // picker pos
|
382 |
+
-vp[a]+tp[a]+ps[a] > vs[a] ?
|
383 |
+
(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
|
384 |
+
tp[a],
|
385 |
+
-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
|
386 |
+
(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
|
387 |
+
(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
|
388 |
+
];
|
389 |
+
drawPicker(pp[a], pp[b]);
|
390 |
+
}
|
391 |
+
};
|
392 |
+
|
393 |
+
|
394 |
+
this.importColor = function() {
|
395 |
+
if(!valueElement) {
|
396 |
+
this.exportColor();
|
397 |
+
} else {
|
398 |
+
if(!this.adjust) {
|
399 |
+
if(!this.fromString(valueElement.value, leaveValue)) {
|
400 |
+
styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
|
401 |
+
styleElement.style.color = styleElement.jscStyle.color;
|
402 |
+
this.exportColor(leaveValue | leaveStyle);
|
403 |
+
}
|
404 |
+
} else if(!this.required && /^\s*$/.test(valueElement.value)) {
|
405 |
+
valueElement.value = '';
|
406 |
+
styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
|
407 |
+
styleElement.style.color = styleElement.jscStyle.color;
|
408 |
+
this.exportColor(leaveValue | leaveStyle);
|
409 |
+
|
410 |
+
} else if(this.fromString(valueElement.value)) {
|
411 |
+
// OK
|
412 |
+
} else {
|
413 |
+
this.exportColor();
|
414 |
+
}
|
415 |
+
}
|
416 |
+
};
|
417 |
+
|
418 |
+
|
419 |
+
this.exportColor = function(flags) {
|
420 |
+
if(!(flags & leaveValue) && valueElement) {
|
421 |
+
var value = this.toString();
|
422 |
+
if(this.caps) { value = value.toUpperCase(); }
|
423 |
+
if(this.hash) { value = '#'+value; }
|
424 |
+
valueElement.value = value;
|
425 |
+
}
|
426 |
+
if(!(flags & leaveStyle) && styleElement) {
|
427 |
+
styleElement.style.backgroundColor =
|
428 |
+
'#'+this.toString();
|
429 |
+
styleElement.style.color =
|
430 |
+
0.213 * this.rgb[0] +
|
431 |
+
0.715 * this.rgb[1] +
|
432 |
+
0.072 * this.rgb[2]
|
433 |
+
< 0.5 ? '#FFF' : '#000';
|
434 |
+
}
|
435 |
+
if(!(flags & leavePad) && isPickerOwner()) {
|
436 |
+
redrawPad();
|
437 |
+
}
|
438 |
+
if(!(flags & leaveSld) && isPickerOwner()) {
|
439 |
+
redrawSld();
|
440 |
+
}
|
441 |
+
};
|
442 |
+
|
443 |
+
|
444 |
+
this.fromHSV = function(h, s, v, flags) { // null = don't change
|
445 |
+
h<0 && (h=0) || h>6 && (h=6);
|
446 |
+
s<0 && (s=0) || s>1 && (s=1);
|
447 |
+
v<0 && (v=0) || v>1 && (v=1);
|
448 |
+
this.rgb = HSV_RGB(
|
449 |
+
h===null ? this.hsv[0] : (this.hsv[0]=h),
|
450 |
+
s===null ? this.hsv[1] : (this.hsv[1]=s),
|
451 |
+
v===null ? this.hsv[2] : (this.hsv[2]=v)
|
452 |
+
);
|
453 |
+
this.exportColor(flags);
|
454 |
+
};
|
455 |
+
|
456 |
+
|
457 |
+
this.fromRGB = function(r, g, b, flags) { // null = don't change
|
458 |
+
r<0 && (r=0) || r>1 && (r=1);
|
459 |
+
g<0 && (g=0) || g>1 && (g=1);
|
460 |
+
b<0 && (b=0) || b>1 && (b=1);
|
461 |
+
var hsv = RGB_HSV(
|
462 |
+
r===null ? this.rgb[0] : (this.rgb[0]=r),
|
463 |
+
g===null ? this.rgb[1] : (this.rgb[1]=g),
|
464 |
+
b===null ? this.rgb[2] : (this.rgb[2]=b)
|
465 |
+
);
|
466 |
+
if(hsv[0] !== null) {
|
467 |
+
this.hsv[0] = hsv[0];
|
468 |
+
}
|
469 |
+
if(hsv[2] !== 0) {
|
470 |
+
this.hsv[1] = hsv[1];
|
471 |
+
}
|
472 |
+
this.hsv[2] = hsv[2];
|
473 |
+
this.exportColor(flags);
|
474 |
+
};
|
475 |
+
|
476 |
+
|
477 |
+
this.fromString = function(hex, flags) {
|
478 |
+
var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
|
479 |
+
if(!m) {
|
480 |
+
return false;
|
481 |
+
} else {
|
482 |
+
if(m[1].length === 6) { // 6-char notation
|
483 |
+
this.fromRGB(
|
484 |
+
parseInt(m[1].substr(0,2),16) / 255,
|
485 |
+
parseInt(m[1].substr(2,2),16) / 255,
|
486 |
+
parseInt(m[1].substr(4,2),16) / 255,
|
487 |
+
flags
|
488 |
+
);
|
489 |
+
} else { // 3-char notation
|
490 |
+
this.fromRGB(
|
491 |
+
parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
|
492 |
+
parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
|
493 |
+
parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
|
494 |
+
flags
|
495 |
+
);
|
496 |
+
}
|
497 |
+
return true;
|
498 |
+
}
|
499 |
+
};
|
500 |
+
|
501 |
+
|
502 |
+
this.toString = function() {
|
503 |
+
return (
|
504 |
+
(0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
|
505 |
+
(0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
|
506 |
+
(0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
|
507 |
+
);
|
508 |
+
};
|
509 |
+
|
510 |
+
|
511 |
+
function RGB_HSV(r, g, b) {
|
512 |
+
var n = Math.min(Math.min(r,g),b);
|
513 |
+
var v = Math.max(Math.max(r,g),b);
|
514 |
+
var m = v - n;
|
515 |
+
if(m === 0) { return [ null, 0, v ]; }
|
516 |
+
var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
|
517 |
+
return [ h===6?0:h, m/v, v ];
|
518 |
+
}
|
519 |
+
|
520 |
+
|
521 |
+
function HSV_RGB(h, s, v) {
|
522 |
+
if(h === null) { return [ v, v, v ]; }
|
523 |
+
var i = Math.floor(h);
|
524 |
+
var f = i%2 ? h-i : 1-(h-i);
|
525 |
+
var m = v * (1 - s);
|
526 |
+
var n = v * (1 - s*f);
|
527 |
+
switch(i) {
|
528 |
+
case 6:
|
529 |
+
case 0: return [v,n,m];
|
530 |
+
case 1: return [n,v,m];
|
531 |
+
case 2: return [m,v,n];
|
532 |
+
case 3: return [m,n,v];
|
533 |
+
case 4: return [n,m,v];
|
534 |
+
case 5: return [v,m,n];
|
535 |
+
}
|
536 |
+
}
|
537 |
+
|
538 |
+
|
539 |
+
function removePicker() {
|
540 |
+
delete jscolor.picker.owner;
|
541 |
+
document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
|
542 |
+
}
|
543 |
+
|
544 |
+
|
545 |
+
function drawPicker(x, y) {
|
546 |
+
if(!jscolor.picker) {
|
547 |
+
jscolor.picker = {
|
548 |
+
box : document.createElement('div'),
|
549 |
+
boxB : document.createElement('div'),
|
550 |
+
pad : document.createElement('div'),
|
551 |
+
padB : document.createElement('div'),
|
552 |
+
padM : document.createElement('div'),
|
553 |
+
sld : document.createElement('div'),
|
554 |
+
sldB : document.createElement('div'),
|
555 |
+
sldM : document.createElement('div')
|
556 |
+
};
|
557 |
+
for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
|
558 |
+
var seg = document.createElement('div');
|
559 |
+
seg.style.height = segSize+'px';
|
560 |
+
seg.style.fontSize = '1px';
|
561 |
+
seg.style.lineHeight = '0';
|
562 |
+
jscolor.picker.sld.appendChild(seg);
|
563 |
+
}
|
564 |
+
jscolor.picker.sldB.appendChild(jscolor.picker.sld);
|
565 |
+
jscolor.picker.box.appendChild(jscolor.picker.sldB);
|
566 |
+
jscolor.picker.box.appendChild(jscolor.picker.sldM);
|
567 |
+
jscolor.picker.padB.appendChild(jscolor.picker.pad);
|
568 |
+
jscolor.picker.box.appendChild(jscolor.picker.padB);
|
569 |
+
jscolor.picker.box.appendChild(jscolor.picker.padM);
|
570 |
+
jscolor.picker.boxB.appendChild(jscolor.picker.box);
|
571 |
+
}
|
572 |
+
|
573 |
+
var p = jscolor.picker;
|
574 |
+
|
575 |
+
// recompute controls positions
|
576 |
+
posPad = [
|
577 |
+
x+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset,
|
578 |
+
y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];
|
579 |
+
posSld = [
|
580 |
+
null,
|
581 |
+
y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];
|
582 |
+
|
583 |
+
// controls interaction
|
584 |
+
p.box.onmouseup =
|
585 |
+
p.box.onmouseout = function() { target.focus(); };
|
586 |
+
p.box.onmousedown = function() { abortBlur=true; };
|
587 |
+
p.box.onmousemove = function(e) { holdPad && setPad(e); holdSld && setSld(e); };
|
588 |
+
p.padM.onmouseup =
|
589 |
+
p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } };
|
590 |
+
p.padM.onmousedown = function(e) { holdPad=true; setPad(e); };
|
591 |
+
p.sldM.onmouseup =
|
592 |
+
p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } };
|
593 |
+
p.sldM.onmousedown = function(e) { holdSld=true; setSld(e); };
|
594 |
+
|
595 |
+
// picker
|
596 |
+
p.box.style.width = 4*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] + 'px';
|
597 |
+
p.box.style.height = 2*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[1] + 'px';
|
598 |
+
|
599 |
+
// picker border
|
600 |
+
p.boxB.style.position = 'absolute';
|
601 |
+
p.boxB.style.clear = 'both';
|
602 |
+
p.boxB.style.left = x+'px';
|
603 |
+
p.boxB.style.top = y+'px';
|
604 |
+
p.boxB.style.zIndex = THIS.pickerZIndex;
|
605 |
+
p.boxB.style.border = THIS.pickerBorder+'px solid';
|
606 |
+
p.boxB.style.borderColor = THIS.pickerBorderColor;
|
607 |
+
p.boxB.style.background = THIS.pickerFaceColor;
|
608 |
+
|
609 |
+
// pad image
|
610 |
+
p.pad.style.width = jscolor.images.pad[0]+'px';
|
611 |
+
p.pad.style.height = jscolor.images.pad[1]+'px';
|
612 |
+
|
613 |
+
// pad border
|
614 |
+
p.padB.style.position = 'absolute';
|
615 |
+
p.padB.style.left = THIS.pickerFace+'px';
|
616 |
+
p.padB.style.top = THIS.pickerFace+'px';
|
617 |
+
p.padB.style.border = THIS.pickerInset+'px solid';
|
618 |
+
p.padB.style.borderColor = THIS.pickerInsetColor;
|
619 |
+
|
620 |
+
// pad mouse area
|
621 |
+
p.padM.style.position = 'absolute';
|
622 |
+
p.padM.style.left = '0';
|
623 |
+
p.padM.style.top = '0';
|
624 |
+
p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
|
625 |
+
p.padM.style.height = p.box.style.height;
|
626 |
+
p.padM.style.cursor = 'crosshair';
|
627 |
+
|
628 |
+
// slider image
|
629 |
+
p.sld.style.overflow = 'hidden';
|
630 |
+
p.sld.style.width = jscolor.images.sld[0]+'px';
|
631 |
+
p.sld.style.height = jscolor.images.sld[1]+'px';
|
632 |
+
|
633 |
+
// slider border
|
634 |
+
p.sldB.style.position = 'absolute';
|
635 |
+
p.sldB.style.right = THIS.pickerFace+'px';
|
636 |
+
p.sldB.style.top = THIS.pickerFace+'px';
|
637 |
+
p.sldB.style.border = THIS.pickerInset+'px solid';
|
638 |
+
p.sldB.style.borderColor = THIS.pickerInsetColor;
|
639 |
+
|
640 |
+
// slider mouse area
|
641 |
+
p.sldM.style.position = 'absolute';
|
642 |
+
p.sldM.style.right = '0';
|
643 |
+
p.sldM.style.top = '0';
|
644 |
+
p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
|
645 |
+
p.sldM.style.height = p.box.style.height;
|
646 |
+
try {
|
647 |
+
p.sldM.style.cursor = 'pointer';
|
648 |
+
} catch(eOldIE) {
|
649 |
+
p.sldM.style.cursor = 'hand';
|
650 |
+
}
|
651 |
+
|
652 |
+
// load images in optimal order
|
653 |
+
switch(modeID) {
|
654 |
+
case 0: var padImg = 'hs.png'; break;
|
655 |
+
case 1: var padImg = 'hv.png'; break;
|
656 |
+
}
|
657 |
+
p.padM.style.background = "url('"+jscolor.getDir()+"cross.gif') no-repeat";
|
658 |
+
p.sldM.style.background = "url('"+jscolor.getDir()+"arrow.gif') no-repeat";
|
659 |
+
p.pad.style.background = "url('"+jscolor.getDir()+padImg+"') 0 0 no-repeat";
|
660 |
+
|
661 |
+
// place pointers
|
662 |
+
redrawPad();
|
663 |
+
redrawSld();
|
664 |
+
|
665 |
+
jscolor.picker.owner = THIS;
|
666 |
+
document.getElementsByTagName('body')[0].appendChild(p.boxB);
|
667 |
+
}
|
668 |
+
|
669 |
+
|
670 |
+
function redrawPad() {
|
671 |
+
// redraw the pad pointer
|
672 |
+
switch(modeID) {
|
673 |
+
case 0: var yComponent = 1; break;
|
674 |
+
case 1: var yComponent = 2; break;
|
675 |
+
}
|
676 |
+
var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
|
677 |
+
var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
|
678 |
+
jscolor.picker.padM.style.backgroundPosition =
|
679 |
+
(THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
|
680 |
+
(THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';
|
681 |
+
|
682 |
+
// redraw the slider image
|
683 |
+
var seg = jscolor.picker.sld.childNodes;
|
684 |
+
|
685 |
+
switch(modeID) {
|
686 |
+
case 0:
|
687 |
+
var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
|
688 |
+
for(var i=0; i<seg.length; i+=1) {
|
689 |
+
seg[i].style.backgroundColor = 'rgb('+
|
690 |
+
(rgb[0]*(1-i/seg.length)*100)+'%,'+
|
691 |
+
(rgb[1]*(1-i/seg.length)*100)+'%,'+
|
692 |
+
(rgb[2]*(1-i/seg.length)*100)+'%)';
|
693 |
+
}
|
694 |
+
break;
|
695 |
+
case 1:
|
696 |
+
var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
|
697 |
+
var i = Math.floor(THIS.hsv[0]);
|
698 |
+
var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
|
699 |
+
switch(i) {
|
700 |
+
case 6:
|
701 |
+
case 0: rgb=[0,1,2]; break;
|
702 |
+
case 1: rgb=[1,0,2]; break;
|
703 |
+
case 2: rgb=[2,0,1]; break;
|
704 |
+
case 3: rgb=[2,1,0]; break;
|
705 |
+
case 4: rgb=[1,2,0]; break;
|
706 |
+
case 5: rgb=[0,2,1]; break;
|
707 |
+
}
|
708 |
+
for(var i=0; i<seg.length; i+=1) {
|
709 |
+
s = 1 - 1/(seg.length-1)*i;
|
710 |
+
c[1] = c[0] * (1 - s*f);
|
711 |
+
c[2] = c[0] * (1 - s);
|
712 |
+
seg[i].style.backgroundColor = 'rgb('+
|
713 |
+
(c[rgb[0]]*100)+'%,'+
|
714 |
+
(c[rgb[1]]*100)+'%,'+
|
715 |
+
(c[rgb[2]]*100)+'%)';
|
716 |
+
}
|
717 |
+
break;
|
718 |
+
}
|
719 |
+
}
|
720 |
+
|
721 |
+
|
722 |
+
function redrawSld() {
|
723 |
+
// redraw the slider pointer
|
724 |
+
switch(modeID) {
|
725 |
+
case 0: var yComponent = 2; break;
|
726 |
+
case 1: var yComponent = 1; break;
|
727 |
+
}
|
728 |
+
var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
|
729 |
+
jscolor.picker.sldM.style.backgroundPosition =
|
730 |
+
'0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
|
731 |
+
}
|
732 |
+
|
733 |
+
|
734 |
+
function isPickerOwner() {
|
735 |
+
return jscolor.picker && jscolor.picker.owner === THIS;
|
736 |
+
}
|
737 |
+
|
738 |
+
|
739 |
+
function blurTarget() {
|
740 |
+
if(valueElement === target) {
|
741 |
+
THIS.importColor();
|
742 |
+
}
|
743 |
+
if(THIS.pickerOnfocus) {
|
744 |
+
THIS.hidePicker();
|
745 |
+
}
|
746 |
+
}
|
747 |
+
|
748 |
+
|
749 |
+
function blurValue() {
|
750 |
+
if(valueElement !== target) {
|
751 |
+
THIS.importColor();
|
752 |
+
}
|
753 |
+
}
|
754 |
+
|
755 |
+
|
756 |
+
function setPad(e) {
|
757 |
+
var posM = jscolor.getMousePos(e);
|
758 |
+
var x = posM[0]-posPad[0];
|
759 |
+
var y = posM[1]-posPad[1];
|
760 |
+
switch(modeID) {
|
761 |
+
case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
|
762 |
+
case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
|
763 |
+
}
|
764 |
+
}
|
765 |
+
|
766 |
+
|
767 |
+
function setSld(e) {
|
768 |
+
var posM = jscolor.getMousePos(e);
|
769 |
+
var y = posM[1]-posPad[1];
|
770 |
+
switch(modeID) {
|
771 |
+
case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
|
772 |
+
case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
|
773 |
+
}
|
774 |
+
}
|
775 |
+
|
776 |
+
|
777 |
+
var THIS = this;
|
778 |
+
var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
|
779 |
+
var abortBlur = false;
|
780 |
+
var
|
781 |
+
valueElement = jscolor.fetchElement(this.valueElement),
|
782 |
+
styleElement = jscolor.fetchElement(this.styleElement);
|
783 |
+
var
|
784 |
+
holdPad = false,
|
785 |
+
holdSld = false;
|
786 |
+
var
|
787 |
+
posPad,
|
788 |
+
posSld;
|
789 |
+
var
|
790 |
+
leaveValue = 1<<0,
|
791 |
+
leaveStyle = 1<<1,
|
792 |
+
leavePad = 1<<2,
|
793 |
+
leaveSld = 1<<3;
|
794 |
+
|
795 |
+
// target
|
796 |
+
jscolor.addEvent(target, 'focus', function() {
|
797 |
+
if(THIS.pickerOnfocus) { THIS.showPicker(); }
|
798 |
+
});
|
799 |
+
jscolor.addEvent(target, 'blur', function() {
|
800 |
+
if(!abortBlur) {
|
801 |
+
window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
|
802 |
+
} else {
|
803 |
+
abortBlur = false;
|
804 |
+
}
|
805 |
+
});
|
806 |
+
|
807 |
+
// valueElement
|
808 |
+
if(valueElement) {
|
809 |
+
var updateField = function() {
|
810 |
+
THIS.fromString(valueElement.value, leaveValue);
|
811 |
+
};
|
812 |
+
jscolor.addEvent(valueElement, 'keyup', updateField);
|
813 |
+
jscolor.addEvent(valueElement, 'input', updateField);
|
814 |
+
jscolor.addEvent(valueElement, 'blur', blurValue);
|
815 |
+
valueElement.setAttribute('autocomplete', 'off');
|
816 |
+
}
|
817 |
+
|
818 |
+
// styleElement
|
819 |
+
if(styleElement) {
|
820 |
+
styleElement.jscStyle = {
|
821 |
+
backgroundColor : styleElement.style.backgroundColor,
|
822 |
+
color : styleElement.style.color
|
823 |
+
};
|
824 |
+
}
|
825 |
+
|
826 |
+
// require images
|
827 |
+
switch(modeID) {
|
828 |
+
case 0: jscolor.requireImage('hs.png'); break;
|
829 |
+
case 1: jscolor.requireImage('hv.png'); break;
|
830 |
+
}
|
831 |
+
jscolor.requireImage('cross.gif');
|
832 |
+
jscolor.requireImage('arrow.gif');
|
833 |
+
|
834 |
+
this.importColor();
|
835 |
+
}
|
836 |
+
|
837 |
+
};
|
838 |
+
|
839 |
+
|
840 |
+
jscolor.install();
|
package.xml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>cloudiq</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://www.cloud-iq.com">Commercial License</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>The callMe extension provides a click-to-call button/service for your website which will automatically connect calls to customers.</summary>
|
10 |
+
<description>Never miss a lead. Convert 10% of your traffic to sales.
|
11 |
+

|
12 |
+
The callMe extension installs a callMe button on your Magento store. It’s beautifully simple to install and use.
|
13 |
+

|
14 |
+
Your visitors can then conveniently input their telephone number for an immediate call back, the service will immediately call you (the business) then instantly connect the customer when you pick up the phone!</description>
|
15 |
+
<notes>You can manage the look and feel of your button. You can schedule call backs to suit your business hours.</notes>
|
16 |
+
<authors><author><name>cloud.IQ</name><user>cloud_iq</user><email>sales@cloud-iq.com</email></author></authors>
|
17 |
+
<date>2013-07-05</date>
|
18 |
+
<time>10:20:44</time>
|
19 |
+
<contents><target name="mageetc"><dir name="modules"><file name="Cloudiq_Callme.xml" hash="e41b3685af06770ec59c90fb9dff6760"/><file name="Cloudiq_Core.xml" hash="cad973564b5dda06d3608f7e51d529e6"/></dir></target><target name="magecommunity"><dir name="Cloudiq"><dir name="Callme"><dir name="Block"><dir name="Adminhtml"><dir name="Config"><dir name="Edit"><dir name="Tab"><file name="Callme.php" hash="b6f541dfa99c1cfbc0148844b742b090"/></dir></dir></dir></dir><file name="Button.php" hash="9053737a38428c9458eba6f34012aeb8"/></dir><dir name="Helper"><file name="Data.php" hash="85b0f590edbd071dadd4dd69f47cf768"/><file name="Options.php" hash="44da04907ac960c206b12c84bdc54850"/></dir><dir name="Model"><dir name="Api"><file name="Callme.php" hash="025cb54a73d4c32f0d80781c772e69a5"/></dir><file name="Config.php" hash="123f7f5b8fc0161e9e94e1c97de74b79"/><file name="Observer.php" hash="a059cbdb977c9c6f7ecb63fd055f8ff8"/><dir name="Resource"><dir name="Config"><file name="Collection.php" hash="c8cb34ede9c8c4ea692a560b47b27025"/></dir><file name="Config.php" hash="f8dfebe59e9f34ee306ea29f188e7bf2"/></dir></dir><dir name="Test"><dir name="Config"><file name="Base.php" hash="8b8b866e1321e1e98e7a4f36a59d2183"/></dir><dir name="Controller"><dir name="Block"><dir name="fixtures"><file name="testCallmeDisabled.yaml" hash="64621424e49f70f56b13857b28268200"/><file name="testCoreDisabled.yaml" hash="4731e31d6f73894232475d7ccbcb7758"/><file name="testDisplayOnAllPages.yaml" hash="81dbaa7b53e28e5d7e5875274dad6ef8"/></dir><dir name="providers"><file name="testDisplayOnAllPages.yaml" hash="c5fb386e2508b360bec626b5acad1076"/></dir></dir><file name="Block.php" hash="87b31a5aa9f2eb7f94f82c4affb9fad9"/></dir><dir name="Helper"><file name="Options.php" hash="431d9ab9633efdbdd0df9ec6e22af9fc"/></dir><dir name="Model"><dir name="Config"><dir name="fixtures"><file name="validConfigObject.yaml" hash="ead7a835c645cbba6e4effe3bc00d864"/></dir><dir name="providers"><file name="testOptionalField.yaml" hash="f253cd136bd4ceacc5f3e07dc936f7db"/><file name="testRequiredField.yaml" hash="63ec4c95468c32b0646eb8e8360097de"/></dir></dir><file name="Config.php" hash="a9b14a2e23922d9638fa12959b1384fb"/></dir></dir><dir name="Varien"><dir name="Data"><dir name="Form"><dir name="Element"><file name="Colourpicker.php" hash="b2f796c6b776291d4820dd355bcd1f7c"/><file name="Openinghours.php" hash="2378bfe07e017eb6e0053443562bbea9"/></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="CallmeController.php" hash="9bc2d43037ea553ee980e32813f17c99"/></dir><file name="CallmeController.php" hash="ea90e4efee01afe4eaaed292abff50b0"/></dir><dir name="etc"><file name="config.xml" hash="4990375a55e13e88c16f4ec8f00fb562"/></dir><dir name="sql"><dir name="cloudiq_callme_setup"><file name="mysql4-install-1.0.0.php" hash="565324b929bcd1cce3813bfbd146a392"/></dir></dir></dir><dir name="Core"><dir name="Block"><dir name="Adminhtml"><dir name="Config"><dir name="Edit"><file name="Form.php" hash="adb6a7430c073ee2930b4d853fb4cfa3"/><dir name="Tab"><file name="Frame.php" hash="5b2f562fb67baf1060eee4c05f67d5da"/><file name="Global.php" hash="46e016a82d206ead0190b45a160df00d"/></dir><file name="Tabs.php" hash="953109aea9e43c0dd960eb9f2aa041f6"/></dir><file name="Edit.php" hash="55f27f8954981871bd7e748f48f9e8c0"/></dir></dir></dir><dir name="Helper"><file name="Config.php" hash="37bd1633ce962c654f0e21818991c191"/><file name="Data.php" hash="528460cf7ec9f942f2f29f6dad1c52f1"/></dir><dir name="Model"><dir name="Api"><file name="Abstract.php" hash="a6df29a5d90cba70242cd36bd0689cd3"/><file name="Core.php" hash="a1c7cfb04097677e5565ce496d558e94"/><file name="Request.php" hash="43bd7500c74d97eac224c23518e3824b"/><file name="Response.php" hash="b977b0f632a7bafa40b52d8d9e0078ac"/></dir></dir><dir name="Test"><dir name="Config"><file name="Base.php" hash="f2e2ca2e59d14048bf46b8c208787793"/></dir><dir name="Model"><dir name="Api"><file name="Response.php" hash="e9d5051331fabfcbe487778ae2c47cc3"/><file name="TestCase.php" hash="2d5114ea542aba75f666b6254390a5d6"/><dir name="data"><dir name="Response"><file name="testWasSuccessfulBadResponseAttribute.txt" hash="7edb6a3d909e8bfb7f04a3450b0fc1c8"/><file name="testWasSuccessfulStatusCodeAndResponseAttribute.txt" hash="14b598d1a6abd984d00cb76fa5351b81"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="CloudiqController.php" hash="4cdb6fc9daf31260c6e020496f7ba557"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="8ee43c9b6d84378c552987e7e980a50d"/><file name="config.xml" hash="d53122159940a78b5f8352355c9f0f99"/></dir><file name=".gitkeep" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="cloudiq"><file name="callme.xml" hash="93aae78cddc91367219762316cf50f9c"/><file name="core.xml" hash="47ca2cb375a8b204080f6cba1cd58074"/></dir></dir><dir name="template"><dir name="cloudiq"><dir name="core"><dir name="tab"><dir name="frame"><file name="iframe.phtml" hash="819fb687981c7054952373f5820824a6"/><file name="submitter.phtml" hash="d0c0dcb6206dd9298630dc564016e24f"/></dir></dir><file name="tabs.phtml" hash="a14de21a37b43d13b4e70b9ef96933c7"/></dir><dir name="global"><file name="tab.phtml" hash="9b7105f44b18bc0d5649658e6e111aaa"/><dir name="widget"><file name="form.phtml" hash="d91ea0fc9b1b2d48068732a3f203610c"/></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="cloudiq"><dir name="callme"><file name="button.phtml" hash="a1497f83bde303bb33cf5ed02328aacb"/></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="cloudiq"><file name="callme.css" hash="9dcffe69220e524ad1a67068313404e0"/><file name="core.css" hash="c22a2fe861358447637a640e75da9076"/><dir name="js"><file name="callme.js" hash="4007f758fde195875608fcaf32f23a7f"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="cloudiq"><dir name="css"><file name="callme-button.css" hash="3feb251dbd7025da16a12f1c122f238e"/></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="cloudiq"><file name="callme-button.js" hash="a39591a5eb8e6b4e8d26f7ec1a5dce63"/><dir name="callme-jscolor"><file name="arrow.gif" hash="5034704a76cd55c1cbcbc58ea6bf523f"/><file name="cross.gif" hash="ba9a274b9323753cd95bc3b1eb2f4e5f"/><file name="demo.html" hash="edf71251cb2be20322d2efb00aee86a6"/><file name="hs.png" hash="fefa1a03d92ebad25c88dca94a0b63db"/><file name="hv.png" hash="990d71cada17da100653636cf8490884"/><file name="jscolor.js" hash="b65a1505390592ac6c0177d6b84774e0"/></dir></dir></dir></target><target name="magelocale"><dir name="en_GB"><file name="Cloudiq_Callme.csv" hash="a056a4403ab97dc4308b9b84a8bcfcfd"/></dir></target></contents>
|
20 |
+
<compatible/>
|
21 |
+
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
22 |
+
</package>
|
skin/adminhtml/default/default/cloudiq/callme.css
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Import button styles for preview
|
3 |
+
*/
|
4 |
+
@import url("../../../../frontend/base/default/cloudiq/css/callme-button.css");
|
5 |
+
|
6 |
+
/* Make the text inputs in the Pop Up section expand to full width */
|
7 |
+
#edit_form #popup.fieldset td.value input {
|
8 |
+
width: 95%;
|
9 |
+
}
|
10 |
+
/*
|
11 |
+
* Openinghours form field styling
|
12 |
+
*/
|
13 |
+
.opening_hours_select > select {
|
14 |
+
display: inline;
|
15 |
+
width: auto !important;
|
16 |
+
margin: 5px;
|
17 |
+
}
|
skin/adminhtml/default/default/cloudiq/core.css
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.cloudiq-banner {
|
2 |
+
padding: 5px 27px 5px 47px;
|
3 |
+
background: rgb(255, 249, 233);
|
4 |
+
border-bottom: 1px solid rgb(238, 226, 190);
|
5 |
+
border-top: 1px solid rgb(238, 226, 190);
|
6 |
+
font-size: 11px;
|
7 |
+
line-height: 16px;
|
8 |
+
margin: 0 0 -3px;
|
9 |
+
color: rgb(68, 68, 68);
|
10 |
+
position: relative;
|
11 |
+
}
|
12 |
+
|
13 |
+
/*
|
14 |
+
* Expand the config form and adjust all elements to expand to the new size.
|
15 |
+
*/
|
16 |
+
#edit_form .form-list {
|
17 |
+
width: 590px;
|
18 |
+
}
|
19 |
+
|
20 |
+
#edit_form .form-list td.value {
|
21 |
+
width: auto;
|
22 |
+
}
|
23 |
+
|
24 |
+
#edit_form td.value .note {
|
25 |
+
width: 90%;
|
26 |
+
}
|
27 |
+
|
28 |
+
#edit_form td.value select {
|
29 |
+
width: 95%;
|
30 |
+
}
|
31 |
+
|
32 |
+
/* Text inputs are half-width by default */
|
33 |
+
#edit_form td.value input {
|
34 |
+
width: 50%;
|
35 |
+
}
|
36 |
+
|
37 |
+
/* Expand the Account ID and Token fields to fit the data */
|
38 |
+
#edit_form #settings.fieldset td.value input {
|
39 |
+
font-family: monospace;
|
40 |
+
width: 64%;
|
41 |
+
}
|
skin/adminhtml/default/default/cloudiq/js/callme.js
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Disable the "Display on selected pages" selection box when "Display on all pages"
|
3 |
+
* gets selected and vice versa when the selection box gets clicked.
|
4 |
+
*/
|
5 |
+
document.observe("dom:loaded", function() {
|
6 |
+
var all_pages = $("callme[published][all]");
|
7 |
+
var selected_pages = $("callme[published][pages]");
|
8 |
+
|
9 |
+
all_pages.observe("change", function () {
|
10 |
+
selected_pages.disabled = all_pages.checked ? true : false;
|
11 |
+
});
|
12 |
+
selected_pages.parentElement.observe("click", function() {
|
13 |
+
selected_pages.disabled = false;
|
14 |
+
all_pages.checked = false;
|
15 |
+
});
|
16 |
+
});
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Display a preview of the callMe button
|
20 |
+
*/
|
21 |
+
document.observe("dom:loaded", function () {
|
22 |
+
var preview_url = $('callme[button][preview_url]').value;
|
23 |
+
var config_form = $('edit_form');
|
24 |
+
var button_form_section = $('button');
|
25 |
+
var popup_form_section = $('popup');
|
26 |
+
|
27 |
+
var button_preview = new Element("div", {id: "cloudiq_callme_button_preview"});
|
28 |
+
button_preview.setStyle({display: "none"});
|
29 |
+
$(document.body).insert(button_preview);
|
30 |
+
|
31 |
+
function updateCloudiqCallmePreview() {
|
32 |
+
new Ajax.Updater(button_preview, preview_url, {
|
33 |
+
method: "POST",
|
34 |
+
parameters: config_form.serialize(true),
|
35 |
+
evalScripts: true
|
36 |
+
});
|
37 |
+
}
|
38 |
+
|
39 |
+
// Update the preview when button or popup configuration is changed
|
40 |
+
button_form_section.select('input, select')
|
41 |
+
.concat(popup_form_section.select('input, select'))
|
42 |
+
.each(function (element) {
|
43 |
+
element.observe("change", updateCloudiqCallmePreview);
|
44 |
+
});
|
45 |
+
|
46 |
+
// Only show the preview when the callMe config form tab is open
|
47 |
+
varienGlobalEvents.attachEventHandler("showTab", function (event) {
|
48 |
+
if (event.tab.name == "callme_section") {
|
49 |
+
button_preview.setStyle({display: "block"});
|
50 |
+
updateCloudiqCallmePreview();
|
51 |
+
} else {
|
52 |
+
button_preview.setStyle({display: "none"});
|
53 |
+
}
|
54 |
+
});
|
55 |
+
});
|
skin/frontend/base/default/cloudiq/css/callme-button.css
ADDED
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Button layout & generic appearance
|
3 |
+
*/
|
4 |
+
|
5 |
+
#cloudiq-callme-button {
|
6 |
+
display: inline-block;
|
7 |
+
position: fixed;
|
8 |
+
z-index: 10;
|
9 |
+
cursor: pointer;
|
10 |
+
|
11 |
+
padding: 7px 25px;
|
12 |
+
text-align: center;
|
13 |
+
}
|
14 |
+
|
15 |
+
#cloudiq-callme-button p {
|
16 |
+
margin: 0px;
|
17 |
+
}
|
18 |
+
|
19 |
+
#cloudiq-callme-button-title {
|
20 |
+
font-size: 1.2em;
|
21 |
+
font-weight: bold;
|
22 |
+
}
|
23 |
+
|
24 |
+
/*
|
25 |
+
* Popup layout & generic appearance
|
26 |
+
*/
|
27 |
+
|
28 |
+
#cloudiq-callme-popup {
|
29 |
+
position: fixed; /* The popup is positioned with js */
|
30 |
+
z-index: 15;
|
31 |
+
|
32 |
+
display: none; /* Hide the popup when loaded, it is toggled by the button */
|
33 |
+
|
34 |
+
min-width: 400px;
|
35 |
+
padding: 15px 20px;
|
36 |
+
}
|
37 |
+
|
38 |
+
#cloudiq-callme-popup-close {
|
39 |
+
float: right;
|
40 |
+
padding: 5px;
|
41 |
+
line-height: 25px;
|
42 |
+
font-size: 25px;
|
43 |
+
cursor: pointer;
|
44 |
+
}
|
45 |
+
|
46 |
+
#cloudiq-callme-popup-logo {
|
47 |
+
float: left;
|
48 |
+
max-height: 50px;
|
49 |
+
}
|
50 |
+
|
51 |
+
#cloudiq-callme-popup p {
|
52 |
+
margin: 0px;
|
53 |
+
text-align: center;
|
54 |
+
}
|
55 |
+
|
56 |
+
#cloudiq-callme-popup-title {
|
57 |
+
clear: both;
|
58 |
+
padding-top: 5px;
|
59 |
+
font-size: 1.3em;
|
60 |
+
font-weight: bold;
|
61 |
+
}
|
62 |
+
|
63 |
+
#cloudiq-callme-popup-form {
|
64 |
+
margin: 20px 0;
|
65 |
+
}
|
66 |
+
|
67 |
+
#cloudiq-callme-popup-form * {
|
68 |
+
display: block;
|
69 |
+
margin: 2px auto;
|
70 |
+
}
|
71 |
+
|
72 |
+
#cloudiq-callme-popup-form label {
|
73 |
+
text-align: left;
|
74 |
+
color: inherit;
|
75 |
+
}
|
76 |
+
|
77 |
+
#cloudiq-callme-popup-form input {
|
78 |
+
width: 90%;
|
79 |
+
padding: 8px;
|
80 |
+
background: #FFFFFF;
|
81 |
+
border: 2px inset;
|
82 |
+
}
|
83 |
+
|
84 |
+
#cloudiq-callme-popup-form button {
|
85 |
+
margin-top: 15px;
|
86 |
+
padding: 8px 18px;
|
87 |
+
background: inherit;
|
88 |
+
border: 0;
|
89 |
+
-webkit-border-radius: 16px;
|
90 |
+
-moz-border-radius: 16px;
|
91 |
+
border-radius: 16px;
|
92 |
+
border-width: 0;
|
93 |
+
font-size: 1.2em;
|
94 |
+
cursor: pointer;
|
95 |
+
}
|
96 |
+
|
97 |
+
/*
|
98 |
+
* Appearance templates
|
99 |
+
*/
|
100 |
+
|
101 |
+
/* Button positioning */
|
102 |
+
|
103 |
+
.cloudiq-callme-position-leftbottom { left: 0; bottom: 0; }
|
104 |
+
.cloudiq-callme-position-leftmiddle { left: 0; top: 50%; }
|
105 |
+
.cloudiq-callme-position-lefttop { left: 0; top: 0; }
|
106 |
+
|
107 |
+
.cloudiq-callme-position-topleft { top: 0; left: 0; }
|
108 |
+
.cloudiq-callme-position-topmiddle { top: 0; left: 50%; }
|
109 |
+
.cloudiq-callme-position-topright { top: 0; right: 0; }
|
110 |
+
|
111 |
+
.cloudiq-callme-position-righttop { right: 0 ; top: 0; }
|
112 |
+
.cloudiq-callme-position-rightmiddle { right: 0 ; top: 50%; }
|
113 |
+
.cloudiq-callme-position-rightbottom { right: 0 ; bottom: 0; }
|
114 |
+
|
115 |
+
.cloudiq-callme-position-bottomright { bottom: 0; right: 0; }
|
116 |
+
.cloudiq-callme-position-bottommiddle { bottom: 0; left: 50%; }
|
117 |
+
.cloudiq-callme-position-bottomleft { bottom: 0; left: 0; }
|
118 |
+
|
119 |
+
/* Response message */
|
120 |
+
|
121 |
+
.cloudiq-callme-status-failure, .cloudiq-callme-status-success {
|
122 |
+
margin: 20px 0;
|
123 |
+
padding: 10px;
|
124 |
+
color: #000000;
|
125 |
+
}
|
126 |
+
|
127 |
+
.cloudiq-callme-status-success { background: #88CC88; }
|
128 |
+
.cloudiq-callme-status-failure { background: #FF8888; }
|
129 |
+
|
130 |
+
/* Button & Popup templates */
|
131 |
+
|
132 |
+
/* Template 1 */
|
133 |
+
|
134 |
+
.cloudiq-callme-template-1 {
|
135 |
+
background: -moz-linear-gradient(top, #ffffff 0%, #E5E5E5 100%) !important; /* FF3.6+ */
|
136 |
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#E5E5E5)) !important; /* Chrome,Safari4+ */
|
137 |
+
background: -webkit-linear-gradient(top, #ffffff 0%,#E5E5E5 100%) !important; /* Chrome10+,Safari5.1+ */
|
138 |
+
background: -o-linear-gradient(top, #ffffff 0%,#E5E5E5 100%) !important; /* Opera 11.10+ */
|
139 |
+
background: -ms-linear-gradient(top, #ffffff 0%,#E5E5E5 100%) !important; /* IE10+ */
|
140 |
+
background: linear-gradient(to bottom, #ffffff 0%,#E5E5E5 100%) !important; /* W3C */
|
141 |
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#E5E5E5',GradientType=0 ) !important; /* IE6-8 */
|
142 |
+
color: #000000 !important;
|
143 |
+
border: 4px solid;
|
144 |
+
}
|
145 |
+
|
146 |
+
/* Template 2 */
|
147 |
+
|
148 |
+
.cloudiq-callme-template-2 {
|
149 |
+
border: 4px solid;
|
150 |
+
}
|
151 |
+
|
152 |
+
#cloudiq-callme-popup.cloudiq-callme-template-2 button {
|
153 |
+
background-color: #000000 !important;
|
154 |
+
color: #FFFFFF !important;
|
155 |
+
}
|
156 |
+
|
157 |
+
/* Template 3 */
|
158 |
+
|
159 |
+
.cloudiq-callme-template-3 {
|
160 |
+
-webkit-border-radius: 30px;
|
161 |
+
-moz-border-radius: 30px;
|
162 |
+
border-radius: 30px;
|
163 |
+
}
|
164 |
+
|
165 |
+
#cloudiq-callme-popup.cloudiq-callme-template-3 button {
|
166 |
+
background-color: #000000 !important;
|
167 |
+
color: #FFFFFF !important;
|
168 |
+
}
|
169 |
+
|
170 |
+
/* Template 4 */
|
171 |
+
|
172 |
+
.cloudiq-callme-template-4 {
|
173 |
+
background: -moz-linear-gradient(top, #FFFFFF 0%, #E5E5E5 100%) !important; /* FF3.6+ */
|
174 |
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFFFFF), color-stop(100%,#E5E5E5)) !important; /* Chrome,Safari4+ */
|
175 |
+
background: -webkit-linear-gradient(top, #FFFFFF 0%,#E5E5E5 100%) !important; /* Chrome10+,Safari5.1+ */
|
176 |
+
background: -o-linear-gradient(top, #FFFFFF 0%,#E5E5E5 100%) !important; /* Opera 11.10+ */
|
177 |
+
background: -ms-linear-gradient(top, #FFFFFF 0%,#E5E5E5 100%) !important; /* IE10+ */
|
178 |
+
background: linear-gradient(to bottom, #FFFFFF 0%,#E5E5E5 100%) !important; /* W3C */
|
179 |
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#E5E5E5',GradientType=0 ) !important; /* IE6-8 */
|
180 |
+
color: #000000 !important;
|
181 |
+
border: 4px solid;
|
182 |
+
-webkit-border-radius: 8px;
|
183 |
+
-moz-border-radius: 8px;
|
184 |
+
border-radius: 8px;
|
185 |
+
}
|
186 |
+
|
187 |
+
/* Template 5 */
|
188 |
+
|
189 |
+
.cloudiq-callme-template-5 {
|
190 |
+
-webkit-border-radius: 8px;
|
191 |
+
-moz-border-radius: 8px;
|
192 |
+
border-radius: 8px;
|
193 |
+
}
|
194 |
+
|
195 |
+
#cloudiq-callme-popup.cloudiq-callme-template-5 button {
|
196 |
+
background-color: #000000 !important;
|
197 |
+
color: #FFFFFF !important;
|
198 |
+
}
|