From 7fb541fc8386178c441522352fbf08e389d743b8 Mon Sep 17 00:00:00 2001 From: FrOZEn-FurY Date: Wed, 28 Aug 2024 00:33:15 +0330 Subject: [PATCH] feat: Generates the graph with the given values --- project/package-lock.json | 644 ++++++++++++++++++ project/package.json | 2 + .../manage-users/manage-users.component.ts | 4 +- .../show-data/show-data.component.html | 13 +- .../show-data/show-data.component.scss | 44 ++ .../show-data/show-data.component.ts | 237 ++++++- .../fetchData/fetch-data.service.spec.ts | 16 + .../services/fetchData/fetch-data.service.ts | 39 ++ .../modify-user/modify-user.service.ts | 6 +- project/src/app/services/user/user.service.ts | 2 +- 10 files changed, 982 insertions(+), 25 deletions(-) create mode 100644 project/src/app/services/fetchData/fetch-data.service.spec.ts create mode 100644 project/src/app/services/fetchData/fetch-data.service.ts diff --git a/project/package-lock.json b/project/package-lock.json index fe33110..741e6a4 100644 --- a/project/package-lock.json +++ b/project/package-lock.json @@ -18,6 +18,8 @@ "@angular/platform-server": "^18.1.0", "@angular/router": "^18.1.0", "@angular/ssr": "^18.1.2", + "@types/d3": "^7.4.3", + "d3": "^7.9.0", "express": "^4.18.2", "jalaali-js": "^1.2.7", "rxjs": "~7.8.0", @@ -5135,6 +5137,228 @@ "@types/node": "*" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz", + "integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz", + "integrity": "sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/eslint": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", @@ -5185,6 +5409,11 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -7797,6 +8026,395 @@ "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-dsv/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/date-format": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", @@ -7909,6 +8527,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -10085,6 +10711,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -14326,6 +14960,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/rollup": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", @@ -14396,6 +15035,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", diff --git a/project/package.json b/project/package.json index 16b87cc..ddd4a0b 100644 --- a/project/package.json +++ b/project/package.json @@ -23,6 +23,8 @@ "@angular/platform-server": "^18.1.0", "@angular/router": "^18.1.0", "@angular/ssr": "^18.1.2", + "@types/d3": "^7.4.3", + "d3": "^7.9.0", "express": "^4.18.2", "jalaali-js": "^1.2.7", "rxjs": "~7.8.0", diff --git a/project/src/app/components/dashboard/manage-users/manage-users.component.ts b/project/src/app/components/dashboard/manage-users/manage-users.component.ts index 6953141..c900cec 100644 --- a/project/src/app/components/dashboard/manage-users/manage-users.component.ts +++ b/project/src/app/components/dashboard/manage-users/manage-users.component.ts @@ -39,7 +39,7 @@ export class ManageUsersComponent { ngOnInit(): void { const token = this.getToken(); - this.http.get(API_BASE_URL + 'Identity/GetUsers', {headers: {'Authorization': "bearer " + token}}) + this.http.get(API_BASE_URL + 'identity', {headers: {'Authorization': "bearer " + token}}) .subscribe((response) => { this.users = response; this.finalUsers = response; @@ -83,7 +83,7 @@ export class ManageUsersComponent { role: this.formGroup.value.role, } const token = this.getToken(); - this.http.post(API_BASE_URL + 'Identity/Signup', data, {headers: {'Authorization': "Bearer " + token}}) + this.http.post(API_BASE_URL + 'identity/signup', data, {headers: {'Authorization': "Bearer " + token}}) .subscribe((res) => { this.finalUsers?.push(res); this.handleClose(); diff --git a/project/src/app/components/dashboard/show-data/show-data.component.html b/project/src/app/components/dashboard/show-data/show-data.component.html index 40d3d1d..f787d4a 100644 --- a/project/src/app/components/dashboard/show-data/show-data.component.html +++ b/project/src/app/components/dashboard/show-data/show-data.component.html @@ -13,6 +13,10 @@ }
+
+ + +
@@ -40,6 +44,11 @@

هیچ داده ای برای نمایش یافت نشد.

+
- -
+
+
    +
  • نمایش کاربر
  • +
  • افزایش تراکنش ها
  • +
+
diff --git a/project/src/app/components/dashboard/show-data/show-data.component.scss b/project/src/app/components/dashboard/show-data/show-data.component.scss index 1228ed5..7559198 100644 --- a/project/src/app/components/dashboard/show-data/show-data.component.scss +++ b/project/src/app/components/dashboard/show-data/show-data.component.scss @@ -87,4 +87,48 @@ @apply absolute w-[4rem] h-[4rem] top-0 right-0; color: $bg-color; } + .form-search-user { + @apply text-[2rem] self-center border rounded-2xl transition-all duration-300 ease-in-out p-4 flex flex-row + gap-4 items-center; + inline-size: 70rem; + + input { + @apply flex-grow p-4 rounded-2xl; + } + } + #graph-container { + @apply self-stretch flex-grow m-8 rounded-xl; + background-color: $secondary-color; + } +} +.context-menu-container { + position: absolute; + + display: none; + + padding: 1rem; + + flex-direction: column; + justify-content: center; + align-items: center; + + background-color: $primary-color; + color: $bg-color; + + font-size: 1.6rem; + + ul { + list-style: none; + + padding: 0.1rem; + + li { + padding: 0.5rem; + user-select: none; + + &:hover { + cursor: pointer; + } + } + } } diff --git a/project/src/app/components/dashboard/show-data/show-data.component.ts b/project/src/app/components/dashboard/show-data/show-data.component.ts index f87462f..7e8f600 100644 --- a/project/src/app/components/dashboard/show-data/show-data.component.ts +++ b/project/src/app/components/dashboard/show-data/show-data.component.ts @@ -1,4 +1,4 @@ -import {Component, ElementRef, ViewChild} from '@angular/core'; +import {Component, ElementRef, EventEmitter, HostListener, Output, ViewChild} from '@angular/core'; import {UserService} from "../../../services/user/user.service"; import User from "../../../interfaces/user"; import {FormsModule} from "@angular/forms"; @@ -9,6 +9,8 @@ import {PersianDatePipe} from "./pipes/persian-date.pipe"; import {heroXMark} from "@ng-icons/heroicons/outline"; import {NgIconComponent, provideIcons} from "@ng-icons/core"; import {BlurClickDirective} from "../../../directives/blur-click.directive"; +import * as d3 from 'd3'; +import {FetchDataService} from "../../../services/fetchData/fetch-data.service"; interface Transaction { TransactionId: number, @@ -19,6 +21,24 @@ interface Transaction { type: string } +interface Node { + x: number; + y: number; + vx: number; + vy: number; + fx?: number | null; + fy?: number | null; + label: string | number; +} + +interface Link { + source: Node; + target: Node; + date: string; + amount: string; + type: string; +} + @Component({ selector: 'app-show-data', standalone: true, @@ -36,14 +56,19 @@ interface Transaction { export class ShowDataComponent { user!: User | undefined; data: Transaction[] | undefined = undefined; - dataGot = false; + nodes: Node[] = []; + links: Link[] = []; + + @Output() dataGotEvent = new EventEmitter(); @ViewChild('labelElement') labelElement!: ElementRef; @ViewChild('inputElement') inputElement!: ElementRef; @ViewChild('selectElement') selectElement!: ElementRef; @ViewChild('dataElement') dataElement!: ElementRef; + @ViewChild('graphElement') graphElement!: ElementRef; + @ViewChild('contextElement') contextElement!: ElementRef; - constructor(private userService: UserService, private http: HttpClient) { + constructor(private userService: UserService, private http: HttpClient, private fetchDataService: FetchDataService) { this.user = this.userService.getUser(); } @@ -64,30 +89,18 @@ export class ShowDataComponent { const file = this.inputElement.nativeElement.files[0]; formData.append('file', file); if (this.selectElement.nativeElement.value === "transaction") { - this.http.post(API_BASE_URL + 'Transaction/ImportTransactions', formData, {headers: {"Authorization": "Bearer " + token}}).subscribe((response) => { + this.http.post(API_BASE_URL + 'transactions/upload', formData, {headers: {"Authorization": "Bearer " + token}}).subscribe((response) => { console.log(response); }) } else if (this.selectElement.nativeElement.value === "account") { - this.http.post(API_BASE_URL + 'Account/ImportAccounts', formData, {headers: {"Authorization": "Bearer " + token}}).subscribe((response) => { + this.http.post(API_BASE_URL + 'accounts/upload', formData, {headers: {"Authorization": "Bearer " + token}}).subscribe((response) => { console.log(response); }) } } } - updateData(): void { - this.dataGot = false; - const token: string | null = this.getToken(); - this.http.get(API_BASE_URL + 'Transaction/GetAllTransactions', {headers: {"Authorization": "Bearer " + token}}).subscribe((response) => { - this.data = response; - this.dataGot = true; - }) - } - showData(): void { - if (this.data === undefined) { - this.updateData(); - } this.dataElement.nativeElement.style.display = 'flex'; } @@ -103,4 +116,194 @@ export class ShowDataComponent { return token; } + + async ngOnInit() { + const response = await this.fetchDataService.fetchData(); + this.data = response; + for (const trans of response) { + if (!this.nodes.find(node => node.label === trans.sourceAccountId)) { + this.nodes.push({ + x: this.nodes[this.nodes.length - 1] ? this.nodes[this.nodes.length - 1].x + 1 : 1, + y: this.nodes[this.nodes.length - 1] ? this.nodes[this.nodes.length - 1].y + 1 : 1, + vx: 1, + vy: 1, + label: trans.sourceAccountId, + }); + } + if (!this.nodes.find(node => node.label === trans.destinationAccountId)) { + this.nodes.push({ + x: this.nodes[this.nodes.length - 1] ? this.nodes[this.nodes.length - 1].x + 1 : 1, + y: this.nodes[this.nodes.length - 1] ? this.nodes[this.nodes.length - 1].y + 1 : 1, + vx: 1, + vy: 1, + label: trans.destinationAccountId, + }); + } + this.links.push({ + source: this.nodes.find(node => node.label === trans.sourceAccountId)!, + target: this.nodes.find(node => node.label === trans.destinationAccountId)!, + date: (new PersianDatePipe()).transform(trans.date), + type: trans.type, + amount: (new RialPipePipe()).transform(trans.amount), + }); + } + this.dataGotEvent.emit(); + } + + @HostListener('dataGotEvent') + handleGraph(): void { + const element = d3.select(this.graphElement.nativeElement) + .append('svg') + .attr('width', this.graphElement.nativeElement.clientWidth) + .attr('height', this.graphElement.nativeElement.clientHeight); + + + const svgGroup = element.append('g'); + + const zoom = d3.zoom() + .scaleExtent([0.5, 4]) + .on('zoom', (event) => { + svgGroup.attr('transform', event.transform); + }); + + element.call(zoom); + + const simulation = d3.forceSimulation(this.nodes) + .force("link", d3.forceLink(this.links)); + + const link = svgGroup.append('g') + .attr('class', 'links') + .selectAll('line') + .data(this.links) + .enter() + .append('line') + .attr('stroke-width', 2) + .attr('stroke', '#FDFDFD'); + + + const linkLabelsAmount = svgGroup.append('g') + .attr('class', 'link-labels') + .selectAll('text') + .data(this.links) + .enter() + .append('text') + .attr('text-anchor', 'middle') + .attr('fill', '#172535') + .attr('style', 'user-select: none;font-weight:bold;font-size:1.5rem;') + .text((d: Link) => d.amount ? d.amount : ""); + + const linkLabelsType = svgGroup.append('g') + .attr('class', 'link-labels') + .selectAll('text') + .data(this.links) + .enter() + .append('text') + .attr('text-anchor', 'middle') + .attr('fill', '#172535') + .attr('style', 'user-select: none;font-weight:bold;font-size:1.5rem;') + .text((d: Link) => d.type ? d.type : ""); + + const linkLabelsDate = svgGroup.append('g') + .attr('class', 'link-labels') + .selectAll('text') + .data(this.links) + .enter() + .append('text') + .attr('text-anchor', 'middle') + .attr('fill', '#172535') + .attr('style', 'user-select: none;font-weight:bold;font-size:1.5rem;') + .text((d: Link) => d.date ? d.date : ""); + + const node = svgGroup.append('g') + .attr('class', 'nodes') + .selectAll('circle') + .data(this.nodes) + .enter() + .append('circle') + .attr('r', 10) + .attr('fill', '#002B5B') + .call(d3.drag() + .on('start', dragStarted) + .on('drag', dragged) + .on('end', dragEnded) + ); + + node.on('contextmenu', (event: MouseEvent, d: Node) => { + event.preventDefault(); + + this.contextElement.nativeElement.style.display = 'flex'; + this.contextElement.nativeElement.style.top = event.clientY + 'px'; + this.contextElement.nativeElement.style.left = event.clientX + 'px'; + }); + + const nodeLabels = svgGroup.append('g') + .attr('class', 'node-labels') + .selectAll('text') + .data(this.nodes) + .enter() + .append('text') + .attr('text-anchor', 'middle') + .attr('dy', -10) // Position above the node + .attr('fill', '#172535') + .attr('style', 'user-select: none;font-weight:bold;font-size:1.5rem;') + .text((d: Node) => d.label ? d.label : ""); + + function ticked() { + link + .attr('x1', d => d.source.x) + .attr('y1', d => d.source.y) + .attr('x2', d => d.target.x) + .attr('y2', d => d.target.y); + + node + .attr('cx', d => d.x) + .attr('cy', d => d.y); + + // Update positions of node labels + nodeLabels + .attr('x', d => d.x) + .attr('y', d => d.y); + + // Update positions of link labels + linkLabelsAmount + .attr('x', d => ((d.source as Node).x + (d.target as Node).x) / 2) + .attr('y', d => ((d.source as Node).y + (d.target as Node).y) / 2); + + linkLabelsDate + .attr('x', d => ((d.source as Node).x + (d.target as Node).x) / 2) + .attr('y', d => ((d.source as Node).y + (d.target as Node).y) / 2 + 20); + + linkLabelsType + .attr('x', d => ((d.source as Node).x + (d.target as Node).x) / 2) + .attr('y', d => ((d.source as Node).y + (d.target as Node).y) / 2 + 40); + } + + simulation.on('tick', ticked); + + simulation + .force('link', d3.forceLink(this.links).id((d, i) => i).distance(250)) + .force('charge', d3.forceManyBody().strength(-350)) + .force('center', d3.forceCenter(this.graphElement.nativeElement.clientWidth / 2, this.graphElement.nativeElement.clientHeight / 2)); + + function dragStarted(event: d3.D3DragEvent, d: Node) { + if (!event.active) simulation.alphaTarget(0.3).restart(); + d.fx = d.x; + d.fy = d.y; + } + + function dragged(event: d3.D3DragEvent, d: Node) { + d.fx = event.x; + d.fy = event.y; + } + + function dragEnded(event: d3.D3DragEvent, d: Node) { + if (!event.active) simulation.alphaTarget(0); + d.fx = null; + d.fy = null; + } + } + + handleCloseContext() { + this.contextElement.nativeElement.style.display = 'none'; + } } diff --git a/project/src/app/services/fetchData/fetch-data.service.spec.ts b/project/src/app/services/fetchData/fetch-data.service.spec.ts new file mode 100644 index 0000000..5bcbb9e --- /dev/null +++ b/project/src/app/services/fetchData/fetch-data.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { FetchDataService } from './fetch-data.service'; + +describe('FetchDataService', () => { + let service: FetchDataService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(FetchDataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/project/src/app/services/fetchData/fetch-data.service.ts b/project/src/app/services/fetchData/fetch-data.service.ts new file mode 100644 index 0000000..09b0403 --- /dev/null +++ b/project/src/app/services/fetchData/fetch-data.service.ts @@ -0,0 +1,39 @@ +import {Inject, Injectable, PLATFORM_ID} from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {isPlatformBrowser} from "@angular/common"; +import {API_BASE_URL} from "../../app.config"; +import {firstValueFrom} from "rxjs"; + +interface Transaction { + TransactionId: number, + sourceAccountId: number, + destinationAccountId: number, + amount: number, + date: string, + type: string +} + +@Injectable({ + providedIn: 'root' +}) +export class FetchDataService { + + constructor(private http: HttpClient, @Inject(PLATFORM_ID) private platform: object) { } + + fetchData(): Promise { + const token = this.getToken(); + return firstValueFrom(this.http.get(API_BASE_URL + 'transactions', {headers: {'Authorization': "Bearer " + token}})) + } + + getToken(): string | null { + if(isPlatformBrowser(this.platform)) { + let token = localStorage.getItem("token"); + if (token) { + token = token.substring(1, token.length - 1); + } + + return token; + } + return null; + } +} diff --git a/project/src/app/services/modify-user/modify-user.service.ts b/project/src/app/services/modify-user/modify-user.service.ts index 723aec7..959713b 100644 --- a/project/src/app/services/modify-user/modify-user.service.ts +++ b/project/src/app/services/modify-user/modify-user.service.ts @@ -31,7 +31,7 @@ export class ModifyUserService { modifyUser(data: ChangeData): void { const token = this.getToken(); - this.http.put(API_BASE_URL + 'Profile/EditProfileInfo', data, {headers: {'Authorization': "Bearer " + token}}) + this.http.put(API_BASE_URL + 'profile/edit-info', data, {headers: {'Authorization': "Bearer " + token}}) .subscribe(() => { const user = { firstName: data.firstName, @@ -45,7 +45,7 @@ export class ModifyUserService { changePassword(data: ChangePassword): void { const token = this.getToken(); - this.http.put(API_BASE_URL + 'Profile/ChangePassword', data, {headers: {'Authorization': "Bearer " + token}}) + this.http.put(API_BASE_URL + 'profile/change-password', data, {headers: {'Authorization': "Bearer " + token}}) .subscribe(response => { console.log(response); }); @@ -58,7 +58,7 @@ export class ModifyUserService { role } - this.http.put(API_BASE_URL + 'Identity/ChangeRole', data, {headers: {'Authorization': "Bearer " + token}}) + this.http.patch(API_BASE_URL + 'identity/change-role', data, {headers: {'Authorization': "Bearer " + token}}) .subscribe((response) => { console.log(response); }) diff --git a/project/src/app/services/user/user.service.ts b/project/src/app/services/user/user.service.ts index 0fba0bd..8fbbc83 100644 --- a/project/src/app/services/user/user.service.ts +++ b/project/src/app/services/user/user.service.ts @@ -36,7 +36,7 @@ export class UserService { username: user.identifier.includes('@') ? null : user.identifier, password: user.password, } - this.http.post(`${API_BASE_URL}Identity/Login`, obj).subscribe((res: any) => { + this.http.post(`${API_BASE_URL}identity/login`, obj).subscribe((res: any) => { this.user = {}; this.user.userName = res?.username; localStorage.setItem('token', JSON.stringify(res?.token));