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=\"\"
😡=\"[[getRowImageX()]]\"
width=\"24\" height=\"24\">
</image>
<text
😡=\"[[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

Published by Angel O. Flores Torres

System engineer, Applications engineer, working with C# and Oracle Apex 5, 5.1 since 2017. I specialize in Oracle APEX (Oracle Application Express )

4 thoughts on “Integrando Oracle Jet 7.1 Gantt + Data dinámica + Oracle APEX 19.1 + AJAX

  1. Hi Angel,Great post, very informative. I tried to follow through your instructions but having issues rendering the gantt in the static content region. All i see is the CSS code. Do you know if this works on APEX 18.2?

    Like

  2. Hola AngelHay que hacer scroll en el calendario cuando tienes dos actividades por hora desde las 7:00 hasta las 19:00 para ver las tardias. ¿Hay una manera de hacer mas alto el calendario para evitar el scroll?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: