* Добавлена страница скачивания файлов, кнопки скачивания изменены на ссылки

* Добавлено игнорирование кода 204
* less перенесён в dev зависимости
This commit is contained in:
goodmice 2022-06-29 16:45:38 +05:00
parent ad66af1a10
commit fa751240ba
9 changed files with 260 additions and 54 deletions

111
package-lock.json generated
View File

@ -15,7 +15,6 @@
"chartjs-plugin-datalabels": "^2.0.0",
"chartjs-plugin-zoom": "^1.2.1",
"d3": "^7.4.4",
"less": "^4.1.2",
"moment": "^2.29.3",
"pigeon-maps": "^0.21.0",
"react": "^18.1.0",
@ -46,6 +45,7 @@
"html-webpack-plugin": "^5.5.0",
"interpolate-html-plugin": "^4.0.0",
"jest": "^28.1.0",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"openapi-typescript": "^5.4.0",
"openapi-typescript-codegen": "^0.23.0",
@ -4855,6 +4855,7 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
"integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
"dev": true,
"dependencies": {
"is-what": "^3.14.1"
},
@ -5445,6 +5446,7 @@
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"optional": true,
"dependencies": {
"ms": "^2.1.1"
@ -5751,6 +5753,7 @@
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"dev": true,
"optional": true,
"dependencies": {
"prr": "~1.0.1"
@ -6453,7 +6456,7 @@
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
"devOptional": true
"dev": true
},
"node_modules/hammerjs": {
"version": "2.0.8",
@ -6751,7 +6754,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"devOptional": true,
"dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@ -6775,6 +6778,7 @@
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
"dev": true,
"optional": true,
"bin": {
"image-size": "bin/image-size.js"
@ -7031,7 +7035,8 @@
"node_modules/is-what": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
"dev": true
},
"node_modules/is-wsl": {
"version": "2.2.0",
@ -8274,9 +8279,10 @@
}
},
"node_modules/less": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.2.tgz",
"integrity": "sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz",
"integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==",
"dev": true,
"dependencies": {
"copy-anything": "^2.0.1",
"parse-node-version": "^1.0.1",
@ -8294,7 +8300,7 @@
"image-size": "~0.5.0",
"make-dir": "^2.1.0",
"mime": "^1.4.1",
"needle": "^2.5.2",
"needle": "^3.1.0",
"source-map": "~0.6.0"
}
},
@ -8430,6 +8436,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"optional": true,
"dependencies": {
"pify": "^4.0.1",
@ -8443,6 +8450,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"optional": true,
"bin": {
"semver": "bin/semver"
@ -8527,7 +8535,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"devOptional": true,
"dev": true,
"bin": {
"mime": "cli.js"
},
@ -8610,7 +8618,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"devOptional": true
"dev": true
},
"node_modules/multicast-dns": {
"version": "7.2.4",
@ -8644,13 +8652,14 @@
"dev": true
},
"node_modules/needle": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
"integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz",
"integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==",
"dev": true,
"optional": true,
"dependencies": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"iconv-lite": "^0.6.3",
"sax": "^1.2.4"
},
"bin": {
@ -8660,6 +8669,19 @@
"node": ">= 4.4.x"
}
},
"node_modules/needle/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==",
"dev": true,
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@ -9030,6 +9052,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
@ -9129,6 +9152,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true,
"optional": true,
"engines": {
"node": ">=6"
@ -9361,6 +9385,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
"dev": true,
"optional": true
},
"node_modules/psl": {
@ -10402,6 +10427,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true,
"optional": true
},
"node_modules/scheduler": {
@ -10706,7 +10732,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"devOptional": true,
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -15779,6 +15805,7 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
"integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
"dev": true,
"requires": {
"is-what": "^3.14.1"
}
@ -16209,6 +16236,7 @@
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"optional": true,
"requires": {
"ms": "^2.1.1"
@ -16439,6 +16467,7 @@
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"dev": true,
"optional": true,
"requires": {
"prr": "~1.0.1"
@ -16965,7 +16994,7 @@
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
"devOptional": true
"dev": true
},
"hammerjs": {
"version": "2.0.8",
@ -17192,7 +17221,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"devOptional": true,
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
@ -17208,6 +17237,7 @@
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
"dev": true,
"optional": true
},
"import-fresh": {
@ -17379,7 +17409,8 @@
"is-what": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
"dev": true
},
"is-wsl": {
"version": "2.2.0",
@ -18334,9 +18365,10 @@
"dev": true
},
"less": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.2.tgz",
"integrity": "sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz",
"integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==",
"dev": true,
"requires": {
"copy-anything": "^2.0.1",
"errno": "^0.1.1",
@ -18344,7 +18376,7 @@
"image-size": "~0.5.0",
"make-dir": "^2.1.0",
"mime": "^1.4.1",
"needle": "^2.5.2",
"needle": "^3.1.0",
"parse-node-version": "^1.0.1",
"source-map": "~0.6.0",
"tslib": "^2.3.0"
@ -18450,6 +18482,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"optional": true,
"requires": {
"pify": "^4.0.1",
@ -18460,6 +18493,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"optional": true
}
}
@ -18531,7 +18565,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"devOptional": true
"dev": true
},
"mime-db": {
"version": "1.52.0",
@ -18590,7 +18624,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"devOptional": true
"dev": true
},
"multicast-dns": {
"version": "7.2.4",
@ -18615,14 +18649,27 @@
"dev": true
},
"needle": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
"integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz",
"integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==",
"dev": true,
"optional": true,
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"iconv-lite": "^0.6.3",
"sax": "^1.2.4"
},
"dependencies": {
"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==",
"dev": true,
"optional": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
}
}
},
"negotiator": {
@ -18896,7 +18943,8 @@
"parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
"dev": true
},
"parseurl": {
"version": "1.3.3",
@ -18972,6 +19020,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true,
"optional": true
},
"pigeon-maps": {
@ -19131,6 +19180,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
"dev": true,
"optional": true
},
"psl": {
@ -19905,6 +19955,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true,
"optional": true
},
"scheduler": {
@ -20166,7 +20217,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"devOptional": true
"dev": true
},
"source-map-js": {
"version": "1.0.2",

View File

@ -10,7 +10,6 @@
"chartjs-plugin-datalabels": "^2.0.0",
"chartjs-plugin-zoom": "^1.2.1",
"d3": "^7.4.4",
"less": "^4.1.2",
"moment": "^2.29.3",
"pigeon-maps": "^0.21.0",
"react": "^18.1.0",
@ -93,6 +92,7 @@
"html-webpack-plugin": "^5.5.0",
"interpolate-html-plugin": "^4.0.0",
"jest": "^28.1.0",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"openapi-typescript": "^5.4.0",
"openapi-typescript-codegen": "^0.23.0",

View File

@ -13,6 +13,7 @@ import Login from '@pages/Login'
import Cluster from '@pages/Cluster'
import Deposit from '@pages/Deposit'
import Register from '@pages/Register'
import FileDownload from '@pages/FileDownload'
import '@styles/App.less'
@ -39,6 +40,7 @@ export const App = memo(() => (
<Route path={Deposit.route} element={<Deposit />} />
<Route path={Cluster.route} element={<Cluster />} />
<Route path={Well.route} element={<Well />} />
<Route path={FileDownload.route} element={<FileDownload />} />
</Routes>
</Router>
</RootPathContext.Provider>

View File

@ -1,22 +1,43 @@
import { memo } from 'react'
import { Button, ButtonProps } from 'antd'
import { memo, ReactNode } from 'react'
import { Link, LinkProps } from 'react-router-dom'
import { FileWordOutlined } from '@ant-design/icons'
import { FileInfoDto } from '@api'
import { downloadFile } from './factory'
export type DownloadLinkProps = ButtonProps & {
import { getLinkToFile } from '@pages/FileDownload'
import '@styles/index.css'
export type DownloadLinkProps = LinkProps & {
file?: FileInfoDto
name?: string
icon?: ReactNode
}
export const DownloadLink = memo<DownloadLinkProps>(({ file, name, ...other }) => (
<Button
type={'link'}
icon={<FileWordOutlined />}
onClick={file && (() => downloadFile(file))}
export const DownloadLink = memo<DownloadLinkProps>(({
className = '',
file,
name,
icon = <FileWordOutlined />,
...other
}) => (
<Link
title={'Чтобы поделиться файлом с другим сотрудником скопируйте ссылку'}
{...other}
>{name ?? file?.name ?? '-'}</Button>
className={`download-link ${className}`}
to={getLinkToFile(file)}
onClick={(e) => {
if (file)
downloadFile(file)
e.preventDefault()
return false
}}
>
{icon}
<span style={{ marginLeft: 8 }}>{name ?? file?.name ?? '-'}</span>
</Link>
))
export default DownloadLink

View File

@ -37,6 +37,21 @@ export const notify = (body?: ReactNode, notifyType: NotifyType = 'info', other?
type asyncFunction = (...args: any) => Promise<any|void>
const parseApiEror = (err: unknown, actionName?: string) => {
if (!(err instanceof ApiError)) return false
switch (err.status) {
case 403:
if (actionName)
notify(`Недостаточно прав для выполнения действия "${actionName}"`, 'error')
else
notify('Недостаточно прав для выполнения действия', 'error')
return true
case 204: return true
default: return false
}
}
export const invokeWebApiWrapperAsync = async (
funcAsync: asyncFunction,
setShowLoader?: Dispatch<SetStateAction<boolean>>,
@ -49,14 +64,8 @@ export const invokeWebApiWrapperAsync = async (
} catch (ex) {
if(isDev())
console.error(ex)
if (ex instanceof ApiError && ex.status === 403) {
if (actionName)
notify(`Недостаточно прав для выполнения действия "${actionName}"`, 'error')
else
notify('Недостаточно прав для выполнения действия', 'error')
} else {
if (!parseApiEror(ex, actionName))
notify(getFunctionalValue(errorNotifyText)(ex), 'error')
}
} finally {
setShowLoader?.(false)
}
@ -104,9 +113,11 @@ export const upload = async (url: string, formData: FormData) => {
export const downloadFile = async (fileInfo: FileInfoDto) => {
try {
await download(`/api/well/${fileInfo.idWell}/files/${fileInfo.id}`)
return true
} catch (error) {
notify(`Не удалось скачать файл ${fileInfo.name} по скважине (${fileInfo.idWell})`, 'error')
notify(`Не удалось скачать файл "${fileInfo.name}" по скважине №${fileInfo.idWell}`, 'error')
console.log(error)
return false
}
}

View File

@ -28,7 +28,7 @@ export const AccessDenied = memo(() => {
<Paragraph>
<CloseCircleOutlined style={{ color: 'red' }} />
&nbsp;Страницы не существует.&nbsp;
<Link to={'#'} onClick={navigate(-1)}>Вернуться назад &gt;</Link>
<Link to={'#'} onClick={() => navigate(-1)}>Вернуться назад &gt;</Link>
</Paragraph>
<Paragraph>
<CloseCircleOutlined style={{ color: 'red' }} />

View File

@ -1,11 +1,12 @@
import { useState, useEffect, useMemo, useCallback } from 'react'
import { DatePicker, Button, Input } from 'antd'
import { DatePicker, Input } from 'antd'
import { useIdWell } from '@asb/context'
import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal'
import { UploadForm } from '@components/UploadForm'
import { CompanyView, UserView } from '@components/views'
import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '@components/factory'
import { invokeWebApiWrapperAsync, formatBytes } from '@components/factory'
import { EditableTable, makeColumn, makeDateColumn, makeNumericColumn, makePaginationObject } from '@components/Table'
import { unique } from '@utils/filters'
import { hasPermission } from '@utils'
@ -21,9 +22,7 @@ const columns = [
key: 'document',
dataIndex: 'name',
render: (name, row) => (
<Button type={'link'} onClick={() => downloadFile(row)} download={name}>
{name}
</Button>
<DownloadLink file={row} name={name} />
),
},
makeDateColumn('Дата загрузки', 'uploadDate'),

107
src/pages/FileDownload.jsx Normal file
View File

@ -0,0 +1,107 @@
import { Link, useNavigate, useParams } from 'react-router-dom'
import { memo, useCallback, useEffect, useState } from 'react'
import { InfoCircleFilled, CloseCircleOutlined } from '@ant-design/icons'
import { Button, Result, Typography } from 'antd'
import { downloadFile, invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils'
import { FileService, WellService } from '@api'
import AccessDenied from './AccessDenied'
const { Paragraph, Text } = Typography
export const getLinkToFile = (fileInfo) => `/file_download/${fileInfo.idWell}/${fileInfo.id}`
const FileDownload = memo(function FileDownload() {
const { idWell, idFile } = useParams()
const [well, setWell] = useState({})
const [file, setFile] = useState({})
const [isError, setIsError] = useState(false)
const navigate = useNavigate()
useEffect(() => {
invokeWebApiWrapperAsync(
async () => setWell(await WellService.get(idWell)),
null,
'Не удалось получить информацию о скважине',
'Получение данных о скважине',
)
}, [idWell])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const files = await FileService.getFilesInfo(idWell)
// TODO Получается только одна категория файлов.
// Поменять при появлении метода получения инфы о конкретном файле
setFile(files.items.find((file) => file.id === idFile) ?? { id: idFile, idWell, name: `File_${idWell}_${idFile}` })
},
null,
() => {
setIsError(true)
return 'Не удалось получить информацию о файле'
},
'Получение информации о файле'
)
}, [idWell, idFile])
const download = useCallback(async () => {
if (!await downloadFile(file))
setIsError(true)
}, [file])
return (
<Result
icon={<InfoCircleFilled style={{ color: '#1890ff' }} />}
title={(
<>
Вы перешли к странице загрузки файла!
<br />
Файл "{file.name ?? ('№' + idFile)}", скважина "{well.caption ?? ('№' + idWell)}".
</>
)}
// subTitle={}
extra={(
<>
<Button type={'ghost'} onClick={() => navigate('/')}>Вернуться на главную</Button>
<Button type={'primary'} onClick={download}>Загрузить</Button>
</>
)}
>
{isError && (
<div className={'desc'}>
<Paragraph>
<Text strong style={{ fontSize: 16 }}>Возможные причины ошибки при попытке скачивания файла:</Text>
</Paragraph>
<Paragraph>
<CloseCircleOutlined style={{ color: 'red' }} />
&nbsp;У вас отсутствует доступ к файлу.&nbsp;
<Typography.Link href={'mailto://support@digitaldrilling.ru'} target={'_blank'}>
Обратиться в поддержку &gt;
</Typography.Link>
</Paragraph>
<Paragraph>
<CloseCircleOutlined style={{ color: 'red' }} />
&nbsp;Файла не существует.&nbsp;
<Link to={'#'} onClick={() => navigate(-1)}>Вернуться назад &gt;</Link>
</Paragraph>
<Paragraph>
<CloseCircleOutlined style={{ color: 'red' }} />
&nbsp;Разрешения не обновились.&nbsp;
<Link to={'/login'}>Перезайти в аккаунт &gt;</Link>
</Paragraph>
</div>
)}
</Result>
)
})
FileDownload.displayName = 'FileDownloadMemo'
export default wrapPrivateComponent(FileDownload, {
requirements: ['File.get'],
route: 'file_download/:idWell/:idFile*',
}, <AccessDenied />)

View File

@ -127,3 +127,18 @@ code {
position: relative;
padding: 16px 0;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.download-link {
height: 32px;
padding: 4px 15px;
}