@romanmazyrin/amocrm_widget_framework
v0.0.6
Published
Ready-to-use library to easy start your widget for amoCRM
Downloads
5
Readme
Amocrm widget framework
Library to make amoCRM widgets development easier and faster. Includes often used components that are essential for widget core functionality.
Built with
Table of contents
Install
Installation by NPM package manager npm
npm install --save amocrm_widget_framework
You must include react in your project as well. Usually react is installed automatically as peer-dependency during npm install
process. However, you must include React in your project explicitly, either in ES6 modules via import
statement or in require
function as a dependency or directly include react on a web page as third-party package.
Using
Destination main file of the lib is built in UMD format. That means you can use this lib with any module system you are used to work with. All the next documentation examples are shown for ES6 modules.
import {
createWidget,
SettingsButtonsComponent,
SettingsContactFormComponent,
SettingsPhoneFieldComponent,
SubscriptionManagerComponent,
VideoInstructionComponent,
SettingsSaverComponent,
SettingsFooterComponent,
} from 'amocrm_widget_framework';
But you can import this lib via AMD (define/require), CommonJS (require) and even include destination script direct on a web page and use components via global variable amocrm_widget_lib
).
How the library works
There is a core function inside the lib createWidget(config)
. That function creates and returns another constructor-function founded on the passed configuration. Result constructor-function has to be imported in script.js file.
Widget configuration includes:
- Widget components (components)
- Widget lifecycle events handlers (events)
During the widget initialization inside amoCRM (i. e. widget instance is being creating) some things happen:
- Instances of components from the configuration is being creating. Those instances subscribes on widget events after that.
- Events handlers from configuration subscribes on widget events as well.
- All neccessary callbacks is being creating in the widget instance attribute 'callbacks'. The only thing happens inside those callbacks is to call the exact event corresponpding to that callback and pass the event name and widget instance inside that event.
Configuration example
const config = {
components: {
videoInstruction: {
class: VideoInstructionComponent,
},
settingsContactForm: {
class: SettingsContactFormComponent,
params: {
text: '{{lang.components.settings_contact_form.text}}',
contactButtons: [
{
type: 'telegram',
params: {
text: '{{lang.components.settings_contact_form.buttons.telegram.text}}',
username: '{{lang.components.settings_contact_form.buttons.telegram.username}}',
},
},
{
type: 'whatsapp',
params: {
text: '{{lang.components.settings_contact_form.buttons.whatsapp.text}}',
phone: '{{lang.components.settings_contact_form.buttons.whatsapp.phone}}',
},
},
{
type: 'email',
params: {
text: '{{lang.components.settings_contact_form.buttons.email.text}}',
email: '{{lang.components.settings_contact_form.buttons.email.email}}',
},
},
{
type: 'link',
params: {
text: '{{lang.components.settings_contact_form.buttons.site.text}}',
href: '{{lang.components.settings_contact_form.buttons.site.link}}',
},
},
],
callbackForm: {
successText: '{{lang.components.settings_contact_form.callback_form.success_text}}',
failText: '{{lang.components.settings_contact_form.callback_form.fail_text}}',
sendButtonText: '{{lang.components.settings_contact_form.callback_form.send_button_text}}',
phoneFieldPlaceholder: '{{lang.components.settings_contact_form.callback_form.phone_field_placeholder}}',
url: 'https://webhook.site/eb5e4c54-99a4-4ced-a5af-b87084b6fdaf',
},
},
},
settingsButtons: {
class: SettingsButtonsComponent,
params: {
buttons: [
{
type: 'link',
params: {
text: '{{lang.components.settings_buttons.auth_btn}}',
href: 'https://mazdata.ru/all-client-leads-integration/oauth?amo_subdomain={{system.domain}}',
style: {
backgroundColor: 'green',
color: 'white',
width: '350px',
},
classname: 'button-input',
},
},
],
},
},
subscriptionManager: {
class: SubscriptionManagerComponent,
params: {
statusUrl: 'https://mazdata.ru/google-drive-integration/get-integration-status',
},
},
settingsPhoneField: {
class: SettingsPhoneFieldComponent,
params: {
phoneFieldOpts: {
initialCountry: 'RU',
preferredCountries: ['RU', 'UA', 'BY', 'KZ'],
},
},
},
settingsSaver: {
class: SettingsSaverComponent,
params: {
url: 'https://webhook.site/eb5e4c54-99a4-4ced-a5af-b87084b6fdaf',
},
},
settingsFooter: {
class: SettingsFooterComponent,
params: {
siteDomain: 'deltasales.ru',
fromYear: '2013',
email: "[email protected]",
text: '{{lang.components.settings_footer.text}}'
}
}
},
events: {
[WidgetLifecycleEvents.EVENT_INIT]: (eventName, widget) => {
// do something on INIT event;
}
}
};
Components
What is a component?
By "component" inside this lib we mean some instance that initializes once during the widget creation, subscribes on widget events and handles events triggers after that. Components instances are available by calling widget method component(componentName)
.
const sm = widget.component('subscriptionManager');
const status = await sm.getStatus();
During the component creation (which happens in the middle of widget instance creating process) two arguments are passed in the component constructor. The first - instance of the widget itself. The second - set of parametees from configuration under the params
key.
In one word, component is a thing which:
- Has to be instantiated only once.
- Has to be available globally within widget.
- Can (but not must) subscribe on widget events and execute handlers on those events.
Component's configuration
Component's configuration consists of 3 main parts:
- Components's key in configuration. That key is neccessary for further component getting from the widget by
widget.component('keyFromConfiguration')
method. - Parameter
class
. This parameter accepts class that is inherited from WidgetComponent class. - Parameter
params
. This parameter is an object which is passed to the component's constructor in the exact same structure it is presented in configuration.
Component configuration example:
settingsFooter: {
class: SettingsFooterComponent,
params: {
siteDomain: 'deltasales.ru',
fromYear: '2013',
email: "[email protected]",
text: '{{lang.components.settings_footer.text}}'
}
}
The instance of class SettingsFooterComponent will be created on widget initialization. While instance is being creating it accepts widget instance and an object under the key params
. In further you can retrieve component instance by calling widget.component('settingsFooter')
.
Built-in library components
- VideoInstruction
- SettingsContactForm
- SettingsButtons
- SubscriptionManager
- SettingsPhoneField
- SettingsSaver
- SettingsSaver
- SettingsFooter
Detailed instructions of each component are available on links.
Custom component creating
- Create component class. Inherit it from
WidgetComponent
- Override the method
getWidgetEventsCallbacks()
.
import WidgetLifecycleEvents from 'amocrm_widget_framework';
import WidgetComponent from 'amocrm_widget_framework';
class MyOwnComponent extends WidgetComponent {
constructor(widget, params) {
super(widget);
//this.params = params; etc...;
}
getWidgetEventsCallbacks() {
return {
[WidgetLifecycleEvents.EVENT_SETTINGS]: this.settings.bind(this),
};
}
settings(eventName, widget) {
// Do something when settings event will be triggered;
}
}
- For further using you have to add your new component in the configuration of
createWidget
method;
const config = {
components: {
//...
myOwnComponentName: {
class: MyOwnComponent,
params: {
someParamName: 'Hi there!'
}
},
//...
}
};
Widget events
AmoCRM widgets are working on callbacks runnig system. You can deep dive into that in the [major documentation] on the official amoCRM site(https://www.amocrm.ru/developers/content/integrations/script_js).
But we want different components (which often are not related with each other) to listen same events. For that purposes the "Events" mechanism was developed. When particular callback is called the widget just emit the "event" and those listeners which are subscribed on that event run their functional.
There is an object events
to subscribe on the particular widget events in the configuration.
Keys of that object are events names, and values are callbacks for those events.
Important! Components handle events first, and only then
events
.
There are two ways to subscribe on events:
- Create custom component with callbacks on particular events, pass component to configuration.
- Create callbacks in the
events
object;
Widget events list
- EVENT_RENDER - Emited on render() callback
- EVENT_INIT - Emited on init() callback
- EVENT_SETTINGS - Emited on settings() callback
- EVENT_DP - Emited on dpSettings() callback
- EVENT_TAB - Emited on loadPreloadedData() callback
- EVENT_SAVE - Emited on onSave() callback
All this events exists as constants in the object WidgetLifecycleEvents
Event handler arguments
When handler handle event it accepts two arguments:
- Event name (from the list above)
- Widget instance.
Built-in tools
Modal
Class for rendering modal window with content inside. Using:
import Modal from 'amocrm_widget_framework';
const modal = new Modal({
content: '<b style="font-size:30px">Hello</b>',
closeOnOverlayClick: true,
afterRender: (instance) => {
},
afterDestroy: (instance) => {
}
});