ejemplo mantenimiento dbf usando webview2

ejemplo mantenimiento dbf usando webview2

Postby leandro » Sun Oct 06, 2024 7:20 pm

Hola buenas tardes para todos, montamos este ejemplo en donde podemos hacer mantenimiento a la dbf customers.dbf que esta en la carpeta samples de fivewin.

La idea era poder entender el funcionamiento del webview2, para poder aplicarlo a mediano plazo en nuestras aplicaciones, esta creado en html5, css y javascript puro, para los maestros, es posible que se pueda simplificar mucho el código usado, sobre todo del lado de javascript; ya teniendo otros recursos como un servidor, podemos enlazar librerías como jquery y boostrap.

Como digo fue montado para entender el funcionamiento webview2, lo compartimos por si alguien algún día llega a necesitarlo, le interesa y quizás le sirva de guía.

Con esto lo que pretendemos es poder mejorar en MUCHO la parte visual o interfase de usuario de nuestras apps, apoyándonos en las maravillas que permite el html y sus amigos jejejeje.

Esperamos les sirva.

Pdta. Apenas nos quede un tiempito vamos a generar un reporte tipo html para ser enviado a la impresora.

Image
Image
Image

webview_custo.prg
Code: Select all  Expand view  RUN

#include "FiveWin.ch"

static oWebView
static d_custo

function Main()

    Local oWnd,cHtml

    USE "customer.dbf" ALIAS d_custo NEW EXCLUSIVE VIA "DBFCDX"
    INDEX ON d_custo->id TAG "id"
    d_custo->(OrdSetFocus("id"))
   
    cHtml := buildHtml()

    DEFINE WINDOW oWnd TITLE "Information maintenance" SIZE 1200, 800
        oWebView = TWebView2():New( oWnd )
        oWebView:SetHtml( cHtml )
        oWebView:InjectJavascript( cJavascript() )
        oWebView:bOnBind = { | cJson, cCalls | whatscoming( cJson ) }      
        //oWebView:OpenDevToolsWindow()
    ACTIVATE WINDOW oWnd CENTER ON RESIZE oWebView:SetSize( nWidth, nHeight ) VALID (d_custo->(DbCloseArea()),.T.)

    oWebView:End()

return nil

function whatscoming( cJson )
    Local oDlg,oGId,oGNm,oGAp,oGDi,oGEd,oGCi,oGSa
    Local cName, cLast,cStreet,cCity,cAge,cSalary,cIdBack
    Local nGId := 0
    Local nGEd := 0
    Local nGSa := 0
    Local nIdDbf := 0
    Local cGNm := space(0)
    Local cGAp := space(0)
    Local cGDi := space(0)
    Local cGCi := space(0)
    Local cIdRow := space(0)
    Local cInsRow := space(0)
    Local nAction := cJson[1]["action"]

    if nAction==1

        nGId := cJson[1]["datos"][1]
        cGNm := cJson[1]["datos"][2]
        cGAp := cJson[1]["datos"][3]
        cGDi := cJson[1]["datos"][4]
        cGCi := cJson[1]["datos"][5]
        nGEd := val(cJson[1]["datos"][6])
        nGSa := val(strtran(cJson[1]["datos"][7],",",""))
       
        DEFINE DIALOG oDlg SIZE 350,250 PIXEL TRUEPIXEL TITLE "Edit Row"
            @ 14,  15 SAY "Id :" SIZE 100,24 PIXEL OF oDlg
            @ 10,  88 GET oGId VAR nGId SIZE 50,24 PIXEL OF oDlg PICTURE "999" RIGHT

            @ 40,  15 SAY "Name :" SIZE 100,24 PIXEL OF oDlg
            @ 36,  88 GET oGNm VAR cGNm SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 66,  15 SAY "Last :" SIZE 100,24 PIXEL OF oDlg
            @ 62,  88 GET oGAp VAR cGAp SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 92,  15 SAY "Adress :" SIZE 100,24 PIXEL OF oDlg
            @ 88,  88 GET oGDi VAR cGDi SIZE 200,24 PIXEL OF oDlg PICTURE "@N"

            @ 118,  15 SAY "City :" SIZE 100,24 PIXEL OF oDlg
            @ 114,  88 GET oGCi VAR cGCi SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 144,  15 SAY "Age :" SIZE 100,24 PIXEL OF oDlg
            @ 140,  88 GET oGEd VAR nGEd SIZE 40,24 PIXEL OF oDlg PICTURE "999" SPINNER

            @ 170,  15 SAY "Salary :" SIZE 100,24 PIXEL OF oDlg
            @ 166,  88 GET oGSa VAR nGSa SIZE 100,24 PIXEL OF oDlg PICTURE "999,999.99" RIGHT

           
            @ 220,15 BUTTONBMP OF oDlg PIXEL size 95, 24 PROMPT "Close" ACTION oDlg:End()
            @ 220,120 BUTTONBMP OF oDlg PIXEL size 120, 24 PROMPT "Update" //ACTION oDlg:End()
           
            oGId:disable()
            oDlg:lHelpIcon := .F.
       
        ACTIVATE DIALOG oDlg CENTERED   
   
    elseif nAction==2
        if msgnoyes("Confirm delete row ?","Confirm")
       
            nIdDbf := val(cJson[1]["datos"][1])
           
            SELECT d_custo
            DELETE FOR d_custo->id = nIdDbf
            PACK
       
            cIdRow := "row_"+alltrim(cJson[1]["datos"][1])
            oWebView:Eval( "deleterowhtmltable( '"+cIdRow+"' )" )
   
        endif
    elseif nAction==0
   
        nIdDbf := cJson[1]["datos"][1]
        cName := cJson[1]["datos"][2]
        cLast := cJson[1]["datos"][3]
        cStreet := cJson[1]["datos"][4]
        cCity := cJson[1]["datos"][5]
        cAge := val(cJson[1]["datos"][6])
        cSalary := val(cJson[1]["datos"][7])
   
        SELECT d_custo
        Dbgotop()
        if !dbseek(nIdDbf)
            dbappend()
            //d_custo->id := nIdDbf //Incremental
            d_custo->first := cName
            d_custo->last := cLast
            d_custo->street := cStreet
            d_custo->city := cCity
            d_custo->age := cAge
            d_custo->salary := cSalary
           
            cIdBack := cValtochar(d_custo->id)
           
            oWebView:Eval( "insertrowhtmltable('"+cIdBack+"','"+transform(cSalary,"999,999.99")+"');")
        else
            //With any of these options you can inform the user that the id already exists
           
            //msginfo("The id you are trying to enter already exists","Error")
            //oWebView:Eval( "document.getElementById('spn_id').innerHTML='<br>Exists'")
            oWebView:Eval( "alert('The id you are trying to enter already exists');")
        endif
       
       
       
    endif
   
