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:

Sunday, June 30, 2019

Getting the Oracle APEX certificate , Tips


I recently took the certification exam to become an Oracle certified developer in APEX. I have to say it was a little complex, when I finished I thought I was not going to pass the test but I did.



I want to write some tips, and the way that I followed to get this Oracle APEX Certificate.
I hope this information will be useful for you, and don't worry I will write it also in Spanish :P

FYI: 
You must have an Oracle Account and register on http://www.pearsonvue.com/oracle

Tip 1:

Watch, understand and try to replicate the examples of office hours videos.

I will recommend these topics:

APEX 18.1 New Features

Application Features

Data Visualization with Oracle APEX

Interactive Grids

Dynamic Actions

Universal Theme / Mobile Applications

Web Source Modules / REST Enabled SQL

Exposing RESTful Services using APEX and ORDS

Tip 2:

Read the official documentation about APEX 18

  


Tip 3:

Install Applications from the gallery,  try to reproduce or just try to understand things that you don’t know.


Tip 4 - Small tips:

  • Review Universal Theme and all components.
  • Review the components with data source and its type of data source.
  • Review all the things that you can do on shared components.
  • Personally, I didn't see any question about JavaScript.
  • Create your own application and try to force errors, determinate the error and solve it.
  • Understand the basic concepts, for example what is the structure of an URL, what is schema authorization, authentication.

   
Tip 4 The most important: 

On the exam web you can find all the topics that you need to study.






Share:

Sunday, June 23, 2019

Mi primera aplicación con Oracle APEX Parte 2/2, Creando Aplicativo Empleados

En este post veremos cómo usar un dataset de empleados para crear nuestra primera aplicación con Oracle APEX.

Ir a Sql Workshop -> Utilities -> Sample Datasets

Seleccionamos el de Install EMP/DEPT, y next en la ventana que se abre.

Install Datasets


Create Application

Las paginas se habrán creado por defecto con alguna configuración adicional. Le damos en create.


Ejecutamos la aplicación

Y finalmente tendremos nuestra aplicación creada.


Share:

Mi primera aplicación con Oracle APEX Parte 1/2, Solicitando un workspace

Para empezar nuestro desarrollo en APEX, requerimos un espacio de trabajo (Workspace).


Existen dos formas de poder tener un workspace:
La primera es de forma local instalando oracle aquí les dejo un link con este procedimiento que toma un poco más de tiempo.
La segunda forma es socitar un espacio de trabajo en https://apex.oracle.com/
Para esto nos dirigimos a apex.oracle.com y le damos en "Get started for free"


Luego "Request a free workspace"


En los puntos 1,2,3 ingresamos nuestra información básica, Para el punto 4 el nombre del WORKSPACE puede ser cualquiera, por ejemplo, algo que represente al uso que le daremos.


Una encuesta que marcamos a nuestra preferencia


Luego una pequeña justificación por que solicitamos el workspace, en mi caso entrenamiento

Aceptamos los términos y condiciones

Confirmamos nuestros datos y enviamos la solicitud.

A los pocos minutos recibiremos un mensaje que hemos solicitado un espacio de trabajo.
Aquí nos indica el nombre de nuestro workspace y le damos en crear workspace.

Un mensaje de que fue creado satisfactoriamente y le damos en siguiente.


Luego nos pedirá ingresar nuestra contraseña para poder acceder.

Finalmente nos llevara al entorno de APEX.


Para volver a ingresar le vamos a https://apex.oracle.com/pls/apex/ y le damos en "Sign In".
Ingresamos nuestros datos y accedemos.

Share:

Sunday, May 19, 2019

Validaciones en apex_item Oracle Apex

Buen día, en esta entrada responderé una pregunta que me hicieron en un video sobre apex_items, como agregar una validación que solo permita números en un apex_item.


Esto se puede lograr usando JavaScript y en este punto con JS tenemos muchos caminos, aquí mostrare uno usando una clase CSS como selector.

Teniendo como base mi ejemplo de este post Apex_item parte 3 , usare la columna SAL para validar que solo acepte números.



Vamos al Query del reporte y agregamos una clase que nos servirá de identificador.


Creamos una acción dinámica:
Evento: Key Press
Tipo: Jquery Selector
Selector: .item_sal


En el código JS validaremos que solo se ingrese números usando el KeyCode y si no cancelamos la acción y mostraremos un mensaje en consola.


 var be = this.browserEvent;

if (be.keyCode < 48 || be.keyCode > 57)
{
    be.preventDefault();
  console.log( be.key + " is not number");
}




Pueden ver la demo aqui. user/pass: demo/demo
Share:

Tuesday, March 5, 2019

Install Oracle DataBase 18c Express and Oracle Apex 18.2 / PL/SQL Gateway / Windows 10

In this tutorial I going to show you how to install Oracle 18c Express and Oracle Apex 18.2 into Windows  




We need to know since version Oracle 12, exists the concepts of plug-gable databases and containers.
So first download oracle database and oracle apex:

Oracle Database Express Edition (XE) Release 18.4.0.0.0 (18c)
Oracle APEX Release 18.2.0.00.12

Use the setup and next.


 We need to provide and remember the passwords of sys, system y PDBADMIN





Finally we will have the URLs where we can access to the database
So, here i have some troubles to access because my listener was stopped.


The URL for access is : https://localhost:5500/em


If you have problems to access. Check using

lsnrctl status


If the listener is stopped, you can start using:

lsnrctl start

About listener :

Foro Oracle 1
Foro Oracle 2

This point is very important.

Firsts we going to check the current pdbs, connect to sqlplus as execute show pdbs, it must the display the correct mode, read only and read write.

Look this guides if is different
Guía 1
Guía 2


Beforo to start the install, we must to select the correct pdb.

ALTER SESSION SET CONTAINER = XEPDB1;



The containers since Oracle 12, is like this, for that reason before to install we need to select to correct container. This link  is a resume about that.


Next, Go to directory where you have apex 18.2 uncompressed, and install,

Guide Oficial Oracle.

@apexins.sql SYSAUX SYSAUX TEMP /i/


Set the password of admin.

@apxchpwd.sql


Configure the Pl/Sql Gateway for local environment.
Use the parent directory as URL.

@apex_epg_config.sql C:\MyPc\InstallApex



Next , check the port:

SELECT DBMS_XDB.GETHTTPPORT FROM DUAL;

If is 0 we need to change with 8080, or another.

EXEC DBMS_XDB.SETHTTPPORT(8080);



The last step, connect in another cmd as sysdba, and show pdbs, for be sure we are in both container, PDB$SEDD and XEPDB1.

If we are in both and with that mode, execute:

ALTER USER ANONYMOUS ACCOUNT UNLOCK;



Finally we can enter to Oracle Apex 18.2

http://localhost:8080/apex
http://localhost:8080/apex/apex_admin

First time enter as workspace Internal and user admin , and pass of the istallation.

References:

Oracle Database Express Edition (XE) Release 18.4.0.0.0 (18c)
Oracle APEX Release 18.2.0.00.12
Si te olvidaste de seleccionar el contenedor o tienes errores al crear el workspace
Problemas con activar el read write en los contenedores 1
Problemas con activar el read write en los contenedores 2
Guía instalacion Oracle 18c express 
Guía instalacion Oracle APEX 18.2
Acerca de pluggable database


Share:

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