From d0400cadcbfbc30449aa648a6c174328e329e232 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Sun, 6 Nov 2022 17:33:54 +0300 Subject: [PATCH 1/3] feat: added views netlify function --- .gitignore | 4 +- netlify.toml | 9 +- netlify/functions/views.ts | 42 +++++++++ package-lock.json | 180 +++++++++++++++++++++++++++++++++++-- package.json | 2 + tsconfig.json | 1 + 6 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 netlify/functions/views.ts diff --git a/.gitignore b/.gitignore index a0bc0c8..1b22441 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ pnpm-debug.log* .env.production # macOS-specific files -.DS_Store \ No newline at end of file +.DS_Store +# Local Netlify folder +.netlify diff --git a/netlify.toml b/netlify.toml index 86e0391..9a237f2 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,3 +1,10 @@ [build] command = "npm run build" - publish = "dist" \ No newline at end of file + publish = "dist" + functions = "netlify/functions" + +[[redirects]] + from = "/api/*" # simplify all calls to serverless functions + to = "/.netlify/functions/:splat" # all function calls will go to this path + status = 200 # ok code + force = true # ensure to always redirect \ No newline at end of file diff --git a/netlify/functions/views.ts b/netlify/functions/views.ts new file mode 100644 index 0000000..abc7fbe --- /dev/null +++ b/netlify/functions/views.ts @@ -0,0 +1,42 @@ +import { Handler } from "@netlify/functions"; + +import Redis from "ioredis"; + +const redis = new Redis({ + host: "redis-19655.c300.eu-central-1-1.ec2.cloud.redislabs.com", + port: 19655, + password: process.env.REDIS_PASSWORD, +}); + +const getViewsBySlug = async (slug: string): Promise => { + let views = 1; + const data = await redis.get(`views:${slug}`); + if (data) views = Number.parseInt(data, 10); + if (Number.isNaN(views)) views = 1; + return views; +}; + +const handler: Handler = async (event) => { + const slug = event.queryStringParameters?.slug; + + switch (event.httpMethod) { + case "GET": { + if (!slug) return { statusCode: 400, body: "Bad request." }; + const views = await getViewsBySlug(slug); + return { statusCode: 200, body: views.toString() }; + } + case "POST": { + if (!slug) return { statusCode: 400, body: "Bad request." }; + const views = await redis.incr(`views:${slug}`); + return { statusCode: 200, body: views.toString() }; + } + default: { + return { + statusCode: 500, + body: "Unrecognized HTTP Method, must be one of GET/POST", + }; + } + } +}; + +export { handler }; diff --git a/package-lock.json b/package-lock.json index 187dc6c..51957be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,16 @@ { "name": "yarkov.tech", - "version": "1.0.3", + "version": "1.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "yarkov.tech", - "version": "1.0.3", + "version": "1.0.6", "license": "MIT", "dependencies": { + "@netlify/functions": "^1.3.0", + "ioredis": "^5.2.4", "sharp": "^0.31.2" }, "devDependencies": { @@ -798,6 +800,11 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -927,6 +934,17 @@ "rollup": ">=2" } }, + "node_modules/@netlify/functions": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.3.0.tgz", + "integrity": "sha512-hN/Fgpz8XIOBfsBPLYUMxVKBlCopgeqGB0popayicnmkFLnvKByTTMYgF01wcF9DBtBQdV0H2h1kPFpMl34I8w==", + "dependencies": { + "is-promise": "^4.0.0" + }, + "engines": { + "node": ">=8.3.0" + } + }, "node_modules/@node-minify/core": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz", @@ -2333,6 +2351,14 @@ "node": ">=0.8" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -2485,7 +2511,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2591,6 +2616,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -4796,6 +4829,29 @@ "node": ">= 0.4" } }, + "node_modules/ioredis": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz", + "integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -5070,6 +5126,11 @@ "node": ">=8" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "node_modules/is-reference": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz", @@ -5404,6 +5465,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6735,8 +6806,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { "version": "3.3.4", @@ -7590,6 +7660,25 @@ "node": ">=0.10.0" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -8472,6 +8561,11 @@ "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", "dev": true }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10663,6 +10757,11 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -10771,6 +10870,14 @@ "vfile": "^5.0.0" } }, + "@netlify/functions": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.3.0.tgz", + "integrity": "sha512-hN/Fgpz8XIOBfsBPLYUMxVKBlCopgeqGB0popayicnmkFLnvKByTTMYgF01wcF9DBtBQdV0H2h1kPFpMl34I8w==", + "requires": { + "is-promise": "^4.0.0" + } + }, "@node-minify/core": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz", @@ -11818,6 +11925,11 @@ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true }, + "cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" + }, "color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -11944,7 +12056,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -12014,6 +12125,11 @@ "object-keys": "^1.1.1" } }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, "dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -13577,6 +13693,22 @@ "side-channel": "^1.0.4" } }, + "ioredis": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz", + "integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==", + "requires": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + } + }, "is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -13743,6 +13875,11 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "is-reference": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz", @@ -13988,6 +14125,16 @@ "p-locate": "^5.0.0" } }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -14889,8 +15036,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { "version": "3.3.4", @@ -15485,6 +15631,19 @@ } } }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -16131,6 +16290,11 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "dev": true }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 4376aed..d59f9d8 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,8 @@ "solid-js": "^1.6.1" }, "dependencies": { + "@netlify/functions": "^1.3.0", + "ioredis": "^5.2.4", "sharp": "^0.31.2" } } diff --git a/tsconfig.json b/tsconfig.json index 9127811..5dad1b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "target": "ESNext", "module": "ESNext", "moduleResolution": "node", + "esModuleInterop": true, "resolveJsonModule": true, "isolatedModules": true, "types": ["vite/client", "@astrojs/image/client", "@types/mdx"], From 92ffa444daa1ba4f6033a5f739cb10069fbd9f14 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Sun, 6 Nov 2022 18:07:00 +0300 Subject: [PATCH 2/3] feat: added views to ArticlePost --- .env.example | 4 ++ netlify/functions/views.ts | 4 +- src/components/ArticlePost/ArticlePost.astro | 45 ++++++++++++++------ src/components/ArticlePost/ArticlePost.scss | 24 ++++++++++- src/i18n/en/ui.ts | 1 + src/i18n/ru/ui.ts | 1 + src/icons/eye.svg | 3 ++ 7 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 .env.example create mode 100644 src/icons/eye.svg diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e62d18f --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +IS_SITE_UNDER_CONSTRUCTION=false +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD=12345 \ No newline at end of file diff --git a/netlify/functions/views.ts b/netlify/functions/views.ts index abc7fbe..e4e8b20 100644 --- a/netlify/functions/views.ts +++ b/netlify/functions/views.ts @@ -3,8 +3,8 @@ import { Handler } from "@netlify/functions"; import Redis from "ioredis"; const redis = new Redis({ - host: "redis-19655.c300.eu-central-1-1.ec2.cloud.redislabs.com", - port: 19655, + host: process.env.REDIS_HOST, + port: Number.parseInt(process.env.REDIS_PORT || "6379", 10), password: process.env.REDIS_PASSWORD, }); diff --git a/src/components/ArticlePost/ArticlePost.astro b/src/components/ArticlePost/ArticlePost.astro index bc42a3a..2ad1992 100644 --- a/src/components/ArticlePost/ArticlePost.astro +++ b/src/components/ArticlePost/ArticlePost.astro @@ -1,10 +1,12 @@ --- import { Picture } from "@astrojs/image/components"; +import { Icon } from "astro-icon"; import { createDateFormatter } from "@root/utils"; import { isURL } from "@utils/string"; import ArticleComments from "@components/ArticleComments"; import TranslatedLink from "../TranslatedLink"; import "./ArticlePost.scss"; +import { useTranslation } from "@root/i18n/utils"; export type Props = { data: ArticleType; @@ -12,23 +14,30 @@ export type Props = { }; const { data, lang } = Astro.props as Props; -const { title, description, coverImage, tags, author, published_at } = data; +const { slug, title, description, coverImage, tags, author, published_at } = data; +const t = useTranslation(Astro); ---
-
-
    - { - tags.map((tag) => ( -
  • - -
  • - )) - } -