return nil

function buildHtml()

    Local cHead,cFoot
    Local cHtml := space(0)
    Local cTable := space(0)
   
    TEXT INTO cHead
        <!DOCTYPE html>
        <html lang="es">
        <head>
            <meta charset="UTF-8">
            <style>
                body {
                    background-color: #e4f2ff;
                    display: flex;
                    flex-direction: column;
                    min-height: 100vh;
                }
                .main-content {
                    padding: 20px;
                    flex-grow: 1;
                    overflow-y: auto;
                }
                .table-container {
                    overflow-x: auto;
                }
                .table {
                    background-color: #fff;
                    min-width: 600px; /* Asegura que la tabla no se comprima demasiado en móviles */
                }
                h2 {
                    color: #0064a5;
                }
                footer {
                    background-color: #0064a5;
                    color: #fff;
                    text-align: center;
                    padding: 2rem 0;
                    margin-top: auto;
                }

                .btntbl {
                  border: none;
                  color: white;
                  padding: 5px 10px;
                  cursor: pointer;
                  border-radius: 5px;
                }
                .primary {background-color: #007bff;}
                .primary:hover {background: #0b7dda;}
                .secondary {background-color: #e7e7e7; color: black;}
                .secondary:hover {background: #ddd;}
                .success {background-color: #04AA6D;}
                .success:hover {background-color: #46a049;}
                .warning {background-color: #ff9800;}
                .warning:hover {background: #e68a00;}
                .danger {background-color: #f44336;}
                .danger:hover {background: #da190b;}
               
                .form-group {
                    margin-bottom: 15px;
                }

                .form-group label {
                    display: flex;
                    font-size: 16px;
                    font-weight: bold;
                    margin-bottom: 2px;
                    color: #0693e3;
                }

                .form-group input {
                    width: 90%;
                    padding: 5px;
                    font-size: 14px;
                    border-radius: 5px;
                    border: 1px solid #0693e3;
                }   

                .msg{
                    color: #f44336;
                }
               
                /* The Modal (background) */
                .modal {
                  display: none; /* Hidden by default */
                  position: fixed; /* Stay in place */
                  z-index: 1; /* Sit on top */
                  padding-top: 20px; /* Location of the box */
                  left: 0;
                  top: 0;
                  width: 100%; /* Full width */
                  height: 100%; /* Full height */
                  overflow: auto; /* Enable scroll if needed */
                  background-color: rgb(0,0,0); /* Fallback color */
                  background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
                }

                /* Modal Content */
                .modal-content {
                  background-color: #fefefe;
                  margin: auto;
                  padding: 20px;
                  border: 1px solid #888;
                  width: 40%;
                }

                /* The Close Button */
                .close {
                  color: #aaaaaa;
                  float: right;
                  font-size: 28px;
                  font-weight: bold;
                }

                .close:hover,
                .close:focus {
                  color: #000;
                  text-decoration: none;
                  cursor: pointer;
                }   

                table.tableSection {
                  display: table;
                  width: 100%;
                }

                table.tableSection thead,
                table.tableSection tbody {
                  width: 100%;
                }

                table.tableSection thead {
                  overflow-y: scroll;
                  display: table;
                  table-layout: fixed;
                  width: calc(100% - 16px); /* assuming scrollbar width as 16px */
                }

                table.tableSection tbody {
                  overflow: auto;
                  height: 500px;
                  display: block;
                }

                table.tableSection tr {
                  width: 100%;
                  text-align: left;
                  display: table;
                  table-layout: fixed;
                }
               
                table.tableSection tr:hover {
                    background-color: #f8f9fa;
                }              
               
               
               
            </style>
        </head>
        <body>
            <div class="container-fluid">
                <div class="row">
                    <!-- Contenido principal -->
                    <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4 main-content">
                        <!-- Trigger/Open The Modal -->
                        <button id="myBtn" onclick="openmodal();" class="btntbl success">New</button>
                        <h2 class="mb-4">Customer Table </h2>
                        <div class="table-container">
                            <table class="tableSection" id="tbl_cstm">
                                <thead>
                                    <tr>
                                        <th style="width:25px">ID</th>
                                        <th style="width:100px">Name</th>
                                        <th style="width:100px">Last</th>
                                        <th style="width:220px">Adress</th>
                                        <th>City</th>
                                        <th>Age</th>
                                        <th>Salary</th>
                                        <th colspan="2">Actions</th>
                                    </tr>
                                </thead>
                                <tbody id="tableBody">
    ENDTEXT
   
   
    TEXT INTO cFoot

                                </tbody>
                            </table>
                        </div>
                    </main>
                </div>
            </div>

            <footer>
                <p>&copy; 2024 My App. All rights reserved.</p>
            </footer>
           
            <!-- The Modal -->
            <div id="myModal" class="modal">

              <!-- Modal content -->
              <div class="modal-content">
                <span class="close" role="button" onclick="closemodal();" title="Close Modal (Cancel)">&times;</span>
                <h2>Customer data</h2>
                <div id="form_data">
                    <div class="form-group">
                        <label for="id">Id:</label>
                        <input type="text" id="id" name="id" class="myinput" value="0" disabled></input>
                        <span id="spn_id" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" id="name" name="name" class="myinput" >
                        <span id="spn_name" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="last">Last:</label>
                        <input type="text" id="last" name="last" class="myinput" >
                        <span id="spn_last" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="adress">Adress:</label>
                        <input type="text" id="adress" name="adress" class="myinput" >
                        <span id="spn_adress" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="city">City:</label>
                        <input type="text" id="city" name="city" class="myinput" >
                        <span id="spn_city" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="age">Age:</label>
                        <input type="number" id="age" name="age" class="myinput" >
                        <span id="spn_age" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="salary">Salary:</label>
                        <input type="number" id="salary" name="salary" class="myinput" >
                        <span id="spn_salary" class="msg"></span>
                    </div>
                    <div class="form-group" >
                        <button type="submit" class="btntbl success" onclick="newdata();">Acept</button>
                    </div>

                </div>
              </div>

            </div> 

        </body>
        </html> 
    ENDTEXT 

    SELECT d_custo
    Dbgotop()   
    Do While !EOF()
       
        cTable += "<tr id='row_"+cValtochar(d_custo->id)+"'>"
            cTable += "<td style='width:25px'>"+transform(d_custo->id,"999")+"</td>"
            cTable += "<td style='width:100px'>"+alltrim(d_custo->first)+"</td>"
            cTable += "<td style='width:100px'>"+alltrim(d_custo->last)+"</td>"
            cTable += "<td style='width:220px'>"+alltrim(d_custo->street)+"</td>"
            cTable += "<td>"+alltrim(d_custo->city)+"</td>"
            cTable += "<td>"+transform(d_custo->age,"999")+"</td>"
            cTable += "<td align='right'>"+transform(d_custo->salary,"999,999.99")+"</td>"
            cTable += "<td>"
                cTable += "<button onclick='how("+cValtochar(d_custo->id)+",1)' title='Edit' class='btntbl primary'>Edit</button>"
            cTable += "</td>"
            cTable += "<td>"
                cTable += "<button onclick='how("+cValtochar(d_custo->id)+",2)' title='Delete' class='btntbl danger'>Delete</button>"
            cTable += "</td>"
        cTable += "</tr>"
        d_custo->(DBSKIP())

    EndDo   
   
    cHtml := cHead+cTable+cFoot


return cHtml

function cJavascript()
    Local cInyec
    TEXT INTO cInyec
        function how(id,acc){
            var id_row = "row_"+id;
            var therow = document.getElementById(id_row);
            var aDatos = new Array();
            var objeto = { action : 0 ,id : "", datos : []};
            var elementsrow = therow.getElementsByTagName("td");
            for(i=0;i<7;i++){
                aDatos.push(elementsrow[i].innerHTML);
            }          
            objeto.action = acc;
            objeto.id = id;
            objeto.datos = aDatos;
            SendToFWH(objeto)
        }
       
        function openmodal(){
            var lamodal = document.getElementById("myModal");
            lamodal.style.display = "block";
        }
       
        function closemodal(){
            var lamodal = document.getElementById("myModal");
            lamodal.style.display = "none";
        }
       
        function newdata(){
            var id_row = "row_0";
            var aDatos = new Array();
            var objeto = { action : 0 ,id : 0, datos : []};
            var aErrores = new Array();
           
            var theform = document.getElementById("form_data");
            var theinputs = theform.getElementsByTagName("input");
            for(i=0;i<theinputs.length;i++){
               
                var idname = theinputs[i].id;
                var id_span = "spn_"+idname;
                var oSpan = document.getElementById(id_span);
                if(theinputs[i].value==""){
                    var cErro = "Please input "+idname;
                    aErrores.push(cErro);
                    oSpan.innerHTML = cErro;
                }else{
                    oSpan.innerHTML = "";
                }          
            }
           
            if (aErrores.length==0){
                aDatos.push(document.getElementById("id").value);
                aDatos.push(document.getElementById("name").value);
                aDatos.push(document.getElementById("last").value);
                aDatos.push(document.getElementById("adress").value);
                aDatos.push(document.getElementById("city").value);
                aDatos.push(document.getElementById("age").value);
                aDatos.push(document.getElementById("salary").value);
                objeto.datos = aDatos;
                SendToFWH(objeto)
            }
        }

        function deleterowhtmltable(id){
            var idrowdel = document.getElementById(id);
            idrowdel.remove();
        }

        function insertrowhtmltable(idDbf,cSal){
            var cIdRow = "row_"+idDbf;
            var tbldata = document.getElementById("tbl_cstm").insertRow(-1);
            tbldata.setAttribute("id", cIdRow );
            var oCol1 = tbldata.insertCell(0);
            var oCol2 = tbldata.insertCell(1);
            var oCol3 = tbldata.insertCell(2);
            var oCol4 = tbldata.insertCell(3);
            var oCol5 = tbldata.insertCell(4);
            var oCol6 = tbldata.insertCell(5);
            var oCol7 = tbldata.insertCell(6);
            var oCol8 = tbldata.insertCell(7);
            var oCol9 = tbldata.insertCell(8);

            oCol1.innerHTML = idDbf;
            oCol1.style.width = "25px";
            oCol2.innerHTML = document.getElementById("name").value;
            oCol2.style.width = "100px";
            oCol3.innerHTML = document.getElementById("last").value;
            oCol3.style.width = "100px";
            oCol4.innerHTML = document.getElementById("adress").value;
            oCol4.style.width = "220px";
            oCol5.innerHTML = document.getElementById("city").value;
            oCol6.innerHTML = document.getElementById("age").value;
            oCol7.innerHTML = cSal;
            oCol7.setAttribute("align", "right");
           
            oCol8.innerHTML = "<button onclick='how("+idDbf+",1)' title='Edit' class='btntbl primary'>Edit</button>";
            oCol9.innerHTML = "<button onclick='how("+idDbf+",2)' title='Delete' class='btntbl danger'>Delete</button>";

            location.hash = "#"+cIdRow;
           
            closemodal();
       
        }

    ENDTEXT

Return cInyec
 
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Re: ejemplo mantenimiento dbf usando webview2

Postby Antonio Linares » Mon Oct 07, 2024 3:09 am

muy bien! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: ejemplo mantenimiento dbf usando webview2

Postby cpheraclio » Mon Oct 07, 2024 2:28 pm

Application
===========
Path and name: C:\Users\Admin\Documents\fwh64\proyects\ContaSic.exe (64 bits)
Size: 8,997,888 bytes
Compiler version: Harbour 3.2.0dev (r2407221137)
FiveWin version: FWH 24.07
C compiler version: Microsoft Visual C 19.32.31329 (64-bit)
Windows 11 64 Bits, version: 6.2, Build 9200

Time from start: 0 hours 0 mins 3 secs
Error occurred at: 07/10/24, 08:24:32
Error description: Error BASE/1070 Error de argumento: ==
Args:
[ 1] = N 0
[ 2] = P 0x2682DD5DD18

Stack Calls
===========
Called from: .\source\classes\twebview2.prg => (b)WEBVIEW2_ONEVAL( 0 )
Called from: .\source\ContaSic.prg => ASCAN( 0 )
Called from: .\source\classes\twebview2.prg => WEBVIEW2_ONEVAL( 0 )
Called from: .\source\classes\window.prg => WINRUN( 0 )
Called from: .\source\classes\window.prg => TWINDOW:ACTIVATE( 0 )
Called from: .\source\ContaSic.prg => MAIN( 43 )
cpheraclio
 
Posts: 11
Joined: Thu Mar 17, 2022 6:47 pm

Re: ejemplo mantenimiento dbf usando webview2

Postby cpheraclio » Mon Oct 07, 2024 7:13 pm

Modificando twebview2

//----------------------------------------------------------------------------//

//function WebView2_OnEval( cJson, hWebView )
//
// local nAt := AScan( aWebViews, { | o | o:hWebView == hWebView } ), nResult
//
// if nAt != 0 .and. ! Empty( aWebViews[ nAt ]:bOnEval )
// nResult = Eval( aWebViews[ nAt ]:bOnEval, cJson, hWebView )
// endif
//
//return nResult

function WebView2_OnEval( cJson, hWebView )

local nAt := AScan( aWebViews, { | o | MsgInfo( o:hWebView ), MsgInfo( hWebView ), o:hWebView == hWebView } ), nResult

if nAt != 0 .and. ! Empty( aWebViews[ nAt ]:bOnEval )
nResult = Eval( aWebViews[ nAt ]:bOnEval, cJson, hWebView )
endif

return nResult


Con el ejemplo de Leandro
Application
===========
Path and name: C:\Users\Admin\Documents\fwh64\proyects\ContaSic.exe (64 bits)
Size: 8,997,376 bytes
Compiler version: Harbour 3.2.0dev (r2407221137)
FiveWin version: FWH 24.07
C compiler version: Microsoft Visual C 19.32.31329 (64-bit)
Windows 11 64 Bits, version: 6.2, Build 9200

Time from start: 0 hours 0 mins 6 secs
Error occurred at: 07/10/24, 12:50:31
Error description: Error BASE/1070 Error de argumento: ==
Args:
[ 1] = N 0
[ 2] = P 0x220A5201928

Stack Calls
===========
Called from: .\source\twebview2.prg => (b)WEBVIEW2_ONEVAL( 138 )
Called from: .\source\ContaSic.prg => ASCAN( 0 )
Called from: .\source\twebview2.prg => WEBVIEW2_ONEVAL( 138 )
Called from: .\source\classes\window.prg => WINRUN( 0 )
Called from: .\source\classes\window.prg => TWINDOW:ACTIVATE( 0 )
Called from: .\source\ContaSic.prg => MAIN( 43 )
cpheraclio
 
Posts: 11
Joined: Thu Mar 17, 2022 6:47 pm

Re: ejemplo mantenimiento dbf usando webview2

Postby leandro » Mon Oct 07, 2024 7:35 pm

Hola buenas tardes, gracias por reportarlo, creo que únicamente funciona con la nueva versión de fw 2409, el error ya lo estamos intentando solucionar en otro POST, con la ayuda de Antonio.

https://forums.fivetechsupport.com/viewtopic.php?f=6&t=44795&start=45&sid=84037a9d8ab972ef080a33ed7c8794a7#p274391
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Re: ejemplo mantenimiento dbf usando webview2

Postby cpheraclio » Mon Oct 07, 2024 8:11 pm

leandro wrote:Hola buenas tardes, gracias por reportarlo, creo que únicamente funciona con la nueva versión de fw 2409, el error ya lo estamos intentando solucionar en otro POST, con la ayuda de Antonio.

https://forums.fivetechsupport.com/viewtopic.php?f=6&t=44795&start=45&sid=0ffba0c70042bafc49b16738600f78d3&sid=0ffba0c70042bafc49b16738600f78d3#p274391


Buenas tardes:

Es con la versión 64-2409 (fue Lib que me pasó Antonio Linares), no tengo idea de porque aparece 64-2407

Sigo al pendiente de la solución, gracias.
cpheraclio
 
Posts: 11
Joined: Thu Mar 17, 2022 6:47 pm

Re: ejemplo mantenimiento dbf usando webview2

Postby Antonio Linares » Tue Oct 08, 2024 3:47 am

> Es con la versión 64-2409 (fue Lib que me pasó Antonio Linares), no tengo idea de porque aparece 64-2407

La versión la toma de FiveWin.ch
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: ejemplo mantenimiento dbf usando webview2

Postby cpheraclio » Tue Oct 08, 2024 11:41 am

Antonio Linares wrote:> Es con la versión 64-2409 (fue Lib que me pasó Antonio Linares), no tengo idea de porque aparece 64-2407

La versión la toma de FiveWin.ch


Contenido de fivewin.ch

/*
!short: FiveWin main Header File */

#ifndef _FIVEWIN_CH
#define _FIVEWIN_CH

#define FWCOPYRIGHT "(c) FiveTech Software, 1993-2023"

#define FWVERSION "FWH 24.09"
#define FW_VersionNo 24090

#ifdef __XHARBOUR__
#ifndef __64__
#define FWDESCRIPTION "FiveWin for xHarbour"
#else
#define FWDESCRIPTION "FiveWin for xHarbour 64"
#endif
#else
#ifndef __64__
#define FWDESCRIPTION "FiveWin for Harbour"
#else
#define FWDESCRIPTION "FiveWin for Harbour 64"
#endif
#endif
cpheraclio
 
Posts: 11
Joined: Thu Mar 17, 2022 6:47 pm

Re: ejemplo mantenimiento dbf usando webview2

Postby acuellar » Tue Oct 08, 2024 11:42 am

Gracias Leandro

Funciona Perfecto.

Faltaría lo de la actualización de los datos
Saludos,

Adhemar C.
User avatar
acuellar
 
Posts: 1644
Joined: Tue Oct 28, 2008 6:26 pm
Location: Santa Cruz-Bolivia

Re: ejemplo mantenimiento dbf usando webview2

Postby leandro » Wed Oct 09, 2024 6:40 pm

Adhemar buenas tardes como estas?

Vale, lo reviso y la publico.
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Re: ejemplo mantenimiento dbf usando webview2

Postby leandro » Fri Oct 11, 2024 10:07 pm

Listo Adhemar ya quedo, con la actualización del registro. Que pena habia colocado la versión que no era. :oops:

Code: Select all  Expand view  RUN

#include "FiveWin.ch"

static oWebView
static d_custo

function Main()

    Local oWnd,cHtml

    USE "customer.dbf" ALIAS d_custo NEW EXCLUSIVE VIA "DBFCDX"
    INDEX ON d_custo->id TAG "id"
    d_custo->(OrdSetFocus("id"))
   
    cHtml := buildHtml()

    DEFINE WINDOW oWnd TITLE "Information maintenance" SIZE 1200, 800
        oWebView = TWebView2():New( oWnd )
        oWebView:SetHtml( cHtml )
        oWebView:InjectJavascript( cJavascript() )
        oWebView:bOnBind = { | cJson, cCalls | whatscoming( cJson ) }      
        oWebView:OpenDevToolsWindow()
    ACTIVATE WINDOW oWnd CENTER ON RESIZE oWebView:SetSize( nWidth, nHeight ) VALID (d_custo->(DbCloseArea()),.T.)

    oWebView:End()

return nil

function whatscoming( cJson )
    Local oDlg,oGId,oGNm,oGAp,oGDi,oGEd,oGCi,oGSa
    Local cName, cLast,cStreet,cCity,cAge,cSalary,cIdBack
    Local nGId := 0
    Local nGEd := 0
    Local nGSa := 0
    Local nIdDbf := 0
    Local cGNm := space(0)
    Local cGAp := space(0)
    Local cGDi := space(0)
    Local cGCi := space(0)
    Local cIdRow := space(0)
    Local cInsRow := space(0)
    Local nAction := cJson[1]["action"]
    Local bUpdateRow := <||
   
        SELECT d_custo
        Dbgotop()
        if dbseek(nGId)
            d_custo->first := cGNm
            d_custo->last := cGAp
            d_custo->street := cGDi
            d_custo->city := cGCi
            d_custo->age := nGEd
            d_custo->salary := nGSa
           
            //oWebView:Eval( "alert('listo en la dbf');")
            oWebView:Eval( "updaterowhtmltable('"+cValtochar(nGId)+"','"+cGNm+"','"+cGAp+"','"+cGDi+"','"+cGCi+"','"+cValtochar(nGEd)+"','"+transform(nGSa,"999,999.99")+"');")
        endif
       
        oDlg:end()
       
    >
   
    Local bComplete := <|cCnd,nLen|
        Local cCmp := alltrim(cCnd)
        Local nLac := len(cCmp)
        cCmp += space(nLen-nLac)
        return cCmp
    >
   
    if nAction==1

        nGId := val(cJson[1]["datos"][1])
        cGNm := EVAL(bComplete,cJson[1]["datos"][2],20)
        cGAp := EVAL(bComplete,cJson[1]["datos"][3],20)
        cGDi := EVAL(bComplete,cJson[1]["datos"][4],30)
        cGCi := EVAL(bComplete,cJson[1]["datos"][5],30)
        nGEd := val(cJson[1]["datos"][6])
        nGSa := val(strtran(cJson[1]["datos"][7],",",""))
       
        DEFINE DIALOG oDlg SIZE 350,250 PIXEL TRUEPIXEL TITLE "Edit Row"
            @ 14,  15 SAY "Id :" SIZE 100,24 PIXEL OF oDlg
            @ 10,  88 GET oGId VAR nGId SIZE 50,24 PIXEL OF oDlg PICTURE "999" RIGHT

            @ 40,  15 SAY "Name :" SIZE 100,24 PIXEL OF oDlg
            @ 36,  88 GET oGNm VAR cGNm SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 66,  15 SAY "Last :" SIZE 100,24 PIXEL OF oDlg
            @ 62,  88 GET oGAp VAR cGAp SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 92,  15 SAY "Adress :" SIZE 100,24 PIXEL OF oDlg
            @ 88,  88 GET oGDi VAR cGDi SIZE 200,24 PIXEL OF oDlg PICTURE "@N"

            @ 118,  15 SAY "City :" SIZE 100,24 PIXEL OF oDlg
            @ 114,  88 GET oGCi VAR cGCi SIZE 140,24 PIXEL OF oDlg PICTURE "@N"

            @ 144,  15 SAY "Age :" SIZE 100,24 PIXEL OF oDlg
            @ 140,  88 GET oGEd VAR nGEd SIZE 40,24 PIXEL OF oDlg PICTURE "99" SPINNER

            @ 170,  15 SAY "Salary :" SIZE 100,24 PIXEL OF oDlg
            @ 166,  88 GET oGSa VAR nGSa SIZE 100,24 PIXEL OF oDlg PICTURE "999,999.99" RIGHT

           
            @ 220,15 BUTTONBMP OF oDlg PIXEL size 95, 24 PROMPT "Close" ACTION oDlg:End()
            @ 220,120 BUTTONBMP OF oDlg PIXEL size 120, 24 PROMPT "Update" ACTION EVAL(bUpdateRow)
           
            oGId:disable()
            oDlg:lHelpIcon := .F.
       
        ACTIVATE DIALOG oDlg CENTERED   
   
    elseif nAction==2
        if msgnoyes("Confirm delete row ?","Confirm")
       
            nIdDbf := val(cJson[1]["datos"][1])
           
            SELECT d_custo
            DELETE FOR d_custo->id = nIdDbf
            PACK
       
            cIdRow := "row_"+alltrim(cJson[1]["datos"][1])
            oWebView:Eval( "deleterowhtmltable( '"+cIdRow+"' )" )
   
        endif
    elseif nAction==0
   
        nIdDbf := cJson[1]["datos"][1]
        cName := cJson[1]["datos"][2]
        cLast := cJson[1]["datos"][3]
        cStreet := cJson[1]["datos"][4]
        cCity := cJson[1]["datos"][5]
        cAge := val(cJson[1]["datos"][6])
        cSalary := val(cJson[1]["datos"][7])
   
        SELECT d_custo
        Dbgotop()
        if !dbseek(nIdDbf)
            dbappend()
            //d_custo->id := nIdDbf //Incremental
            d_custo->first := cName
            d_custo->last := cLast
            d_custo->street := cStreet
            d_custo->city := cCity
            d_custo->age := cAge
            d_custo->salary := cSalary
           
            cIdBack := cValtochar(d_custo->id)
           
            oWebView:Eval( "insertrowhtmltable('"+cIdBack+"','"+transform(cSalary,"999,999.99")+"');")
        else
            //With any of these options you can inform the user that the id already exists
           
            //msginfo("The id you are trying to enter already exists","Error")
            //oWebView:Eval( "document.getElementById('spn_id').innerHTML='<br>Exists'")
            oWebView:Eval( "alert('The id you are trying to enter already exists');")
        endif
       
       
       
    endif
   
return nil

function buildHtml()

    Local cHead,cFoot
    Local cHtml := space(0)
    Local cTable := space(0)
   
    TEXT INTO cHead
        <!DOCTYPE html>
        <html lang="es">
        <head>
            <meta charset="UTF-8">
            <style>
                body {
                    background-color: #e4f2ff;
                    display: flex;
                    flex-direction: column;
                    min-height: 100vh;
                }
                .main-content {
                    padding: 20px;
                    flex-grow: 1;
                    overflow-y: auto;
                }
                .table-container {
                    overflow-x: auto;
                }
                .table {
                    background-color: #fff;
                    min-width: 600px; /* Asegura que la tabla no se comprima demasiado en móviles */
                }
                h2 {
                    color: #0064a5;
                }
                footer {
                    background-color: #0064a5;
                    color: #fff;
                    text-align: center;
                    padding: 2rem 0;
                    margin-top: auto;
                }

                .btntbl {
                  border: none;
                  color: white;
                  padding: 5px 10px;
                  cursor: pointer;
                  border-radius: 5px;
                }
                .primary {background-color: #007bff;}
                .primary:hover {background: #0b7dda;}
                .secondary {background-color: #e7e7e7; color: black;}
                .secondary:hover {background: #ddd;}
                .success {background-color: #04AA6D;}
                .success:hover {background-color: #46a049;}
                .warning {background-color: #ff9800;}
                .warning:hover {background: #e68a00;}
                .danger {background-color: #f44336;}
                .danger:hover {background: #da190b;}
               
                .form-group {
                    margin-bottom: 15px;
                }

                .form-group label {
                    display: flex;
                    font-size: 16px;
                    font-weight: bold;
                    margin-bottom: 2px;
                    color: #0693e3;
                }

                .form-group input {
                    width: 90%;
                    padding: 5px;
                    font-size: 14px;
                    border-radius: 5px;
                    border: 1px solid #0693e3;
                }   

                .msg{
                    color: #f44336;
                }
               
                /* The Modal (background) */
                .modal {
                  display: none; /* Hidden by default */
                  position: fixed; /* Stay in place */
                  z-index: 1; /* Sit on top */
                  padding-top: 20px; /* Location of the box */
                  left: 0;
                  top: 0;
                  width: 100%; /* Full width */
                  height: 100%; /* Full height */
                  overflow: auto; /* Enable scroll if needed */
                  background-color: rgb(0,0,0); /* Fallback color */
                  background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
                }

                /* Modal Content */
                .modal-content {
                  background-color: #fefefe;
                  margin: auto;
                  padding: 20px;
                  border: 1px solid #888;
                  width: 40%;
                }

                /* The Close Button */
                .close {
                  color: #aaaaaa;
                  float: right;
                  font-size: 28px;
                  font-weight: bold;
                }

                .close:hover,
                .close:focus {
                  color: #000;
                  text-decoration: none;
                  cursor: pointer;
                }   

                table.tableSection {
                  display: table;
                  width: 100%;
                }

                table.tableSection thead,
                table.tableSection tbody {
                  width: 100%;
                }

                table.tableSection thead {
                  overflow-y: scroll;
                  display: table;
                  table-layout: fixed;
                  width: calc(100% - 16px); /* assuming scrollbar width as 16px */
                }

                table.tableSection tbody {
                  overflow: auto;
                  height: 500px;
                  display: block;
                }

                table.tableSection tr {
                  width: 100%;
                  text-align: left;
                  display: table;
                  table-layout: fixed;
                }
               
                table.tableSection tr:hover {
                    background-color: #f8f9fa;
                }              
               
               
               
            </style>
        </head>
        <body>
            <div class="container-fluid">
                <div class="row">
                    <!-- Contenido principal -->
                    <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4 main-content">
                        <!-- Trigger/Open The Modal -->
                        <button id="myBtn" onclick="openmodal();" class="btntbl success">New</button>
                        <h2 class="mb-4">Customer Table </h2>
                        <div class="table-container">
                            <table class="tableSection" id="tbl_cstm">
                                <thead>
                                    <tr>
                                        <th style="width:25px">ID</th>
                                        <th style="width:100px">Name</th>
                                        <th style="width:100px">Last</th>
                                        <th style="width:220px">Adress</th>
                                        <th>City</th>
                                        <th>Age</th>
                                        <th>Salary</th>
                                        <th colspan="2">Actions</th>
                                    </tr>
                                </thead>
                                <tbody id="tableBody">
    ENDTEXT
   
   
    TEXT INTO cFoot

                                </tbody>
                            </table>
                        </div>
                    </main>
                </div>
            </div>

            <footer>
                <p>&copy; 2024 My App. All rights reserved.</p>
            </footer>
           
            <!-- The Modal -->
            <div id="myModal" class="modal">

              <!-- Modal content -->
              <div class="modal-content">
                <span class="close" role="button" onclick="closemodal();" title="Close Modal (Cancel)">&times;</span>
                <h2>Customer data</h2>
                <div id="form_data">
                    <div class="form-group">
                        <label for="id">Id:</label>
                        <input type="text" id="id" name="id" class="myinput" value="0" disabled></input>
                        <span id="spn_id" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" id="name" name="name" class="myinput" size="20">
                        <span id="spn_name" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="last">Last:</label>
                        <input type="text" id="last" name="last" class="myinput" size="20">
                        <span id="spn_last" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="adress">Adress:</label>
                        <input type="text" id="adress" name="adress" class="myinput" size="30">
                        <span id="spn_adress" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="city">City:</label>
                        <input type="text" id="city" name="city" class="myinput" size="30">
                        <span id="spn_city" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="age">Age:</label>
                        <input type="number" id="age" name="age" class="myinput" size="2">
                        <span id="spn_age" class="msg"></span>
                    </div>
                    <div class="form-group">
                        <label for="salary">Salary:</label>
                        <input type="number" id="salary" name="salary" class="myinput" size="9">
                        <span id="spn_salary" class="msg"></span>
                    </div>
                    <div class="form-group" >
                        <button type="submit" class="btntbl success" onclick="newdata();">Acept</button>
                    </div>

                </div>
              </div>

            </div> 

        </body>
        </html> 
    ENDTEXT 

    SELECT d_custo
    Dbgotop()   
    Do While !EOF()
       
        cTable += "<tr id='row_"+cValtochar(d_custo->id)+"'>"
            cTable += "<td style='width:25px'>"+transform(d_custo->id,"999")+"</td>"
            cTable += "<td style='width:100px'>"+alltrim(d_custo->first)+"</td>"
            cTable += "<td style='width:100px'>"+alltrim(d_custo->last)+"</td>"
            cTable += "<td style='width:220px'>"+alltrim(d_custo->street)+"</td>"
            cTable += "<td>"+alltrim(d_custo->city)+"</td>"
            cTable += "<td>"+transform(d_custo->age,"999")+"</td>"
            cTable += "<td align='right'>"+transform(d_custo->salary,"999,999.99")+"</td>"
            cTable += "<td>"
                cTable += "<button onclick='how("+cValtochar(d_custo->id)+",1)' title='Edit' class='btntbl primary'>Edit</button>"
            cTable += "</td>"
            cTable += "<td>"
                cTable += "<button onclick='how("+cValtochar(d_custo->id)+",2)' title='Delete' class='btntbl danger'>Delete</button>"
            cTable += "</td>"
        cTable += "</tr>"
        d_custo->(DBSKIP())

    EndDo   
   
    cHtml := cHead+cTable+cFoot


return cHtml

function cJavascript()
    Local cInyec
    TEXT INTO cInyec
        function how(id,acc){
            var id_row = "row_"+id;
            var therow = document.getElementById(id_row);
            var aDatos = new Array();
            var objeto = { action : 0 ,id : "", datos : []};
            var elementsrow = therow.getElementsByTagName("td");
            for(i=0;i<7;i++){
                aDatos.push(elementsrow[i].innerHTML);
            }          
            objeto.action = acc;
            objeto.id = id;
            objeto.datos = aDatos;
            SendToFWH(objeto)
        }
       
        function openmodal(){
            var lamodal = document.getElementById("myModal");
            lamodal.style.display = "block";
        }
       
        function closemodal(){
            var lamodal = document.getElementById("myModal");
            lamodal.style.display = "none";
        }
       
        function newdata(){
            var id_row = "row_0";
            var aDatos = new Array();
            var objeto = { action : 0 ,id : 0, datos : []};
            var aErrores = new Array();
           
            var theform = document.getElementById("form_data");
            var theinputs = theform.getElementsByTagName("input");
            for(i=0;i<theinputs.length;i++){
               
                var idname = theinputs[i].id;
                var id_span = "spn_"+idname;
                var oSpan = document.getElementById(id_span);
                if(theinputs[i].value==""){
                    var cErro = "Please input "+idname;
                    aErrores.push(cErro);
                    oSpan.innerHTML = cErro;
                }else{
                    oSpan.innerHTML = "";
                }          
            }
           
            if (aErrores.length==0){
                aDatos.push(document.getElementById("id").value);
                aDatos.push(document.getElementById("name").value);
                aDatos.push(document.getElementById("last").value);
                aDatos.push(document.getElementById("adress").value);
                aDatos.push(document.getElementById("city").value);
                aDatos.push(document.getElementById("age").value);
                aDatos.push(document.getElementById("salary").value);
                objeto.datos = aDatos;
                SendToFWH(objeto)
            }
        }

        function deleterowhtmltable(id){
            var idrowdel = document.getElementById(id);
            idrowdel.remove();
        }

        function insertrowhtmltable(idDbf,cSal){
            var cIdRow = "row_"+idDbf;
            var tbldata = document.getElementById("tbl_cstm").insertRow(-1);
            tbldata.setAttribute("id", cIdRow );
            var oCol1 = tbldata.insertCell(0);
            var oCol2 = tbldata.insertCell(1);
            var oCol3 = tbldata.insertCell(2);
            var oCol4 = tbldata.insertCell(3);
            var oCol5 = tbldata.insertCell(4);
            var oCol6 = tbldata.insertCell(5);
            var oCol7 = tbldata.insertCell(6);
            var oCol8 = tbldata.insertCell(7);
            var oCol9 = tbldata.insertCell(8);

            oCol1.innerHTML = idDbf;
            oCol1.style.width = "25px";
            oCol2.innerHTML = document.getElementById("name").value;
            oCol2.style.width = "100px";
            oCol3.innerHTML = document.getElementById("last").value;
            oCol3.style.width = "100px";
            oCol4.innerHTML = document.getElementById("adress").value;
            oCol4.style.width = "220px";
            oCol5.innerHTML = document.getElementById("city").value;
            oCol6.innerHTML = document.getElementById("age").value;
            oCol7.innerHTML = cSal;
            oCol7.setAttribute("align", "right");
           
            oCol8.innerHTML = "<button onclick='how("+idDbf+",1)' title='Edit' class='btntbl primary'>Edit</button>";
            oCol9.innerHTML = "<button onclick='how("+idDbf+",2)' title='Delete' class='btntbl danger'>Delete</button>";

            location.hash = "#"+cIdRow;
           
            closemodal();
       
        }
       
        function updaterowhtmltable(idDbf,cNm,cLs,cSt,cCt,cEd,cSal){
            var id_row = "row_"+idDbf;
            var therow = document.getElementById(id_row);
            var elementsrow = therow.getElementsByTagName("td");

            elementsrow[1].innerHTML = cNm;
            elementsrow[2].innerHTML = cLs;
            elementsrow[3].innerHTML = cSt;
            elementsrow[4].innerHTML = cCt;
            elementsrow[5].innerHTML = cEd;
            elementsrow[6].innerHTML = cSal;
        }
       
       

    ENDTEXT

Return cInyec



 
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 66 guests