Wednesday, July 31, 2024

ag-grid note

 floating filter

https://www.ag-grid.com/example-assets/olympic-winners.json


useEffect(() => {

fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')

.then(result => result.json())

.then(rowData => setRowData(rowData))

},[]

);

Thursday, July 25, 2024

nodejs, express call MS SQL Server Procedure with parameters

  • npm install express tedious
  • npm install cors
  • nodejs database.js


     const express = require('express');

    const { Connection, Request, TYPES } = require('tedious');

    const cors = require('cors');

    const app = express();

    // Enable CORS for all routes 

    app.use(cors());

    const port = 3000;


    const config = {

      server: '192.168.2.70', // Update with your server details

      authentication: {

        type: 'default',

        options: {

          userName: '***', // Update with your username

          password: 'Le*****', // Update with your password

        },

      },

      options: {

        encrypt: false, // If you're on Microsoft Azure

        database: 'sample_data', // Update with your database name

      },

    };


    app.get('/api/olympic-winners', (req, res) => {

      const country = req.query.country;

      const year = parseInt(req.query.year, 10);


      console.log("Country is " + country)

      console.log("year is " + year)

      if (!country || isNaN(year)) {

        return res.status(400).json({ error: 'Country and year parameters are required' });

      }

      const connection = new Connection(config);


      connection.on('connect', (err) => {

        if (!err) {

          console.log('Connected');

          executeStatement(connection,country, year, res);

        } else {

          console.error('Error connecting:', err.message);

          res.status(500).json({ error: err.message });

        }

      });


      connection.connect();

    });


    function executeStatement(connection, country, year, res) {

      const request = new Request(`GetTopOlympicWinners`, (err) => {

        if (err) {

          console.error(err);

          res.status(500).json({ error: err.message });

        }

      });


      request.addParameter('Country', TYPES.NVarChar, country);

      request.addParameter('Year', TYPES.Int, year);

      const results = [];


      request.on('row', (columns) => {

        const result = {};

        columns.forEach((column) => {

          result[column.metadata.colName] = column.value;

        });

        results.push(result);

      });


      request.on('requestCompleted', () => {

        console.log(`${results.length} rows returned. requestCompleted`);

        res.json(results);

        connection.close();

      });


      connection.callProcedure(request);

    }


    app.listen(port, () => {

      console.log(`API server listening at http://localhost:${port}`);

    });


    Tuesday, July 16, 2024

    node js books library

    https://www.torontopubliclibrary.ca/detail.jsp?Entt=RDM4361223&R=4361223

    https://www.torontopubliclibrary.ca/detail.jsp?Entt=RDM4395894&R=4395894

    https://www.torontopubliclibrary.ca/detail.jsp?Entt=RDM4497634&R=4497634

    Friday, July 12, 2024

    ag grid react

     

    1. Install nodist from nodists/nodist: Natural node.js and npm version manager for windows. (github.com)

    after the installation, the node and npm are available:

    C:\Users\peterpeng>node -v

    v20.10.0


    C:\Users\peterpeng>npm -v

    10.2.3

    2. Install yarn

    npm install --global yarn

    C:\Users\peterpeng>yarn --version

    1.22.22

    3.

    git clone https://github.com/ag-grid/ag-grid-server-side-nodejs-example.git
    
    cd ag-grid-server-side-nodejs-example
    
    insert the data into MS SQL Server table (8001 rows)
      Not necessary, can get the data directly from https://www.ag-grid.com/example-assets/olympic-winners.json 


    npx create-react-app olympic-winners cd olympic-winners npm install ag-grid-react ag-grid-community axios

    npm start


    App.js
    import React, { useState, useEffect, useRef } from 'react'; import axios from 'axios'; import { AgGridReact } from 'ag-grid-react'; import 'ag-grid-community/styles/ag-grid.css'; import 'ag-grid-community/styles/ag-theme-alpine.css'; import './OlympicWinners.css'; const OlympicWinners = () => { const [rowData, setRowData] = useState([]); const [country, setCountry] = useState('United States'); const [year, setYear] = useState(2008); const gridRef = useRef(); const fetchWinners = async () => { try { const response = await axios.get('https://www.ag-grid.com/example-assets/olympic-winners.json', { params: { country, year, }, }); setRowData(response.data); } catch (error) { console.error('Error fetching data', error); } }; useEffect(() => { fetchWinners(); }, []); const handleUpdate = async (updatedData) => { try { await axios.put('http://localhost:3000/api/olympic-winners', updatedData); fetchWinners(); } catch (error) { console.error('Error updating data', error); } }; const handleDelete = async (id) => { try { await axios.delete(`http://localhost:3000/api/olympic-winners/${id}`); fetchWinners(); } catch (error) { console.error('Error deleting data', error); } }; const onCellEditingStopped = async (event) => { const updatedData = event.data; await handleUpdate(updatedData); }; const DeleteButton = (props) => { const onClick = () => { props.onClick(props.data.id); }; return <button onClick={onClick}>Delete</button>; }; const columnDefs = [ { field: 'athlete', editable: true }, { field: 'age', editable: true }, { field: 'country', editable: true }, { field: 'country_group', editable: true }, { field: 'year', editable: true }, { field: 'date', editable: true }, { field: 'sport', editable: true }, { field: 'gold', editable: true }, { field: 'silver', editable: true }, { field: 'bronze', editable: true }, { field: 'total', editable: true }, { headerName: 'Actions', cellRenderer: DeleteButton, cellRendererParams: { onClick: handleDelete, }, }, ]; return ( <div className="app-container"> <nav className="left-nav"> <ul> <li><a href="#">Dashboard</a></li> <li><a href="#">Olympic Winners</a></li> <li><a href="#">Statistics</a></li> <li><a href="#">Settings</a></li> </ul> </nav> <div className="main-content"> <header className="top-nav"> <h1>Olympic Data Management</h1> <div> <span>User: Admin</span> <button style={{marginLeft: '10px'}}>Logout</button> </div> </header> <main className="content"> <div className="container"> <h2 className="header">Olympic Winners</h2> <div> <div className="form-group"> <label> Country: <input type="text" value={country} onChange={(e) => setCountry(e.target.value)} /> </label> </div> <div className="form-group"> <label> Year: <input type="number" value={year} onChange={(e) => setYear(Number(e.target.value))} /> </label> </div> <button onClick={fetchWinners}>Fetch Winners</button> </div> <div className="ag-theme-alpine" style={{marginTop: '20px'}}> <AgGridReact ref={gridRef} rowData={rowData} columnDefs={columnDefs} defaultColDef={{ sortable: true, filter: true }} rowSelection="single" onCellEditingStopped={onCellEditingStopped} /> </div> </div> </main> </div> </div> ); }; export default OlympicWinners;



    OlympicWinners.css
    /* OlympicWinners.css */ body, html { margin: 0; padding: 0; height: 100%; font-family: Arial, sans-serif; } .app-container { display: flex; height: 100vh; } .left-nav { width: 200px; background-color: #2c3e50; color: white; padding: 20px; } .left-nav ul { list-style-type: none; padding: 0; } .left-nav li { margin-bottom: 10px; } .left-nav a { color: white; text-decoration: none; } .main-content { flex-grow: 1; display: flex; flex-direction: column; } .top-nav { background-color: #34495e; color: white; padding: 10px 20px; display: flex; justify-content: space-between; align-items: center; } .content { padding: 20px; overflow-y: auto; } .container { background-color: #f9f9f9; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); padding: 20px; } .header { font-size: 24px; margin-bottom: 20px; text-align: center; } .form-group { margin-bottom: 15px; } label { font-weight: bold; margin-right: 10px; } input[type="text"], input[type="number"] { padding: 8px; border: 1px solid #ccc; border-radius: 4px; width: 200px; } button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #0056b3; } .ag-theme-alpine { height: 500px; width: 100%; }




    The below doesn't show any grid:
    import React, { useState, useEffect, useRef } from 'react';
    import axios from 'axios';
    import { AgGridReact } from 'ag-grid-react';
    import 'ag-grid-community/styles/ag-grid.css';
    import 'ag-grid-community/styles/ag-theme-alpine.css';
    import './CRInsertLogs.css';

    const CRInsertLogs = () => {
      const [rowData, setRowData] = useState([]);
      const gridRef = useRef();

      const fetchCRInsertLogs = async () => {
        try {
          const response = await axios.get('http://localhost:3000/api/importLog');
          setRowData(response.data);
        } catch (error) {
          console.error('Error fetching data', error);
        }
      };

      useEffect(() => {
        fetchCRInsertLogs();
      }, []);

      const handleUpdate = async (updatedData) => {
        try {
          await axios.put('http://localhost:3000/api/importLog', updatedData);
          fetchCRInsertLogs();
        } catch (error) {
          console.error('Error updating data', error);
        }
      };

      const handleDelete = async (id) => {
        try {
          await axios.delete(`http://localhost:3000/api/importLog/${id}`);
          fetchCRInsertLogs();
        } catch (error) {
          console.error('Error deleting data', error);
        }
      };

      const onCellEditingStopped = async (event) => {
        const updatedData = event.data;
        await handleUpdate(updatedData);
      };

      const DeleteButton = (props) => {
        const onClick = () => {
          props.onClick(props.data.id);
        };

        return <button onClick={onClick}>Delete</button>;
      };

      const colDefs = [
        { field: 'Id', editable: false },
        { field: 'FundIssuerIdentifier', editable: false },
        { field: 'CreateEmailTS', editable: false },
        { field: 'EMailSubject', editable: false },
        { field: 'FileName', editable: false },
        { field: 'Directory', editable: false },
        { field: 'Status', editable: true },
        { field: 'ProcessResult', editable: true },
        { field: 'InseredBy', editable: false },
        { field: 'InsertedDate', editable: false },
        { field: 'NumberOfFiles', editable: false },
        { field: 'Description', editable: false },
        {
          headerName: 'Actions',
          cellRenderer: DeleteButton,
          cellRendererParams: {
            onClick: handleDelete,
          },
        },
      ];

      return (
        <div
        className="ag-theme-quartz" // applying the Data Grid theme
        style={{ height: 500 }} // the Data Grid will fill the size of the parent container
       >
         <AgGridReact
             rowData={rowData}
             columnDefs={colDefs}
         />
       </div>    
      );
    };

    export default CRInsertLogs;

    Tuesday, July 9, 2024

    Song of the open road 大路之歌

    Afoot and light-hearted I take to the open road,
    Healthy, free, the world before me,
    The long brown path before me leading wherever I choose.

    Henceforth I ask not good-fortune, I myself am good-fortune,
    Henceforth I whimper no more, postpone no more, need nothing,
    Done with indoor complaints, libraries, querulous criticisms,
    Strong and content I travel the open road.

    The earth, that is sufficient,
    I do not want the constellations any nearer,
    I know they are very well where they are,

    I know they suffice for those who belong to them. 

    美国诗人沃尔特·惠特曼的《大路之歌》:“我轻松愉快地走上大路,我健康自由,世界在我面前,长长的褐色大路在我面前,指向我想去的任何地方。从此我不再希求幸福,我自己便是幸福。凡是我遇见的我都喜欢,一切都被接受。从此,我不受限制,我使我自己自由,我走到我所愿去的任何地方。我完全而绝对的主持着我。”

    我轻松愉快地走上大路,
    我健康,我自由,整个世界展开在我的面前,
    漫长的黄土道路可引到我想去的地方。
    
    从此我不再希求幸福,我自己便是幸福,
    从此我不再啜泣,不再踌躇,也不要求什么,
    消除了家中的嗔怨,放下了书本,停止了苛酷的非难。
    我强壮而满足地走在大路上。
    
    地球,有了它就够了,
    我不要求星星们更和我接近,
    我知道它们所在的地位很适宜。
    我知道它们能够满足属于它们的一切。

    https://www.poetryfoundation.org/poems/48859/song-of-the-open-road

    https://m.sohu.com/a/790003113_121894854

    https://www.sohu.com/a/634663575_121124776

    玫瑰的故事

    http://www.shigeku.com/shiku/ws/wg/whitman/21.htm

    https://www.iyf.tv/play/zjJaXODma3N?id=BhmjsGRKzn8

    43:21