diff --git a/.env b/.env index 4be97b4..1b2c45b 100644 --- a/.env +++ b/.env @@ -2,5 +2,5 @@ DEFAULT_PORT=":8000" ASSETS_PATH="dist/assets/" HTML_PATH="dist/index.html" DB_PATH="api/database/db.sql" -DB_INIT="api/database/TableInit.txt" +DB_INIT="api/database/db-init" PATH_TO_VITE="%appdata%/npm/vite.cmd" \ No newline at end of file diff --git a/.eslintignore b/.eslintignore index 9e0b02f..953d7d0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ -dist/assets/index.js \ No newline at end of file +dist/assets/**/* +.vscode/setting.json \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 2f2f661..f65e0ba 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,13 +3,13 @@ "browser": true, "es2021": true }, - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:solid/recommended"], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": ["@typescript-eslint", "jsdoc"], + "plugins": ["jsdoc", "solid"], "rules": { "@typescript-eslint/no-explicit-any": "off", "indent": ["off", "tab"], @@ -22,6 +22,7 @@ "id-length": ["error", {"min": 2, "exceptions": ["_"], "properties": "never"}], "no-underscore-dangle":"error", + "solid/no-array-handlers": "error", "eslint-plugin-import/no-unresolved": "off", "@typescript-eslint/no-namespace": "off", "jsdoc/check-access": 1, // Recommended diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6c8788e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "svg.preview.background": "editor" +} \ No newline at end of file diff --git a/api/database/TableInit.txt b/api/database/TableInit.txt deleted file mode 100644 index aed0c7a..0000000 --- a/api/database/TableInit.txt +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE Images ( - url TEXT PRIMARY KEY, - content BLOB, - mimetype TEXT -); - -CREATE TABLE Posts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - PostedBy INTEGER, - content TEXT, - timeCreated DATETIME, - ParentId INTEGER, - images TEXT -); - -CREATE TABLE Users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT, - password BLOB, - handle TEXT UNIQUE, - email TEXT NULL, - auth TEXT NOT NULL, - timeCreated DATETIME, - followers INTEGER DEFAULT 0, - followersCount INTEGER DEFAULT 0, - bio TEXT DEFAULT "", - Posts INTEGER DEFAULT 0, - Profile TEXT DEFAULT "", - Banner TEXT DEFAULT "" -); \ No newline at end of file diff --git a/api/database/db-init b/api/database/db-init new file mode 100644 index 0000000..945ed96 --- /dev/null +++ b/api/database/db-init @@ -0,0 +1,41 @@ +CREATE TABLE Images ( + URL TEXT PRIMARY KEY, + content BLOB, + mimetype TEXT +); + +CREATE TABLE Posts ( + ID INTEGER PRIMARY KEY AUTOINCREMENT, + PostedBy INTEGER, + content TEXT, + + likes INTEGER DEFAULT 0, + whoLiked TEXT NOT NULL DEFAULT "", + + dislikes INTEGER DEFAULT 0, + whoDisliked TEXT NOT NULL DEFAULT "", + + timeCreated DATETIME, + parentID INTEGER, + images TEXT +); + +CREATE TABLE Users ( + ID INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT, + password BLOB, + handle TEXT UNIQUE, + email TEXT NULL, + bio TEXT DEFAULT "", + + auth TEXT NOT NULL, + timeCreated DATETIME, + + Followers NUMBER DEFAULT 0, + whoFollowed TEXT DEFAULT "", + + posts INTEGER DEFAULT 0, + + profile TEXT DEFAULT "", + banner TEXT DEFAULT "" +); diff --git a/api/images.go b/api/images.go index 37599bf..41883a2 100644 --- a/api/images.go +++ b/api/images.go @@ -14,8 +14,8 @@ import ( // ImageData contains the URL, content, content-type of an image type ImageData struct { - URL string `db:"url"` - Content []byte `db:"Content"` + URL string `db:"URL"` + Content []byte `db:"content"` ContentType string `db:"mimetype"` } diff --git a/api/post.go b/api/post.go index 3d2cd73..c2fe4f0 100644 --- a/api/post.go +++ b/api/post.go @@ -26,13 +26,16 @@ type AddPostRequest struct { // PostDB is a struct replicata of the `Posts` table type PostDB struct { - ID int `json:"ID" db:"id"` - PostedBy int `json:"postedBy" db:"PostedBy"` + ID int `json:"ID" db:"ID"` + PostedBy int `json:"postedBy" db:"postedBy"` Content string `json:"content" db:"content"` TimeCreated time.Time `json:"timeCreated" db:"timeCreated"` - ParentID int `json:"parentID" db:"ParentId"` - // Images list format seperated with commas: url (alt) - Images string `json:"images" db:"images"` + ParentID int `json:"parentID" db:"parentID"` + WhoLiked string `json:"whoLiked" db:"whoLiked"` + WhoDisliked string `json:"whoDisliked" db:"whoDisliked"` + Likes int `json:"likes" db:"likes"` + Dislikes int `json:"dislikes" db:"dislikes"` + Images string `json:"images" db:"images"` } // PostListBody is used by [coffeecoserver/api.server.PostFeedList] and only contains Amount int value. diff --git a/api/user.go b/api/user.go index d5bc204..081ec49 100644 --- a/api/user.go +++ b/api/user.go @@ -25,13 +25,14 @@ type LoginUser struct { // PublicUser is the root of most User structs contains non-personal information about the user type PublicUser struct { - ID int `json:"ID" db:"id"` - Username string `json:"username" db:"username"` // A non-unique name - Handle string `json:"handle" db:"handle"` // An unique handle - Bio string `json:"bio" db:"bio"` // The description (biography) - FollowersCount int `json:"followersCount" db:"followersCount"` // How many users following - Banner string `json:"Banner" db:"Banner"` // Url to the Banner - Profile string `json:"Profile" db:"Profile"` // Url to the Profile + ID int `json:"ID" db:"ID"` + Username string `json:"username" db:"username"` // A non-unique name + Handle string `json:"handle" db:"handle"` // An unique handle + Bio string `json:"bio" db:"bio"` // The description (biography) + Followers int `json:"followers" db:"followers"` + WhoFollowed string `json:"whoFollowed" db:"whoFollowed"` // How many users following + Banner string `json:"Banner" db:"banner"` // Url to the Banner + Profile string `json:"Profile" db:"profile"` // Url to the Profile } // SentUser contains all the regular information from [coffeecoserver/api.PublicUser] as well as: @@ -129,16 +130,7 @@ func (srv *Server) APIUserFromID(w http.ResponseWriter, r *http.Request) { return } - type UFIUser struct { - Username string `json:"username"` - Handle string `json:"handle"` - FollowersCount int `json:"followersCount"` - Banner string `json:"Banner"` - Profile string `json:"Profile"` - Bio string `json:"bio"` - } - - var u UFIUser + var u PublicUser if err := scan.Row(&u, rows); err != nil { utility.SendScanErr(w, err, nil) return diff --git a/meta/buildrelease.py b/meta/build-release.py similarity index 100% rename from meta/buildrelease.py rename to meta/build-release.py diff --git a/package-lock.json b/package-lock.json index 6eff485..5e2427a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,8 +27,9 @@ "@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/parser": "^6.20.0", "autoprefixer": "^10.4.17", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-plugin-jsdoc": "^48.2.6", + "eslint-plugin-solid": "^0.14.0", "postcss": "^8.4.33", "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.14", @@ -986,9 +987,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2315,16 +2316,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -2415,6 +2416,150 @@ "node": ">=10" } }, + "node_modules/eslint-plugin-solid": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-solid/-/eslint-plugin-solid-0.14.0.tgz", + "integrity": "sha512-EY0GJLOZdLynAyBM39WBLJH2bUftGI0KekyzpfxQEhCTuOhXkIRf648P97mQjME3TDaQQbY+ObVXeE2mjfs4FQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^7.6.0", + "estraverse": "^5.3.0", + "is-html": "^2.0.0", + "kebab-case": "^1.0.2", + "known-css-properties": "^0.30.0", + "style-to-object": "^1.0.6" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-solid/node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-solid/node_modules/@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-solid/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-solid/node_modules/@typescript-eslint/utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/eslint-plugin-solid/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-solid/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-plugin-solid/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -2921,6 +3066,18 @@ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -2976,6 +3133,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "dev": true + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3027,6 +3190,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-html": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-html/-/is-html-2.0.0.tgz", + "integrity": "sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==", + "dev": true, + "dependencies": { + "html-tags": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3163,6 +3338,12 @@ "node": ">=6" } }, + "node_modules/kebab-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz", + "integrity": "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==", + "dev": true + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3172,6 +3353,12 @@ "json-buffer": "3.0.1" } }, + "node_modules/known-css-properties": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", + "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "dev": true + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4253,6 +4440,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -4399,12 +4595,12 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -5351,9 +5547,9 @@ } }, "@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true }, "@humanwhocodes/config-array": { @@ -6319,16 +6515,16 @@ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -6503,6 +6699,91 @@ } } }, + "eslint-plugin-solid": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-solid/-/eslint-plugin-solid-0.14.0.tgz", + "integrity": "sha512-EY0GJLOZdLynAyBM39WBLJH2bUftGI0KekyzpfxQEhCTuOhXkIRf648P97mQjME3TDaQQbY+ObVXeE2mjfs4FQ==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^7.6.0", + "estraverse": "^5.3.0", + "is-html": "^2.0.0", + "kebab-case": "^1.0.2", + "known-css-properties": "^0.30.0", + "style-to-object": "^1.0.6" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" + } + }, + "@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, "eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -6753,6 +7034,12 @@ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" }, + "html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true + }, "ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -6796,6 +7083,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -6832,6 +7125,15 @@ "is-extglob": "^2.1.1" } }, + "is-html": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-html/-/is-html-2.0.0.tgz", + "integrity": "sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==", + "dev": true, + "requires": { + "html-tags": "^3.0.0" + } + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -6924,6 +7226,12 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, + "kebab-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz", + "integrity": "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==", + "dev": true + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6933,6 +7241,12 @@ "json-buffer": "3.0.1" } }, + "known-css-properties": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", + "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -7604,6 +7918,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dev": true, + "requires": { + "inline-style-parser": "0.2.3" + } + }, "sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -7717,9 +8040,9 @@ } }, "ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index 5607e7a..e789b68 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,9 @@ "@typescript-eslint/eslint-plugin": "^6.20.0", "@typescript-eslint/parser": "^6.20.0", "autoprefixer": "^10.4.17", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-plugin-jsdoc": "^48.2.6", + "eslint-plugin-solid": "^0.14.0", "postcss": "^8.4.33", "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.14", diff --git a/src/assets/DefaultProfile.png b/src/assets/default-profile.png similarity index 100% rename from src/assets/DefaultProfile.png rename to src/assets/default-profile.png diff --git a/src/assets/DefaultLogo.xcf b/src/assets/default-profile.xcf similarity index 100% rename from src/assets/DefaultLogo.xcf rename to src/assets/default-profile.xcf diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico index d09dc7f..00fba55 100644 Binary files a/src/assets/favicon.ico and b/src/assets/favicon.ico differ diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..5a12a4b --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/src/assets/logos/logo128.png b/src/assets/logos/logo128.png deleted file mode 100644 index 6f2aa9c..0000000 Binary files a/src/assets/logos/logo128.png and /dev/null differ diff --git a/src/assets/logos/logo256.png b/src/assets/logos/logo256.png deleted file mode 100644 index 4a2d60d..0000000 Binary files a/src/assets/logos/logo256.png and /dev/null differ diff --git a/src/assets/logos/logo32.png b/src/assets/logos/logo32.png deleted file mode 100644 index 2f3c4c4..0000000 Binary files a/src/assets/logos/logo32.png and /dev/null differ diff --git a/src/assets/logos/logo512.png b/src/assets/logos/logo512.png deleted file mode 100644 index cdae3a5..0000000 Binary files a/src/assets/logos/logo512.png and /dev/null differ diff --git a/src/assets/logos/logo64.png b/src/assets/logos/logo64.png deleted file mode 100644 index f775679..0000000 Binary files a/src/assets/logos/logo64.png and /dev/null differ diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 236646c..4de4981 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,8 +1,8 @@ import { Component, JSX, Show, Setter, createSignal } from 'solid-js'; import { OcPlus2, OcBell2, OcThreebars2, OcSearch2 } from 'solid-icons/oc'; import { A } from '@solidjs/router'; -import Logo64 from '../assets/logos/logo64.png'; -import { useUser } from '../contexts/usercontext'; +import Logo from '../assets/logo.svg'; +import { useUser } from '../contexts/user-context'; import { isLoggedIn } from '../requests/user'; import { ChildrenProps } from '../common'; import Hamburger from './hamburger'; @@ -27,22 +27,27 @@ const HeaderButton: Component = (props) => { ); - return props.url ? ( - - {Content} - - ) : ( - + } > - {Content} - + + {Content} + + ); }; @@ -59,15 +64,16 @@ const Left: Component<{ setHamburger: Setter }> = (props) => { - + CoffeeCo Logo -

+

CoffeeCo

@@ -75,17 +81,14 @@ const Left: Component<{ setHamburger: Setter }> = (props) => { ); }; -const rightNotLoggedIn: Component = () => { +const RightNotLoggedIn: Component = () => { return ( <> - + Login or - + Signup @@ -99,28 +102,34 @@ const Right: Component = () => { const [Connected, search] = useInput(searchTerm ?? ''); - const onSearchSubmit = () => { - console.log(`Searched for "${search()}"`); + const onSearchInput: JSX.EventHandlerUnion< + HTMLInputElement, + KeyboardEvent + > = (event) => { + if (event.key !== 'Enter') return; + + event.preventDefault(); + + console.log(`Searchbar: Searched for "${search()}"`); const SearchURL = new URL(location.href); + if (search()) SearchURL.searchParams.delete('search'); + SearchURL.searchParams.set('search', search()); location.href = SearchURL.toString(); }; - const onSearchInput: JSX.EventHandlerUnion< - HTMLInputElement, - KeyboardEvent - > = (event) => { - if (event.key === 'Enter') { - event.preventDefault(); - onSearchSubmit(); - } - }; - return (
- + + + + } + >
{ - + -
- +
+ { value={search()} onInput={Connected} onKeyPress={onSearchInput} - class='w-24 overflow-ellipsis rounded bg-button px-2 py-1 pl-8 text-white transition-[width] focus:w-48 focus:outline-none' + class='full-center h-8 w-24 gap-2 text-ellipsis rounded bg-header p-2 pl-8 text-title outline outline-1 outline-outline transition-[width] placeholder:text-subtitle focus:w-48' />
@@ -174,7 +183,7 @@ const Header: Component = () => { return ( <>
-
+
diff --git a/src/components/Post.tsx b/src/components/Post.tsx index 05c5c4c..aea93c7 100644 --- a/src/components/Post.tsx +++ b/src/components/Post.tsx @@ -1,7 +1,7 @@ import { OcComment2, OcThumbsdown2, OcThumbsup2 } from 'solid-icons/oc'; -import { deformatImages, ImageObj, ValidImages } from '../requests/images'; +import { deformatImages, ValidImages } from '../requests/images'; import { DefaultUser, getUserFromID, User } from '../requests/user'; -import { Show, Component, createResource, For } from 'solid-js'; +import { Show, Component, createResource, For, createMemo } from 'solid-js'; import ProfileIcon from '../assets/DefaultProfile.png'; import { Post } from '../requests/post'; import { ChildrenProps } from '../common'; @@ -31,12 +31,10 @@ export interface PostSkeletonProps extends ChildrenProps { * @param props children, title and subtitle */ export const PostSkeleton: Component = (props) => { - const linkLabel = `${props.title}'s page`; - return (
{props.url ? ( - + {`${props.title} = (props) => { - return props.isButton ? ( - - ) : ( - + {props.children} + {props.text} + + } > - {props.children} - {props.text} - + + ); }; @@ -133,15 +136,15 @@ export interface PostImageProps { * @param props an `images` string */ const PostImages: Component = (props) => { - const ref: ImageObj[] = deformatImages(props.images); + const images = createMemo(() => deformatImages(props.images)); return (
- + {(image) => ( {image.alt} @@ -163,11 +166,11 @@ export interface PostProps { * @param props A {@link Post} Object */ const PostUI: Component = (props) => { - const pst = props.post; + const pst = () => props.post; const [user] = createResource(async () => { try { - const usr = await getUserFromID(pst.postedBy); + const usr = await getUserFromID(pst().postedBy); return usr; } catch (error) { @@ -177,26 +180,26 @@ const PostUI: Component = (props) => { } }); - const date = new Date(pst.timeCreated).toDateString(); + const date = () => new Date(pst().timeCreated).toDateString(); return ( }>
- {pst.content} + {pst().content} - - + +
- + diff --git a/src/components/auth.tsx b/src/components/auth.tsx index 3e17f8c..c601236 100644 --- a/src/components/auth.tsx +++ b/src/components/auth.tsx @@ -1,14 +1,5 @@ -import { - Component, - createContext, - createSignal, - For, - JSX, - Setter, - Show, - Signal, - useContext, -} from 'solid-js'; +/* eslint-disable jsdoc/check-param-names */ +import { Component, createSignal, For, Setter, Show, Signal } from 'solid-js'; import { OcArrowleft2 } from 'solid-icons/oc'; import { Status, Statuses, BasicStatus } from '../common'; import { A } from '@solidjs/router'; @@ -19,7 +10,7 @@ export namespace FormInput { export type AuthSubmit = (Inputs: InputMap) => Promise; /** - * Used by {@link AuthOnClick} + * Used by {@link authOnClick} */ export interface AuthOnClickInputs { page: FormInput.AuthProps; @@ -96,23 +87,12 @@ export namespace FormInput { */ const InputMap: FormInput.InputMap = new Map(); -/** - * Happens the input has a keyup event, then updates the signal and adds from {@link InputMap} - * @param key The name of {@link InputUI Input} - * @param Signal Contains getter (0) and setter (1) - * @returns An event connecter - */ -function onInput( - key: string, - Signal: Signal, -): JSX.EventHandlerUnion { - return (event) => { - const Target: HTMLInputElement = event.target as HTMLInputElement; - - Signal[1](Target.value); - InputMap.set(key, Signal[0]()); - }; -} +const onInput = (key: string, signal: Signal, event: KeyboardEvent) => { + const Target: HTMLInputElement = event.target as HTMLInputElement; + + signal[1](Target.value); + InputMap.set(key, signal[0]()); +}; /** * The InputComponent included in {@link Auth} @@ -124,7 +104,7 @@ const InputUI: Component = (props) => { return ( onInput(props.key, [input, setInput], event)} class='rounded border-2 border-outline bg-background p-2 text-text placeholder:text-subtitle focus:outline-accent' placeholder={ props.limit ? `${props.key} (${props.limit} limit)` : props.key @@ -136,79 +116,31 @@ const InputUI: Component = (props) => { ); }; +// eslint-disable-next-line jsdoc/require-param /** * When the submit button is clicked - * @param setStatus Sets the page's status + * @param 0 Sets the page's status + * @param 1 The auth page * @param event The event occured on Mouse Click */ -const AuthOnClick = async (setStatus: Setter, event: MouseEvent) => { +const authOnClick = async ( + [setStatus, page]: [Setter, FormInput.AuthProps], + event: MouseEvent, +) => { event.preventDefault(); - const page = usePage(); - const result = await page.submit(InputMap), resultStatus = new Status(result.msg, result.ok); setStatus(resultStatus); - console.log(result); + console.log('Auth: Result is', result); if (result.ok) { location.href = '/'; } }; -const AuthBottom: Component<{ setStatus: Setter }> = (props) => { - const page = usePage(); - - return ( -
- - - - - Back - -
- ); -}; - -const AuthTitle: Component = () => { - const page = usePage(); - return ( -
-

- {page.title} -

- {page.subtitle} -
- ); -}; - -const PageContext = createContext({ - title: '', - subtitle: '', - confirmText: '', - Inputs: [], - submit: (() => {}) as any, -}); - -/** - * Get the page context - */ -function usePage(): FormInput.AuthProps { - const page = useContext(PageContext); - if (!page) { - throw new Error('Cannot get page'); - } - return page; -} - /** * The Auth Page (could be Login / Signin) * @param props The page's propetries @@ -216,16 +148,21 @@ function usePage(): FormInput.AuthProps { const Auth: Component<{ page: FormInput.AuthProps }> = (props) => { const [status, setStatus] = createSignal(Statuses.DefaultStatus); + const page = () => props.page; + const statusColour = () => (status().ok ? 'text-accent' : 'text-warning'); return ( - + <> CoffeeCo - {props.page.title}
- +

+ {page().title} +

+ {page().subtitle} @@ -234,7 +171,7 @@ const Auth: Component<{ page: FormInput.AuthProps }> = (props) => {
- + {(input) => ( = (props) => {
- +
+ + + + + Back + +
-
+ ); }; diff --git a/src/components/comment.tsx b/src/components/comment.tsx index 820fdc2..88913ea 100644 --- a/src/components/comment.tsx +++ b/src/components/comment.tsx @@ -1,13 +1,13 @@ import { Component, createResource, Show } from 'solid-js'; import { DefaultUser, getUserFromID } from '../requests/user'; -import { PostProps } from './Post'; +import { PostProps } from './post'; const Comment: Component = (props) => { - const pst = props.post; + const pst = () => props.post; const [user] = createResource(async () => { try { - const user = await getUserFromID(pst.postedBy); + const user = await getUserFromID(pst().postedBy); return user; } catch { @@ -15,7 +15,7 @@ const Comment: Component = (props) => { } }); - const date = new Date(pst.timeCreated).toDateString(); + const date = () => new Date(pst().timeCreated).toDateString(); return ( @@ -31,9 +31,9 @@ const Comment: Component = (props) => {

@{user()!.handle}

- {date} + {date()}
-

{pst.content}

+

{pst().content}

); diff --git a/src/components/hamburger.tsx b/src/components/hamburger.tsx index c5d5e87..38fd607 100644 --- a/src/components/hamburger.tsx +++ b/src/components/hamburger.tsx @@ -1,6 +1,6 @@ import { Component, For, Show } from 'solid-js'; import { ChildrenProps } from '../common'; -import getLeftLink from '../sideurls'; +import getLeftLink from '../side-urls'; import { A } from '@solidjs/router'; interface HamburgerItemProps extends ChildrenProps { diff --git a/src/components/postlist.tsx b/src/components/post-list.tsx similarity index 71% rename from src/components/postlist.tsx rename to src/components/post-list.tsx index f7835c7..15bf139 100644 --- a/src/components/postlist.tsx +++ b/src/components/post-list.tsx @@ -3,16 +3,30 @@ import { Post } from '../requests/post'; import { createStore, SetStoreFunction } from 'solid-js/store'; import { createBottomListener } from '../hooks'; +const PlaceholderList: Component = () => { + const postClass: string = 'rounded bg-button/25'; + return ( +
+
+
+
+
+
+
+
+ ); +}; + /** * Appears when there is {@link PostList} has no posts */ const ListFallback: Component = () => { return (
-

404

-

- Not Found -

+ + + +
); }; @@ -44,6 +58,8 @@ export interface PostListState { * @param props The amount of the PostList */ const PostList: Component = (props) => { + const loadOffset = () => props.loadOffset; + const [state, setState] = createStore({ times: 0, loading: false, @@ -56,7 +72,7 @@ const PostList: Component = (props) => { onMount(HandlerWrapper); - createBottomListener(HandlerWrapper, props.loadOffset); + createBottomListener(HandlerWrapper, loadOffset()); return (
diff --git a/src/components/rich-text.tsx b/src/components/rich-text.tsx index ed30506..546ddb9 100644 --- a/src/components/rich-text.tsx +++ b/src/components/rich-text.tsx @@ -89,7 +89,8 @@ const RichText: Component = (props) => { loadEncodings(he.encode(props.children), getEncodings()), ); - return
; + // eslint-disable-next-line solid/no-innerhtml + return

; }; export default RichText; diff --git a/src/components/sides-compontents/island.tsx b/src/components/sides-compontents/island.tsx index 163333d..7bb7543 100644 --- a/src/components/sides-compontents/island.tsx +++ b/src/components/sides-compontents/island.tsx @@ -8,11 +8,11 @@ export interface IslandLinkProps extends ChildrenProps { } export const IslandLink: Component = (props) => { - const background: string = props.selected ? 'bg-slate-950/35' : ''; + const background = () => (props.selected ? 'bg-slate-950/35' : ''); return (

  • - + {props.children}
  • diff --git a/src/components/sides-compontents/popular.tsx b/src/components/sides-compontents/popular.tsx index 8b01784..179839d 100644 --- a/src/components/sides-compontents/popular.tsx +++ b/src/components/sides-compontents/popular.tsx @@ -1,4 +1,4 @@ -import { Component } from 'solid-js'; +import { Component, createEffect } from 'solid-js'; import { OcHash2 } from 'solid-icons/oc'; import Island, { IslandLink } from './island'; @@ -7,9 +7,11 @@ interface HashtagProps { } const Hashtag: Component = (props) => { + const text = () => props.text; + const href = new URL(location.href); - href.searchParams.set('h', encodeURIComponent(props.text)); + createEffect(() => href.searchParams.set('h', encodeURIComponent(text()))); return ( diff --git a/src/components/sides-compontents/side-links.tsx b/src/components/sides-compontents/side-links.tsx index e7e069f..ec13ea3 100644 --- a/src/components/sides-compontents/side-links.tsx +++ b/src/components/sides-compontents/side-links.tsx @@ -1,6 +1,6 @@ import { Component, createMemo, For } from 'solid-js'; import { A } from '@solidjs/router'; -import getLeftLink from '../../sideurls'; +import getLeftLink from '../../side-urls'; import { ChildrenProps } from '../../common'; import Island from './island'; @@ -15,7 +15,7 @@ const LeftLink: Component = (props) => { return (
  • {props.children} diff --git a/src/contexts/usercontext.tsx b/src/contexts/user-context.tsx similarity index 64% rename from src/contexts/usercontext.tsx rename to src/contexts/user-context.tsx index 0182409..d6a1109 100644 --- a/src/contexts/usercontext.tsx +++ b/src/contexts/user-context.tsx @@ -20,18 +20,20 @@ async function GetUser(): Promise { // refresh page Cookies.remove('AuthToken'); - console.error('Invalid Auth Token; Refreshing.'); + console.warn('GetUser: Invalid `AuthToken`, refreshing'); location.reload(); return undefined as never; } + console.log('GetUser: Gotten user successfully', User); + return User; } catch { - /* empty */ - } + console.warn('GetUser: Could not get user'); - return undefined; + return undefined; + } } /** @@ -46,15 +48,22 @@ const UserResource = Solid.createResource(GetUser); export const UserProvider: Solid.Component = (props) => { const [user] = UserResource; - const Auth = UserReq.getAuth(), - isInDevelopment = import.meta.env.DEV; + const isInDevelopment = import.meta.env.DEV; + + Solid.createEffect(() => { + console.log('Is in Development:', isInDevelopment); + }); - return !Auth || isInDevelopment ? ( - {props.children} - ) : ( - - {props.children} - + return ( + <> + {isInDevelopment ? ( + {props.children} + ) : ( + + {props.children} + + )} + ); }; diff --git a/src/index.css b/src/index.css index dd7c2fa..750f958 100644 --- a/src/index.css +++ b/src/index.css @@ -9,7 +9,7 @@ } .head-btn { - @apply p-2 rounded text-lg outline outline-1 text-title outline-outline h-8 gap-2 full-center; + @apply p-2 rounded outline outline-1 text-title outline-outline h-8 gap-2 full-center; } .btn { diff --git a/src/index.tsx b/src/index.tsx index 8d530bc..d25b46d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,7 +5,7 @@ import { render } from 'solid-js/web'; import { Router, Route } from '@solidjs/router'; import { Link, MetaProvider } from '@solidjs/meta'; -import { UserProvider } from './contexts/usercontext'; +import { UserProvider } from './contexts/user-context'; import 'solid-devtools'; import './index.css'; @@ -49,21 +49,20 @@ function getRoot(): HTMLElement { */ const RouteElement = () => { return ( - + - - - + + - - - - + + + + @@ -74,9 +73,9 @@ const RouteElement = () => { - + - + ); }; diff --git a/src/logo.png b/src/logo.png deleted file mode 100644 index c850aaf..0000000 Binary files a/src/logo.png and /dev/null differ diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 8f5906c..0000000 --- a/src/logo.svg +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/requests/images.ts b/src/requests/images.ts index 0b1d7d4..65d7ddf 100644 --- a/src/requests/images.ts +++ b/src/requests/images.ts @@ -52,6 +52,8 @@ export function deformatImages(images: string): ImageObj[] { index++; } + console.log(`DeformatImages: ${images}:`, total); + return total; } @@ -71,7 +73,10 @@ export function reformatImages(images: ImageObj[]): string { index++; } - return total.join(','); + const join = total.join(','); + + console.log('ReformatImages:', total, `: ${join}`); + return join; } /** diff --git a/src/requests/post.ts b/src/requests/post.ts index 442f60b..0899443 100644 --- a/src/requests/post.ts +++ b/src/requests/post.ts @@ -10,6 +10,13 @@ export interface Post { content: string; timeCreated: string; parentID: number; + + likes: number; + whoLiked: string; + + dislikes: number; + whoDisliked: string; + images: string; } @@ -29,6 +36,10 @@ export interface PostListReq { export const DefaultPost: Post = { ID: 0, postedBy: 0, + whoDisliked: '', + dislikes: 0, + likes: 0, + whoLiked: '', content: 'THIS TEST CODE DO NOT USE FOR PRODUCTION', timeCreated: 'Invalid Date', parentID: -1, diff --git a/src/routes/add-post.tsx b/src/routes/add-post.tsx index ceed596..897bd64 100644 --- a/src/routes/add-post.tsx +++ b/src/routes/add-post.tsx @@ -2,8 +2,8 @@ import { NoEnter, Status, Statuses } from '../common'; import { Accessor, Component, For, Show } from 'solid-js'; import { addPost as addPost, AddPostRequest } from '../requests/post'; -import { PostSkeleton } from '../components/Post'; -import { useUser } from '../contexts/usercontext'; +import { PostSkeleton } from '../components/post'; +import { useUser } from '../contexts/user-context'; import { OcImage2, OcPaperairplane2, OcX2 } from 'solid-icons/oc'; import { uploadImage, reformatImages, ImageObj } from '../requests/images'; import Header from '../components/header'; @@ -11,12 +11,13 @@ import Sides from '../components/sides'; import { useInput } from '../hooks'; import { Meta, Title } from '@solidjs/meta'; import { createStore, SetStoreFunction } from 'solid-js/store'; +import { User } from '../requests/user'; /** * Propetries for {@link AddImageButton} */ interface AddImageProps { - OnFileAdd: (Params: FileAddParams, event: Event) => Promise | void; + onFileAdd: (Params: FileAddParams, event: Event) => Promise | void; Params: FileAddParams; } @@ -47,7 +48,7 @@ const AddImageButton: Component = (props) => { type='file' id='image-picker' class='absolute -z-10 opacity-0' - onInput={[props.OnFileAdd, props.Params as any]} + onInput={(event) => props.onFileAdd(props.Params, event)} accept='image/png, image/jpeg, image/gif' multiple /> @@ -55,44 +56,26 @@ const AddImageButton: Component = (props) => { ); }; -/** - * Inputs need to {@link OnSubmit submit} a post. - */ -interface SubmitInputs { - /*The content of the post*/ - input: Accessor; - /** - * Gets the status and images - */ - state: PromptState; - /** - * Sets the status and images - */ - setState: SetStoreFunction; -} - -/** - * Submits a new post to the Database (Can fail) - * @param inputs content, images and setting status - * @param event The mouse event - */ -const OnSubmit = async (inputs: SubmitInputs, event: MouseEvent) => { +const onSubmit = async ( + input: Accessor, + state: PromptState, + setState: SetStoreFunction, + user: User, + event: MouseEvent, +) => { event.preventDefault(); try { - const userID = useUser()?.ID; - if (!userID) throw new Error('UserID doesn not exist'); - const Req: AddPostRequest = { - content: inputs.input(), - images: reformatImages(inputs.state.Images), - postedBy: userID, + content: input(), + images: reformatImages(state.Images), + postedBy: user.ID, parentID: -1, // Sole Post }; const Res = await addPost(Req); - inputs.setState('status', { + setState('status', { show: true, ok: Res.ok, msg: Res.ok ? 'Success' : 'Something Went Wrong', @@ -102,7 +85,7 @@ const OnSubmit = async (inputs: SubmitInputs, event: MouseEvent) => { } catch (err) { console.error(err); - inputs.setState('status', { + setState('status', { show: true, ok: false, msg: (err as Error).message, @@ -187,7 +170,7 @@ module ImagePreview { * Closes a {@link ImagePreview} * @param Params the {@link ImagePreview.Props Propetries} of {@link ImagePreview} */ - export const Close = (Params: Props) => { + export const close = (Params: Props) => { Params.setState('Images', (prev) => { const clone = [...prev]; clone.splice(Params.index, 1); @@ -200,19 +183,19 @@ module ImagePreview { * @param props {@link ImagePreview.Props Propetries} */ export const Preview: Component = (props) => { - const image = props.state.Images[props.index]; + const image = () => props.state.Images[props.index]; return (
  • {image.alt} { const [Connecter, getInput] = useInput(); - const User = useUser(); - if (!User) throw new Error('UserID doesn not exist'); + const user = useUser(); + if (!user) throw new Error('UserID doesn not exist'); const [state, setState] = createStore({ Images: [], @@ -246,7 +229,7 @@ const Prompt: Component = () => { const colorStatus = () => (state.status.ok ? 'text-accent' : 'text-warning'); return ( - +
    @@ -262,8 +245,8 @@ const Prompt: Component = () => { cols={50} rows={6} maxLength={240} - oninput={Connecter} - onkeydown={NoEnter} + onInput={Connecter} + onKeyDown={NoEnter} />

    {getInput().length}/240 @@ -271,7 +254,7 @@ const Prompt: Component = () => {

    - + 0}>