Monday, August 5, 2019

Integrando Oracle Jet 7.1 Gantt + Data dinámica + Oracle APEX 19.1 + AJAX

En este post integraremos la actual versión de Oracle JET 7.1 en Oracle APEX y usaremos AJAX para cargar la información de forma dinámica.



Demo

Descarga App: GDrive


Para este ejemplo usaremos el control Gantt del CookBook de JET

En la hoja creamos una variable que será nuestro enlace de la data.

Agregamos la referencia de CSS

#JET_CSS_DIRECTORY#/alta/oj-alta-notag-min.css


Agregamos la librería de requireJS

APEX_JAVASCRIPT.add_requirejs();


En el page load creamos dos acciones dinámicas, en una cargamos las librerías de JET 7.1



requirejs.config({

    "baseUrl": "https://static.oracle.com/cdn/jet/v7.1.0", 
    // Path mappings for the logical module names
    paths: {
        'knockout': '3rdparty/knockout/knockout-3.5.0',
        'jquery': '3rdparty/jquery/jquery-3.4.1.min',
        'jqueryui-amd': '3rdparty/jquery/jqueryui-amd-1.12.1.min',
        'promise': '3rdparty/es6-promise/es6-promise.min',
        'hammerjs': '3rdparty/hammer/hammer-2.0.8.min',
        'ojdnd': '3rdparty/dnd-polyfill/dnd-polyfill-1.0.0.min',
        'ojs': 'default/js/min',
        'ojL10n': 'default/js/ojL10n',
        'ojtranslations': 'default/js/resources',
        'text': '3rdparty/require/text',
        'signals': '3rdparty/js-signals/signals.min',
        'customElements': '3rdparty/webcomponents/custom-elements.min',
        'proj4': '3rdparty/proj4js/dist/proj4',
        'css': '3rdparty/require-css/css.min',
        'touchr': '3rdparty/touchr/touchr'
  },    
  // Shim configurations for modules that do not expose AMD    
  shim: {    
    'jquery': {    
      exports: ['jQuery', '$']    
    }    
  }    
}); 

Y en otra acción dinámica el código del ViewModel, el código fue extraído de la guía del cookbook de Oracle JET.

Aquí se han modificado los siguientes puntos:

-- La función recibe un parámetro que es la data para usar en el Gantt
function ViewModel(dataArray) 
-- El construcctor recibe el parametro de la data.
this.dataProvider = new ArrayDataProvider(dataArray, {keyAttributes: 'id'});

