lsFusion 4: pivot tables, charts, maps and calendars, OAuth authentication, dark theme and more





Just the other day, a new fourth version of the free open platform lsFusion was released. In this article I will try to briefly tell you about the main new features of this version and illustrate them as much as possible with gif-pictures and examples (at least for those who do not like to read a lot of text). Also, many of these features can be tried online on the official website or, for example, in a demo version of one of the solutions on lsFusion.







lsFusion ( ). , ( , ).







, ( ), ( ) β€” UI .







, , . . , , ( ). MyCompany. ( , , ), , . , , , , .







, , .











. : . , , β€” , , , , - , , .







, , . , frontend ( javascript HTML). , , ( Java Swing RCP) . . . , , , - ( http-). - lsFusion OLTP-, , . - , lsFusion -.









, lsFusion ( , , ) , , (BI) ( , BI- ). , , , , .







lsFusion . ( ) , , . , , .











Note that at the physical level, the grouping operation in grouping views can be performed on both the database server and the client. The platform manages this choice automatically: if the number of groups decreases, or the amount of initial data is less than the threshold, then the data is processed on the client (to exclude unnecessary calls to the server). In most other cases, the grouping is performed on the SQL server using a query (however, subtotals are still calculated on the client).







Grouping can be changed by the user using the appropriate drag-drop interface. The developer can define groupings using the appropriate syntax in the FORM statement.

FORM myReport

    OBJECTS l = Ledger PIVOT 'Area Chart'

    PROPERTIES (l) customer ROW, sum MEASURE

;





Pivot table



. , :







  • . , β€” --, .
  • . , .


, , , , Excel . :







  1. ( ), ( drag-drop ). , ( , ).
  2. Excel , , /


(drill-down) β€” , , , , , .







, , , (, ), . - , .

















, .







/ :







  • ( / , / )






. open-source plotly, ( ). , ( , , , ), .







img-, ( / ) . , , , , , .









, ( -) , . , time-tracking, ..







lsFusion :







    • / .
    • , , ..
    • ,
    • ( ), ( ).
    • .
    • ( ).










, , . :







    • longitude β€”
    • latitude β€”
    • polygon β€”
    • line β€”
    • icon β€”
    • ..
    • date, dateTime β€” /
    • dateFrom, dateTimeFrom β€” /
    • dateTo, dateTimeTo β€” /
    • name β€”
    • ..
