npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@romanmazyrin/amocrm_widget_framework

v0.0.6

Published

Ready-to-use library to easy start your widget for amoCRM

Downloads

8

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

webpack react esLint npm jest babel

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:

  1. Widget components (components)
  2. Widget lifecycle events handlers (events)

During the widget initialization inside amoCRM (i. e. widget instance is being creating) some things happen:

  1. Instances of components from the configuration is being creating. Those instances subscribes on widget events after that.
  2. Events handlers from configuration subscribes on widget events as well.
  3. 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:

  1. Has to be instantiated only once.
  2. Has to be available globally within widget.
  3. 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:

  1. Components's key in configuration. That key is neccessary for further component getting from the widget by widget.component('keyFromConfiguration') method.
  2. Parameter class. This parameter accepts class that is inherited from WidgetComponent class.
  3. 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

  1. Create component class. Inherit it from WidgetComponent
  2. 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;
    }
}
  1. 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:

  1. Create custom component with callbacks on particular events, pass component to configuration.
  2. 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:

  1. Event name (from the list above)
  2. 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) => {
    }
});