+
+
+
    + { + tags.map((tag) => ( +
  • + +
  • + )) + } +
+
+
+ + --- {t("article.views")} +

{title}

@@ -65,3 +74,13 @@ const { title, description, coverImage, tags, author, published_at } = data;
+ + diff --git a/src/components/ArticlePost/ArticlePost.scss b/src/components/ArticlePost/ArticlePost.scss index 56da18e..1f63f75 100644 --- a/src/components/ArticlePost/ArticlePost.scss +++ b/src/components/ArticlePost/ArticlePost.scss @@ -1,5 +1,18 @@ .article { & header { + & div:nth-child(1) { + display: flex; + justify-content: space-between; + align-items: center; + & .views { + display: flex; + align-items: center; + & span { + margin-left: 3.5px; + font-size: var(--font-size-sm); + } + } + } & .heading { margin-top: 1.125rem; @@ -62,8 +75,15 @@ @media screen and (max-width: 560px) { .article { - & header .heading h1 { - font-size: 2rem; + & header { + & div:nth-child(1) { + flex-direction: column-reverse; + row-gap: 10px; + align-items: flex-start; + } + & .heading h1 { + font-size: 2rem; + } } } } diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index a140144..c7ef8c1 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -6,6 +6,7 @@ export default { "article.availableOn": "Available on", "articles.empty": "No articles found...", "articlePost.comments": "Comments", + "article.views": "views", "recentArticles.empty": "There is nothing here yet...", /* Page titles */ "pageTitle.about": "About me", diff --git a/src/i18n/ru/ui.ts b/src/i18n/ru/ui.ts index f7ad02c..32cea20 100644 --- a/src/i18n/ru/ui.ts +++ b/src/i18n/ru/ui.ts @@ -6,6 +6,7 @@ export default { "article.availableOn": "Доступно на", "articles.empty": "Не найдено ни одной статьи...", "articlePost.comments": "Комментарии", + "article.views": "просмотров", "recentArticles.empty": "Пока что здесь ничего нет...", /* Page titles */ "pageTitle.about": "Обо мне", diff --git a/src/icons/eye.svg b/src/icons/eye.svg new file mode 100644 index 0000000..5ec0611 --- /dev/null +++ b/src/icons/eye.svg @@ -0,0 +1,3 @@ + + + From 111f35d36b8d9162a30b256cb9c35745a2ec3717 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Sun, 6 Nov 2022 18:07:51 +0300 Subject: [PATCH 3/3] bump ver --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d59f9d8..35047d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yarkov.tech", - "version": "1.0.6", + "version": "1.1.6", "private": true, "description": "Personal website created with Astro.", "author": {