-- Para los path de las images se estan usando link de images online
 this.rowLabelImagePath = { 'Flag1' ....
-- dataArray se inicializa como:
dataArray = ko.observableArray([]); 

Código ViewModel

  require(['knockout', 'ojs/ojbootstrap', 'ojs/ojarraydataprovider', 'ojs/ojknockout', 'ojs/ojgantt'],  
    function(ko, Bootstrap, ArrayDataProvider)
    {
      function ViewModel(dataArray) 
      {
        this.dataProvider = new ArrayDataProvider(dataArray, {keyAttributes: 'id'});
        this.projectStartDate = new Date("Jan 1, 2019");
        this.projectEndDate = new Date("Dec 31, 2019");
  
        this.currentDateString = "Apr 15, 2019";
        this.currentDate = new Date(this.currentDateString);
  
        // set viewport to center around the reference object
        var month = 1000 * 60 * 60 * 24 * 30;
        this.viewportStart = new Date(Math.max(this.projectStartDate.getTime(), this.currentDate.getTime() - 3*month));
        this.viewportEnd = new Date(Math.min(this.projectEndDate.getTime(), this.currentDate.getTime() + 3*month));
  
        // Helper function to get appropriate row label image x position depending on document reading direction
        this.getRowImageX = function() {
          var dir = document.documentElement.getAttribute("dir");
          return dir === 'ltr' ? '0' : '0';
        };
  
        // Helper function to get appropriate row label text x position depending on document reading direction
        this.getRowTextX = function() {
          var dir = document.documentElement.getAttribute("dir");
          return dir === 'ltr' ? '30' : '25';
        };
  
        this.getRowTextAnchor = function() {
          var dir = document.documentElement.getAttribute("dir");
          var userAgent = navigator.userAgent.toLowerCase();
          var isIE = userAgent.indexOf('trident') != -1 || userAgent.indexOf('msie') != -1 || userAgent.indexOf('edge') != -1;
          // Unlike other browsers, IE11 and Edge treats left side of svg text as start in RTL, 
          // so set text-anchor to end to achieve consistent behavior
          return dir === 'rtl' && isIE ? 'end' : 'start';
        };
  
        this.rowLabelImagePath = {
          'Flag1': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//pe.png',
          'Flag2': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//pw.png',
          'Flag3': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//aq.png',
          'Flag4': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//bg.png',
          'Flag5': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//bl.png',
          'Flag6': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//ch.png',
          'Flag7': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//es.png',
          'Flag8': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//gg.png',
          'Flag9': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//id.png',
          'Flag10': 'https://raw.githubusercontent.com/stefangabos/world_countries/master/flags/24x24//lt.png',
        };
      }
  
      Bootstrap.whenDocumentReady().then(
        function()
        {
          dataArray = ko.observableArray([]);  
          ko.applyBindings(new ViewModel(dataArray), document.getElementById('gantt'));
        }
      );
    }
  );

Creamos una región estática y agregamos el CSS de la región Gantt
 



 <div id="componentDemoContent" style="width: 1px; min-width: 100%;">
          
          <oj-gantt id="gantt"
              axis-position="bottom"
              start="[[projectStartDate.toISOString()]]"
              end="[[projectEndDate.toISOString()]]"
              gridlines.horizontal="visible"
              gridlines.vertical="visible"
              major-axis.scale="months"
              major-axis.zoom-order='["quarters", "months", "weeks", "days"]'
              minor-axis.scale="weeks"
              minor-axis.zoom-order='["quarters", "months", "weeks", "days"]'
              row-axis.rendered="on"
              selection-mode="single"
              reference-objects='[[[{"value": currentDate.toISOString()}]]]'
              viewport-start="[[viewportStart.toISOString()]]"
              viewport-end="[[viewportEnd.toISOString()]]"
              task-data="[[dataProvider]]"
              :aria-label='[["Gantt Chart. Current date is " + currentDateString]]'
              style="width:100%;height:500px">
            <template slot="rowTemplate" data-oj-as="row">
              <oj-gantt-row
                  label="[[row.id]]">
              </oj-gantt-row>
            </template>
            <template slot="taskTemplate" data-oj-as="task">
              <oj-gantt-task
                  row-id="[[task.data.resource]]"
                  start="[[task.data.begin]]"
                  end="[[task.data.finish]]"
                  label="[[task.data.name]]">
              </oj-gantt-task>
            </template>
            <template slot="rowAxisLabelTemplate" data-oj-as="rowAxisLabel">
              <svg style="overflow:visible">
                <g>
                  <image
                      :xlink:href='[[rowLabelImagePath[rowAxisLabel.rowData.id.replace(" ", "")]]]'
                      xlink:href=""
                      :x="[[getRowImageX()]]"
                      width="24" height="24">
                  </image>
                  <text
                      :x="[[getRowTextX()]]"
                      y="16"
                      :text-anchor="[[getRowTextAnchor()]]">
                    <oj-bind-text value="[[rowAxisLabel.rowData.label]]"></oj-bind-text>
                  </text>
                </g>
              </svg>
            </template>
          </oj-gantt>
  
          
        </div>


Creamos un botón y lo definimos con una acción dinámica que ejecutara un JavaScript, la cual es la llamada AJAX


    apex.server.process("LOAD_DATA", {     
      },   
      {  
        success: function(pData) {   
         console.log(pData);
          dataArray(pData);
        }  
      }                          
    ); // apex process  

Creamos nuestro AjaxCallback


Por motivos didáctivos estoy usando unos select dentro de un for para generar data de forma dinámica.


declare
  l_begin_date date;
  l_end_date date;
begin
   apex_json.open_array();  
      -- for generate random data
      for i in 1..20
      loop      
        -- tasks 1
          select TO_DATE(TRUNC(DBMS_RANDOM.VALUE(TO_CHAR(DATE '2019-01-01','J'),TO_CHAR(DATE '2019-12-31','J'))),'J' ) random_date 
            into l_begin_date
            from dual;

          select TO_DATE(TRUNC(DBMS_RANDOM.VALUE(TO_CHAR(l_begin_date,'J'),TO_CHAR(DATE '2019-12-31','J'))),'J' ) random_date 
            into l_end_date
            from dual;

        apex_json.open_object;  
        apex_json.write('id', 'task1-'||i);  
        apex_json.write('begin', l_begin_date );  
        apex_json.write('finish', l_end_date);  
        apex_json.write('name', 'Label 1-'||i);  
        apex_json.write('resource', 'Flag'||i);  
        apex_json.close_object;  

        -- tasks 2 
        select TO_DATE(TRUNC(DBMS_RANDOM.VALUE(TO_CHAR(DATE '2019-01-01','J'),TO_CHAR(DATE '2019-12-31','J'))),'J' ) random_date 
          into l_begin_date
          from dual;

        select TO_DATE(TRUNC(DBMS_RANDOM.VALUE(TO_CHAR(l_begin_date,'J'),TO_CHAR(DATE '2019-12-31','J'))),'J' ) random_date 
          into l_end_date
          from dual;

        apex_json.open_object;  
        apex_json.write('id', 'task1-'||i);  
        apex_json.write('begin', l_begin_date );  
        apex_json.write('finish', l_end_date);  
        apex_json.write('name', 'Label 1-'||i);  
        apex_json.write('resource', 'Flag'||i);  
        apex_json.close_object;  
      end loop;

  apex_json.close_array();  
end;


En el network la llamada ajax debe tener la siguiente estructura, la misma del ejemplo del cookbook.




Y finalmente el resultado






Share:

0 comentarios:

Post a Comment

Subscribe to my Newsletter

Acerca de mi:

img

Ing. Angel O. Flores Torres, soy Ingeniero de Sistemas e Ingeniero de Aplicaciones Oracle Apex, he trabajado con Oracle Apex 5 y 5.1 desde el 2017, En los ultimos años he desarrollado habilidades en CSS, JavaScript, Jquery y PlSql , I specialize in Oracle APEX (Oracle Application Express )

Followers

Popular Posts