lsFusion 4: tablas dinámicas, gráficos, mapas y calendarios, autenticación OAuth, tema oscuro y más





Justo el otro día, se lanzó una nueva cuarta versión de la plataforma abierta gratuita lsFusion. En este artículo intentaré contarte brevemente las principales novedades de esta versión e ilustrarlas tanto como sea posible con imágenes gif y ejemplos (al menos para aquellos a los que no les gusta leer mucho texto). Además, muchas de estas funciones se pueden probar en línea en el sitio web oficial o, por ejemplo, en una versión de demostración de una de las soluciones de lsFusion.







lsFusion ( ). , ( , ).







, ( ), ( ) — UI .







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







, , .











. : . , , — , , , , - , , .







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









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







lsFusion . ( ) , , . , , .











Tenga en cuenta que, a nivel físico, la operación de agrupación en vistas de agrupación se puede realizar tanto en el servidor de base de datos como en el cliente. La plataforma gestiona esta elección automáticamente: si el número de grupos disminuye o la cantidad de datos iniciales es menor que el umbral, entonces los datos se procesan en el cliente (para excluir llamadas innecesarias al servidor). En la mayoría de los otros casos, la agrupación se realiza en el servidor SQL mediante una consulta (sin embargo, los subtotales aún se calculan en el cliente).







El usuario puede cambiar la agrupación mediante la correspondiente interfaz de arrastrar y soltar. El desarrollador puede definir agrupaciones utilizando la sintaxis adecuada en la declaración FORM.

FORM myReport

    OBJECTS l = Ledger PIVOT 'Area Chart'

    PROPERTIES (l) customer ROW, sum MEASURE

;





Tabla dinámica



. , :







  • . , — --, .
  • . , .


, , , , 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

;





Si lo desea, puede experimentar con el mapa y el calendario en el sitio web oficial de lsFusion en la sección Probar en línea (Modo plataforma -> Mapa y calendario).



Vistas personalizadas



Independientemente de las vistas que se admitan desde el primer momento en lsFusion, es posible que no siempre sean suficientes (o que la configuración de las vistas existentes sea insuficiente). Para resolver el problema en el caso general, la plataforma admite las llamadas vistas personalizadas.







Hay dos partes para respaldar estas opiniones:







  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- , .







Ahora, volvamos a lsFusion. Para trabajar con sistemas externos, incluido el protocolo http, la plataforma utiliza el operador EXTERNAL. Es cierto que la peculiaridad de este operador es que en la tercera versión solo se podía ejecutar en el servidor, lo que significa que era imposible utilizarlo para el mismo trabajo con equipos en el cliente. En consecuencia, en la cuarta versión de la plataforma para el protocolo HTTP, fue posible ejecutar el operador EXTERNO en el cliente. Sintácticamente, se ve así:





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';

    }

}





Físicamente, al igual que cuando se realizan otras acciones del cliente (por ejemplo, mostrar formularios / mensajes), la propia plataforma detiene la acción en el servidor, transfiere el control al cliente, ejecuta una solicitud http allí, luego devuelve el control al servidor y continúa la ejecución de la acción detenida en el servidor.





, . , , , . , , , . , — «» ( OBJECTS) / . , , — FILTERS :





exportAndShowIncomes (Supplier s) {

    // i -      (incomes)

    EXPORT incomes FILTERS supplier(i) = s;

    open(exportFile());

    DIALOG incomes FILTERS supplier(i) = s;

}





Como en el caso de los encabezados computados, una innovación importante no es la funcionalidad de agregar filtros adicionales al formulario en sí, sino en general la infraestructura para usar el contexto de apertura del formulario dentro del formulario mismo. Entonces, en versiones futuras, será fácil implementar soporte para agregar, por ejemplo, propiedades u órdenes adicionales al abrir un formulario, mientras que en el proceso de agregar estos elementos, también puede usar parámetros del contexto de apertura del formulario. Sin embargo, todos estos elementos adicionales (a excepción de los filtros) dependen del contexto con mucha menos frecuencia, por lo tanto, para agregarlos, aún sería más lógico utilizar el mecanismo de herencia (agregación) de formularios, que también aparecerá en una de las próximas versiones (este mecanismo se discutirá en detalle en la próxima artículos).



Optimización DOM



, 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