Youth
Monday, September 2, 2024
Friday, August 23, 2024
React note
1. Install Node.js so that you can run npm command
2. npm install -g create-react-app
Add the path to env: C:\Users\theuser\AppData\Roaming\npm
3. Run
create-react-app reactapp
then cd reactapp, npm start to start the react app
4. The virtual DOM is a lightweight copy of DOM, with the key difference that while the real DOM is made up of Node objects,
the virtual DOM is made up of plain JS objects that act as descriptions.
5. Reconciliation compares the virtual tree representing the current state of the user interface with a previous version to
determine which parts of the user interface need to be updated.
6. Only reactive variables can be modified in the display, once the component is rendered. React uses a concept called "state".
7. [...Array(11).keys()].slice(1)
8. useEffect( function(){ setValue(1);,[] }; ) //conditions = [] means that setValue(1) is executed only on the initial display.
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 corsnodejs 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
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.gitcd ag-grid-server-side-nodejs-exampleinsert 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.jsonnpx create-react-app olympic-winners cd olympic-winners npm install ag-grid-react ag-grid-community axiosnpm startApp.jsimport 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 (<divclassName="ag-theme-quartz" // applying the Data Grid themestyle={{ height: 500 }} // the Data Grid will fill the size of the parent container><AgGridReactrowData={rowData}columnDefs={colDefs}/></div>);};export default CRInsertLogs;
Tuesday, July 9, 2024
Song of the open road 大路之歌
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