How we made widget support for applications in MyStore

Hello everyone! MySklad Marketplace is on air. The last time we talked about how we launched marketpleys applications in SaaS-service MoySklad . Today we will continue about how we enable applications to extend the user interface of the service. Probably, many have come across in desktop applications with similar plugins, which, when connected, add some of their own buttons, menu items and even whole sets of new windows and dialogs to the application, and also embed their own UI blocks into existing screens. How do you do this in a SaaS service that has a browser UI?





Why embed in UI at all?

At the start of the Marketplace for general-purpose applications, the only available way to integrate applications with MyStore is data integration via a common JSON API . Through this API, the backend of vendor applications can receive and modify user data. Thus, at the start, we only had the ability to integrate application backends and MyStore with each other. They could not add a button or widget to the application editing form.





Initially, it was clear that this was not enough to provide the ultimate user experience for end users. On the other hand, external developers and integrators had to collective farm their mechanisms in the UI - they had a choice either to embed directly into the HTML web applications of MyStore through browser plugins or to make separate interfaces (UI) on their side, largely duplicating the functionality of the screens in MyStore (for example, document lists with filters).





, โ€” , ( ). โ€” , , . , () , .





, , UI- โ€” must have , .





โ€” โ€” iframe . , , . . 





UI- -.





.

, , SaaS-.





. UI, .





:





:













  1. ,









:





  • . . , , ( ) UI ( ) (UX).





  • . . , , , โ€œโ€ .





  • / . , UI โ€” SPA, : DOM- , UI โ€” . , .





?

SaaS- (Jira, Salesforce, Zendesk) (amoCRM, 24, InSales). .





:





  1. : SPA - ?





  2. - (- , iframe ), , SDK ( UI)?





  3. , ?





  4. . , / .





. , .





, SPA- โ€œโ€ SPA (โ€œโ€ โ€” , , UI SPA, - โ€” ). UI โ€” SPA. 





iframeโ€™. :





  1. iframe , ( , โ€” ). sandbox iframeโ€™a allow-same-origin



    , DOM - . - , , JavaScript-. ().





  2. iframe ( allow-same-origin



    ) โ€” , DOM- - . . - postMessage, , , , JavaScript- - . , postMessage JS SDK โ€” JavaScript-.





JS SDK. JS SDK API , API โ€œโ€ postMessage JavaScript-.





amoCRM, DOM- -. , , , โ€” , UI. , . , , , - .





(, ) โ€” JSON- (). XML โ€” XML- ( JSON-). XML JSONโ€™a โ€” .





XML-

, , :





<ServerApplication xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"             
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             
                    xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2      
                    https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
        <expand>true</expand>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
    <widgets>        
        <entity.counterparty.edit>            
            <sourceUrl>https://example.com/widget.php</sourceUrl>            
            <height>                
                <fixed>150px</fixed>            
            </height>
            <supports>
                <open-feedback/>
                <save-handler/>
            </supports>
            <uses>
                <good-folder-selector/>
            </uses>                  
        </entity.counterparty.edit>    
    </widgets>
    <popups>
        <popup>
            <name>somePopup</name>
            <sourceUrl>https://example.com/popup.php</sourceUrl>
        </popup>
        <popup>
            <name>somePopup2</name>
            <sourceUrl>https://example.com/popup-2.php</sourceUrl>
        </popup>
    </popups>
</ServerApplication>

      
      



, XML, JSON? , XML โ€” XML Schema. JSON โ€” , JSON Schema. JSON- ( XML-) , , IDE. , JSON- . , XML- . JSON-, , XML JSON , XML- .





? :





  1. , . , , , - . โ€” .





  2. code completion IDE โ€œ โ€ UI . - ( ), .





, , Intellij IDEA , :





IDE open-feedback ( - ):





:





.





XML-

( ) . , ( ) . โ€” . , . , . . . .   





. , . , โ€” , , , , , , - . , , - , . .





, XML-:





<widgets>
    <some.extension.point1>...</some.extension.point1>
    <some.extension.point2>...</some.extension.point2>
</widgets>
      
      



, , :





<widgets>
    <widget location="some.extension.point1">...</widget>
    <widget location="some.extension.point2">...</widget>
</widgets>
      
      



XML- (โ€œโ€) . - โ€œโ€ โ€” . , XML-, XML-.





? , , ?





:





<document.customerorder.edit>
    <sourceUrl>https://example.com/widget.php</sourceUrl>
    <height>
        <fixed>150px</fixed>
    </height>
    <supports>...</supports>
    <uses>...</uses>
</document.customerorder.edit>
      
      



sourceUrl



height



. sourceUrl



iframe, height



( , โ€” , , UI).





( ) - (, , ), , <height><dynamic/></height>



. โ€” . , , <dynamic/>



, . 





supports



uses



. .





( API , ):





:





<document.customerorder.edit>
    <sourceUrl>https://example.com/widget.php</sourceUrl>
    <height>
        <fixed>150px</fixed>
    </height>
    <supports>
        <open-feedback/>
        <save-handler/>
        <change-handler>
            <expand>agent</expand>
            <expand>positions.assortment</expand>
        </change-handler>
    </supports>
    <uses>
        <good-folder-selector/>
    </uses>
</document.customerorder.edit>
      
      



.





โ€” , UI , . , HTTP postMesssage. .





.





โ€” , / ( ). . , sourceUrl



height



, iframe HTTP - postMessage- Open



.





DOM- :





Open



:





{
  "name": "Open",
  "messageId": 12345,
  "extensionPoint": "entity.counterparty.edit",
  "objectId": "8e9512f3-111b-11ea-0a80-02a2000a3c9c",
  "displayMode": "expanded"
}
      
      



โ€” ( ) , . supports



( ). .





supports



. .





pen-feedback



( ) โ€” , , , OpenFeedback



. , . - , .





:





OpenFeedback



:





{
  "name": "OpenFeedback",
  "correlationId": 12345
}  
      
      



save-handler



( ) โ€” , - โ€œโ€ Save



.





Save



:





{
  "name": "Save",
  "messageId": 32109,
  "extensionPoint": "entity.counterparty.edit",
  "objectId": "8e9512f3-111b-11ea-0a80-02a2000a3c9c"
}
      
      



hange-handler



( ) โ€” , , , ( ). , change-handler



, - โ€œโ€ โ€” - (, ) - Change



JSON . expand



, JSON API ( change-handler



expand



).





โ€” , - . . uses ( ). , -> - -.





โ€” good-folder-selector



. . :





1. - SelectGoodFolderRequest



(, - ):





{
  "name": "SelectGoodFolderRequest",
  "messageId": 12345
}
      
      



2. - :





3. - SelectGoodFolderResponse



:





{
  "name": "SelectGoodFolderResponse",
  "correlationId": 12345,
  "selected": true,
  "goodFolderId": "8e9512f3-111b-11ea-0a80-02a2000a3c9c"
}
      
      



:





  1. , .





  2. XML- , ( ). 





  3. / , . : , , - , , , .





  4. , -. , change-handler, - , ( SPA- ).





(, - Init postMessage, iframe. , , ( ), (, ). , , โ€” , - , ( ). , .





. .





?

?





. - , . - . . iframe, . postMessage- -. .





change-handler



. โ€” update



, -.





:





  • โ€œโ€ postMessage JavaScript/TypeScript Widget SDK









  • UI- ( ) โ€” , :





    • ,

























  • UI





  • RESP API Widget SDK





UI โ€” SaaS- , .





โ€” email- , , .





SaaS- โ€” โ€” , .








All Articles