FORM map 'Map'

    OBJECTS o = Element MAP

    PROPERTIES (o) longitude, latitude, polygon

    PROPERTIES name = name(o) IF o IS Point, color = RGB(25500IF isInAnyArea(o)

    PROPERTIES SHOWIF o IS Point namePopup = name(o) PANEL, inParis '' = 'I am ' + (CASE WHEN isInAnyArea(o) THEN '' ELSE 'not ') + 'in Paris. Drag me' PANEL

    PROPERTIES (o) 'Add point' = NEW[Point], 'Add area' = NEW[Area], DELETE

;

FORM calendar 'Calendar'

    OBJECTS e = Event CALENDAR

    PROPERTIES (e) date, name, NEWDELETE

;





If desired, you can experiment with the map and calendar on the official lsFusion website in the Try Online section (Platform Mode -> Map and Calendar).



Custom views



Whatever views are supported out of the box in lsFusion, they may not always be enough (well, or there may not be enough settings in existing views). To solve the problem in the general case, the platform supports the so-called custom views.







There are two parts to supporting these views:







  1. javascript css web-. , web ( ) , -, , web-. , , , , .
  2. . javascript-, ( window , javascript function window, ). :
    • element β€” DOM,
    • objects β€” javascript-, ( = , = )
    • controller β€” javascript-, / (, , ).


.







web js css ( , test.js test.css):



function calendar(element, objects, controller) {
    if(controller.calendar == null) { // lazy initialization
        controller.calendar = new FullCalendar.Calendar(element, {
            height: 'parent',
            editable: true,
            eventChange: function(info) {
                controller.changeDateProperty('date', controller.objects[info.event.extendedProps.index], info.event.start.getFullYear(),
                    info.event.start.getMonth() + 1,info.event.start.getUTCDate() + 1); // month and day are zero-based in full calendar
            },
            eventClick: function(info) {
                controller.changeSimpleGroupObject(controller.objects[info.event.extendedProps.index], false, info.el);
            }
        });
        setTimeout(function () {
            controller.calendar.render();
        }, 0);
    }

    controller.objects = objects; // need to save it to work with changes
    controller.calendar.setOption('events', objects.map((obj, index) =>
        Object.assign({}, obj, {
            index: index, // needed to work with changes
            classNames: controller.isCurrent(obj) ? 'event-highlight' : '' // highlighting current element
        })));
}

      
      





.event-highlight {
    border-color: #2C4751;
    background-color: #2C4751;
}

      
      





(web) ( js css, web, -, ).

, e:

CLASS Event;

date = DATA DATE (Event);

date(Event e) <- currentDate() WHEN SET(e IS Event);

title = DATA STRING (Event);

title(Event e) <- 'Event' + e WHEN SET(e IS Event);



FORM calendar

    OBJECTS e=Event CUSTOM 'calendar'

    PROPERTIES (e) date, title, NEWEDITDELETE 

;



NAVIGATOR {

    NEW calendar;

}





:









lsFusion , Flatlaf, , , , Intellij. - Flatlaf , - «» . lsFusion :







  • ( ) β€” -
  • β€” -


«» . , , / ( ). , lsFusion , , , - ( ). (, ).









OAuth



«»: , , , . :







  • - ( ). , .
  • .


( ) OAuth . , (, lsFusion) / . / , / (, β€” ). Β« Β» lsFusion / : Facebook, Google, Github, . (Authorization URI, Token URI ..). , ( OAuth , , , ).







lsFusion β€” «» Β« Β». «» -. Β« Β» (, ).









, ( «», OAuth-) « ». , « ». , , , , .







url user password ( http://myserver?user=X&password=Y



). , , , , VPN.









lsFusion :







  • ( , 'Some text {x.y}'



    ).
  • - :
    • ( ),
    • .


, , . :







  • / .
  • ( ).


Β« Β». :







  • , , .
  • , , , .
  • , ( ).


, , :







  • , ;
  • Β« Β», .


:







  • , ;
  • .


:







  • .
  • , , Google Translate. , . , .
  • , .
  • PROFIT


, , , - lsFusion. / : guestuk / guestuk ( ), guestbe / guestbe ( ).









lsFusion, , , . :







  • CTRL ( Excel). , ( EDIT_OBJECT



    ) .
  • Β« Β» .
  • ( ) Β« Β».
  • ( CHANGE



    , , )


, .







. , .









Β« Β»



lsFusion ( ), ( ) . :







  • .
  • , .


. N+1, , , .







-.
(GROUP_CHANGE) :

onChange(a);

PUSH REQUEST

    FOR [FILTER formY.a](ga) AND NOT a=ga DO

        onChange(ga);





onChange β€” (CHANGE), a β€” ( , ).

, f(a,b) :

DIALOG formX OBJECTS x = f(a,b) CHANGE//   formX,   f(a,b)    x





? «». ( CHANGE , ):

REQUEST 

    DIALOG formX OBJECTS x=f(a,b) INPUT DO requestedX() <- x; 

DO 

    f(a,b) <- requestedX();



PUSH REQUEST 

    FOR [FILTER formY.a](ga) AND NOT a=ga DO

        REQUEST 

            DIALOG formX OBJECTS x=f(a,b) INPUT DO requestedX() <- x; 

        DO 

            f(a,b) <- requestedX();





PUSH REQUEST REQUEST ( DO ). , :

PUSH REQUEST 

    FOR [FILTER formY.a](ga) AND NOT a=ga DO

        f(a,b) <- requestedX();





, lsFusion, FOR WHERE:

PUSH REQUEST 

        f(a,b) <- requestedX() WHERE [FILTER formY.a](ga) AND NOT a=ga;





, Β« Β».


, (, , ).











( , ) β€” . , . , :





DESIGN order {

    caption = ' β„–' + number(o);



    lines {

        caption  = ' (' + (GROUP SUM 1 IF line(OrderDetail od) = o) + ')';

    }

}







, . (, width pattern) ( )









:







  • .
  • , .


, , , . , , . , lsFusion . , ( ). , .











lsFusion Β« Β» β€” (, , , ..). , , , , , , , , ( ). / ( , ).







, , , «». .









, ( ), / - .







http-



, . , - 2 :







  • . javascript, , , css html ( ) .
  • «» . , / , .


( Chrome V8 ), , , . , , β€” , http-. http- , .







Now, back to lsFusion. To work with external systems, including the http-protocol, the platform uses the EXTERNAL operator. True, the peculiarity of this operator is that in the third version it could only be executed on the server, which means that it was impossible to use it for the same work with equipment on the client. Accordingly, in the fourth version of the platform for the HTTP protocol, it became possible to execute the EXTERNAL operator on the client. Syntactically, it looks like this:





reportX(Pos p) {

    generateUUID();

    EXPORT reportX JSON CHARSET 'UTF-8';

    TRY {

        EXTERNAL HTTP CLIENT 'http://' + hostname(p) + ':16732/requests' PARAMS exportFile();

    } CATCH {

        CASE

            WHEN statusHttp() > 299 THEN

                MESSAGE ' - ' + STRING(statusHttp());

            WHEN NOT statusHttp() THEN

                MESSAGE ' -      v.10';

            ELSE

                MESSAGE ' -      v.10';

    }

}





Physically, just like when performing other client actions (for example, displaying forms / messages), the platform itself stops the action on the server, transfers control to the client, executes an http request there, then returns control to the server and continues the execution of the stopped action on the server.





, . , , , . , , , . , β€” «» ( OBJECTS) / . , , β€” FILTERS :





exportAndShowIncomes (Supplier s) {

    // i -      (incomes)

    EXPORT incomes FILTERS supplier(i) = s;

    open(exportFile());

    DIALOG incomes FILTERS supplier(i) = s;

}





As in the case of computed headers, an important innovation is not the functionality of adding additional filters to the form itself, but in general the infrastructure for using the context of opening the form inside the form itself. So in future versions, it will be easy to implement support for adding, for example, additional properties or orders when opening a form, while in the process of adding these elements, you can also use parameters from the context of opening the form. However, all these additional elements (with the exception of filters) depend on the context much less often, therefore, to add them, it would still be more logical to use the inheritance (aggregation) mechanism of forms, which will also appear in one of the next versions (this mechanism will be described in detail in the next articles).



DOM optimization



, lsFusion -, - . , (- ), Swing ( , / ), / HTML DOM. , . , . , :







  1. β€œβ€ -.
  2. - .


β€” . , lsFusion- ( -), . - ( lsFusion), DOM . , - MyCompany ( ). , , ( , / , ).









( github). , (UX) developer experience (DX), . ( -) , .







MyCompany. (, custom-made ), , . -, ERP-, / «» . MyCompany. SME ( ERP ), ( , , Apache 2.0 ). WMS, , , WMS - ( lsFusion), - ( -).










All Articles