lesson 8
This commit is contained in:
parent
23225bb54b
commit
c6d68334be
@ -3,8 +3,42 @@ services:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
# files are put in here
|
||||
volumes:
|
||||
- .:/usr/src/app
|
||||
- ./node_modules:/usr/src/app/node_modules
|
||||
command: ["yarn", "dev"]
|
||||
# Database
|
||||
|
||||
# Database: how we want to create the database
|
||||
db:
|
||||
# Image of postgres in 13th version
|
||||
image: postgres:13
|
||||
environment: #secret
|
||||
POSTGRES_USER: ${DB_USER}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_DB: ${DB_NAME}
|
||||
ports: #internally the port is 5432, but we want to use 5432 locally
|
||||
- "5432:5432"
|
||||
# create a file to store stuff, store inside "data" folder
|
||||
volumes:
|
||||
- ./data:/var/lib/postgresql/data
|
||||
|
||||
# PGAdmin: visualize postgres database
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
|
||||
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
|
||||
ports:
|
||||
# our local port is 3001, but the container port is 80
|
||||
- "3001:80"
|
||||
# creating a folder called pgadmin to store the pgadmin files
|
||||
volumes:
|
||||
- ./pgadmin:/root/.pgadmin
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
# tell docker to create something called data (refer to above) and store all the postgres data in it
|
||||
volumes:
|
||||
data:
|
||||
pgadmin:
|
||||
|
||||
@ -11,10 +11,12 @@
|
||||
"dependencies": {
|
||||
"dotenv": "^16.4.7",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^4.21.2"
|
||||
"express": "^4.21.2",
|
||||
"pg": "^8.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/pg": "^8.11.10",
|
||||
"concurrently": "^9.1.1",
|
||||
"nodemon": "^3.1.9",
|
||||
"sass": "^1.83.0",
|
||||
|
||||
178
nodeJS/Learning/06/pnpm-lock.yaml
generated
178
nodeJS/Learning/06/pnpm-lock.yaml
generated
@ -17,10 +17,16 @@ importers:
|
||||
express:
|
||||
specifier: ^4.21.2
|
||||
version: 4.21.2
|
||||
pg:
|
||||
specifier: ^8.13.1
|
||||
version: 8.13.1
|
||||
devDependencies:
|
||||
'@types/express':
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
'@types/pg':
|
||||
specifier: ^8.11.10
|
||||
version: 8.11.10
|
||||
concurrently:
|
||||
specifier: ^9.1.1
|
||||
version: 9.1.1
|
||||
@ -168,6 +174,9 @@ packages:
|
||||
'@types/node@22.10.2':
|
||||
resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
|
||||
|
||||
'@types/pg@8.11.10':
|
||||
resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==}
|
||||
|
||||
'@types/qs@6.9.17':
|
||||
resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==}
|
||||
|
||||
@ -560,6 +569,9 @@ packages:
|
||||
resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
obuf@1.1.2:
|
||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||
|
||||
on-finished@2.4.1:
|
||||
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -571,10 +583,87 @@ packages:
|
||||
path-to-regexp@0.1.12:
|
||||
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
|
||||
|
||||
pg-cloudflare@1.1.1:
|
||||
resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
|
||||
|
||||
pg-connection-string@2.7.0:
|
||||
resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==}
|
||||
|
||||
pg-int8@1.0.1:
|
||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
|
||||
pg-numeric@1.0.2:
|
||||
resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
pg-pool@3.7.0:
|
||||
resolution: {integrity: sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==}
|
||||
peerDependencies:
|
||||
pg: '>=8.0'
|
||||
|
||||
pg-protocol@1.7.0:
|
||||
resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==}
|
||||
|
||||
pg-types@2.2.0:
|
||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
pg-types@4.0.2:
|
||||
resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
pg@8.13.1:
|
||||
resolution: {integrity: sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
peerDependencies:
|
||||
pg-native: '>=3.0.1'
|
||||
peerDependenciesMeta:
|
||||
pg-native:
|
||||
optional: true
|
||||
|
||||
pgpass@1.0.5:
|
||||
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
|
||||
|
||||
picomatch@2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
postgres-array@2.0.0:
|
||||
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postgres-array@3.0.2:
|
||||
resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-bytea@1.0.0:
|
||||
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-bytea@3.0.0:
|
||||
resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
postgres-date@1.0.7:
|
||||
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-date@2.1.0:
|
||||
resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-interval@3.0.0:
|
||||
resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-range@1.1.4:
|
||||
resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
|
||||
|
||||
proxy-addr@2.0.7:
|
||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -664,6 +753,10 @@ packages:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
split2@4.2.0:
|
||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||
engines: {node: '>= 10.x'}
|
||||
|
||||
statuses@2.0.1:
|
||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -755,6 +848,10 @@ packages:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -886,6 +983,12 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
|
||||
'@types/pg@8.11.10':
|
||||
dependencies:
|
||||
'@types/node': 22.10.2
|
||||
pg-protocol: 1.7.0
|
||||
pg-types: 4.0.2
|
||||
|
||||
'@types/qs@6.9.17': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
@ -1282,6 +1385,8 @@ snapshots:
|
||||
|
||||
object-inspect@1.13.3: {}
|
||||
|
||||
obuf@1.1.2: {}
|
||||
|
||||
on-finished@2.4.1:
|
||||
dependencies:
|
||||
ee-first: 1.1.1
|
||||
@ -1290,8 +1395,77 @@ snapshots:
|
||||
|
||||
path-to-regexp@0.1.12: {}
|
||||
|
||||
pg-cloudflare@1.1.1:
|
||||
optional: true
|
||||
|
||||
pg-connection-string@2.7.0: {}
|
||||
|
||||
pg-int8@1.0.1: {}
|
||||
|
||||
pg-numeric@1.0.2: {}
|
||||
|
||||
pg-pool@3.7.0(pg@8.13.1):
|
||||
dependencies:
|
||||
pg: 8.13.1
|
||||
|
||||
pg-protocol@1.7.0: {}
|
||||
|
||||
pg-types@2.2.0:
|
||||
dependencies:
|
||||
pg-int8: 1.0.1
|
||||
postgres-array: 2.0.0
|
||||
postgres-bytea: 1.0.0
|
||||
postgres-date: 1.0.7
|
||||
postgres-interval: 1.2.0
|
||||
|
||||
pg-types@4.0.2:
|
||||
dependencies:
|
||||
pg-int8: 1.0.1
|
||||
pg-numeric: 1.0.2
|
||||
postgres-array: 3.0.2
|
||||
postgres-bytea: 3.0.0
|
||||
postgres-date: 2.1.0
|
||||
postgres-interval: 3.0.0
|
||||
postgres-range: 1.1.4
|
||||
|
||||
pg@8.13.1:
|
||||
dependencies:
|
||||
pg-connection-string: 2.7.0
|
||||
pg-pool: 3.7.0(pg@8.13.1)
|
||||
pg-protocol: 1.7.0
|
||||
pg-types: 2.2.0
|
||||
pgpass: 1.0.5
|
||||
optionalDependencies:
|
||||
pg-cloudflare: 1.1.1
|
||||
|
||||
pgpass@1.0.5:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
|
||||
postgres-array@2.0.0: {}
|
||||
|
||||
postgres-array@3.0.2: {}
|
||||
|
||||
postgres-bytea@1.0.0: {}
|
||||
|
||||
postgres-bytea@3.0.0:
|
||||
dependencies:
|
||||
obuf: 1.1.2
|
||||
|
||||
postgres-date@1.0.7: {}
|
||||
|
||||
postgres-date@2.1.0: {}
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
dependencies:
|
||||
xtend: 4.0.2
|
||||
|
||||
postgres-interval@3.0.0: {}
|
||||
|
||||
postgres-range@1.1.4: {}
|
||||
|
||||
proxy-addr@2.0.7:
|
||||
dependencies:
|
||||
forwarded: 0.2.0
|
||||
@ -1403,6 +1577,8 @@ snapshots:
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
split2@4.2.0: {}
|
||||
|
||||
statuses@2.0.1: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
@ -1482,6 +1658,8 @@ snapshots:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
0
nodeJS/Learning/06/public/js/index.js
Normal file
0
nodeJS/Learning/06/public/js/index.js
Normal file
14
nodeJS/Learning/06/src/database/pg.ts
Normal file
14
nodeJS/Learning/06/src/database/pg.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Pool } from "pg";
|
||||
|
||||
console.log(process.env.DB_HOST);
|
||||
|
||||
const pg = new Pool({
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME,
|
||||
port: parseInt(process.env.DB_PORT as string),
|
||||
});
|
||||
|
||||
// export pg to outside to use
|
||||
export default pg;
|
||||
@ -1,10 +1,17 @@
|
||||
import express, { Application, Request, Response } from "express";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config({ path: "$(__dirname)/../env" });
|
||||
dotenv.config({ path: ".env" });
|
||||
|
||||
import express, { Application, Request, Response } from "express";
|
||||
import pg from "./database/pg";
|
||||
import { PoolClient } from "pg";
|
||||
|
||||
const app: Application = express();
|
||||
const port: number = parseInt(process.env.PORT as string) || 3000;
|
||||
|
||||
//Middleware
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
//Setting up for EJS
|
||||
app.set("views", `./src/views`);
|
||||
app.set("view engine", "ejs");
|
||||
@ -14,14 +21,82 @@ app.use(express.static(`${__dirname}/../public`));
|
||||
|
||||
//check and send index ejs
|
||||
app.get("/", (_req: Request, res: Response): void => {
|
||||
const date = new Date().toLocaleString();
|
||||
let todos: string[] = [];
|
||||
|
||||
res.render("index", {
|
||||
time: date,
|
||||
//Query postgres database to get all todos (async await)
|
||||
pg.query("SELECT * FROM todos", async (err: Error, result: any) => {
|
||||
if (err) {
|
||||
console.log("Error querying todos", err);
|
||||
return;
|
||||
}
|
||||
|
||||
todos = result.rows.map((row: any) => row.todo);
|
||||
}
|
||||
|
||||
res.render("index",{
|
||||
todos,
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/form-action", (req: Request, res: Response): void => {
|
||||
const todo: string = req.body.todo;
|
||||
|
||||
//query postgres to insert todo, $1 is a placeholder for the value of todo
|
||||
pg.query("INSERT INTO todos (todo) VALUES ($1)", [todo], (err: Error) => {
|
||||
if (err) {
|
||||
console.log("Error inserting todo", err);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Inserted ${todo} successfully`);
|
||||
});
|
||||
|
||||
res.redirect("/");
|
||||
});
|
||||
|
||||
// app.delete("/delete-todo/:todo", (req: Request, res: Response): void => {
|
||||
// //delete todo from postgres
|
||||
// });
|
||||
|
||||
app.listen(port, (): void => {
|
||||
console.log(`Server is running on port ${port}`);
|
||||
});
|
||||
|
||||
//Connect to postgres, postgres initialization
|
||||
pg.connect(
|
||||
(err: Error | undefined, client: PoolClient | undefined, done): void => {
|
||||
if (err) {
|
||||
console.log("Error connecting to pg", err);
|
||||
return;
|
||||
}
|
||||
if (!client) {
|
||||
console.log("No client found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to Query (asking the database, to check it is connected), it might take us a while and we wont be able to run the rest of the program
|
||||
// Async this
|
||||
client.query("SELECT NOW()", async (err: Error, _result: any) => {
|
||||
if (err) {
|
||||
console.log("Error querying pg", err);
|
||||
return;
|
||||
}
|
||||
|
||||
//Create the table if no error (await)
|
||||
//Query statement, instruction "CREATE TABLE IF NOT EXISTS todos", there is a whole table, https://www.w3schools.com/sql/default.asp
|
||||
//VACHAR is a string, 255 is the max length of the string
|
||||
await client.query(
|
||||
`CREATE TABLE IF NOT EXISTS todos (
|
||||
todo VARCHAR(255) NOT NULL
|
||||
)`,
|
||||
(err: Error) => {
|
||||
console.log("Error creating table", err);
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
console.log("Connected to postgres successfully");
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@ -33,7 +33,13 @@
|
||||
<p><i>Add something cute to my to-do list!</i></p>
|
||||
<form action="/form-action" method="post">
|
||||
<label for="to-do"></label>
|
||||
<input name="todo" type="text" placeholder="Enter a to-do" required class="todo-input" />
|
||||
<input
|
||||
name="todo"
|
||||
type="text"
|
||||
placeholder="Enter a to-do"
|
||||
required
|
||||
class="todo-input"
|
||||
/>
|
||||
<button type="submit" class="form-submit">Add</button>
|
||||
</form>
|
||||
|
||||
@ -44,6 +50,9 @@
|
||||
<div class="inner-todo">
|
||||
<h1>To do list</h1>
|
||||
<ol>
|
||||
<!-- rendering the todos -->
|
||||
<!-- <% todos.forEach(todo => { %> <li><%= todo %></li> <% }); %> -->
|
||||
<!-- click button, go to app.delete, then delete something -->
|
||||
<!-- <li>Learn from Ronald</li>
|
||||
<li>Watch movies</li>
|
||||
<li>Sleep</li> -->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user