diff --git a/package-lock.json b/package-lock.json index 5716069..4b077a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22622,15 +22622,6 @@ "@hapi/hoek": "^8.3.0" } }, - "@hypnosphi/create-react-context": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz", - "integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==", - "requires": { - "gud": "^1.0.0", - "warning": "^4.0.3" - } - }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -23188,9 +23179,9 @@ }, "dependencies": { "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", "requires": { "async-limiter": "~1.0.0" } @@ -28261,9 +28252,9 @@ } }, "follow-redirects": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", - "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" }, "for-in": { "version": "1.0.2", @@ -28646,11 +28637,6 @@ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "optional": true }, - "gud": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", - "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" - }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -29049,114 +29035,6 @@ "requires-port": "^1.0.0" } }, - "http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "requires": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -32963,6 +32841,11 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "pigeon-maps": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/pigeon-maps/-/pigeon-maps-0.19.7.tgz", + "integrity": "sha512-8yS5o7lr3mr5674Cfkxrk3EqPiV6WjGBrpVKNn6/40bTdH5qq2NNXK2Iu0fQcDRRZ6mTtXHX0tJAO1tp8ZKBNg==" + }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -33072,11 +32955,6 @@ "ts-pnp": "^1.1.6" } }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" - }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -33103,9 +32981,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -34783,18 +34661,6 @@ "whatwg-fetch": "^3.4.1" } }, - "react-datepicker": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.8.0.tgz", - "integrity": "sha512-iFVNEp8DJoX5yEvEiciM7sJKmLGrvE70U38KhpG13XrulNSijeHw1RZkhd/0UmuXR71dcZB/kdfjiidifstZjw==", - "requires": { - "classnames": "^2.2.6", - "date-fns": "^2.0.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.10.0", - "react-popper": "^1.3.8" - } - }, "react-dev-utils": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", @@ -34921,25 +34787,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "react-onclickoutside": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.10.0.tgz", - "integrity": "sha512-7i2L3ef+0ILXpL6P+Hg304eCQswh4jl3ynwR71BSlMU49PE2uk31k8B2GkP6yE9s2D4jTGKnzuSpzWxu4YxfQQ==" - }, - "react-popper": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", - "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", - "requires": { - "@babel/runtime": "^7.1.2", - "@hypnosphi/create-react-context": "^0.3.1", - "deep-equal": "^1.1.1", - "popper.js": "^1.14.4", - "prop-types": "^15.6.1", - "typed-styles": "^0.0.7", - "warning": "^4.0.2" - } - }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", @@ -35443,9 +35290,9 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "resolve-url-loader": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz", - "integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.4.tgz", + "integrity": "sha512-D3sQ04o0eeQEySLrcz4DsX3saHfsr8/N6tfhblxgZKXxMT2Louargg12oGNfoTRLV09GXhVUe5/qgA5vdgNigg==", "requires": { "adjust-sourcemap-loader": "3.0.0", "camelcase": "5.3.1", @@ -35453,7 +35300,7 @@ "convert-source-map": "1.7.0", "es6-iterator": "2.0.3", "loader-utils": "1.2.3", - "postcss": "7.0.21", + "postcss": "7.0.36", "rework": "1.0.1", "rework-visit": "1.0.0", "source-map": "0.6.1" @@ -35487,28 +35334,10 @@ "json5": "^1.0.1" } }, - "postcss": { - "version": "7.0.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", - "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -37211,9 +37040,9 @@ } }, "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, "tryer": { @@ -37310,11 +37139,6 @@ "mime-types": "~2.1.24" } }, - "typed-styles": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", - "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -38429,6 +38253,17 @@ } } }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -38652,9 +38487,9 @@ } }, "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", "requires": { "async-limiter": "~1.0.0" } @@ -39110,9 +38945,9 @@ } }, "ws": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", - "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index bb45f3e..576e207 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,9 @@ "chartjs-plugin-datalabels": "^2.0.0-rc.1", "chartjs-plugin-zoom": "^1.1.1", "craco-less": "^1.17.1", - "date-fns": "^2.20.0", "moment": "^2.29.1", + "pigeon-maps": "^0.19.7", "react": "^17.0.2", - "react-datepicker": "^3.8.0", "react-dom": "^17.0.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..1f2f141 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -6,16 +6,6 @@ "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" } ], "start_url": ".", diff --git a/src/App.js b/src/App.js index 1f74ae1..032c0f8 100644 --- a/src/App.js +++ b/src/App.js @@ -8,7 +8,7 @@ import Main from './pages/Main' import { OpenAPI } from './services/api' import { PrivateRoute } from './components/PrivateRoute' -OpenAPI.BASE = 'http://localhost:3000' +//OpenAPI.BASE = 'http://localhost:3000' OpenAPI.TOKEN = localStorage['token'] export default function App() { diff --git a/src/components/CementFluid.jsx b/src/components/CementFluid.jsx new file mode 100644 index 0000000..45fa840 --- /dev/null +++ b/src/components/CementFluid.jsx @@ -0,0 +1,106 @@ +let date = new Date().toLocaleString() + +export function CementFluid() { + return (<> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ НаименованиеТемпература, °CПлотность, г/см³Усл. вязкость, секR300R600R3/R6ДНС, дПаПластич. вязкость, сПзСНС, дПаR3/R6 49СДНС 49С, дПаПластич. вязкость 49С, сПзСНС 49С, дПаМВТ, кг/м³Песок, %Фильтрация, см³/30минКорка, ммКТКрНЖесткость, мг/лХлориды, мг/лPfMfPmТвердая фаза раствора, %Смазка, %Карбонат кальция, кг/м³
План                           
Факт                           
+
 
+

{date}

+ + ) +} \ No newline at end of file diff --git a/src/components/CustomColumn.jsx b/src/components/CustomColumn.jsx index c8d5da3..597a2a5 100644 --- a/src/components/CustomColumn.jsx +++ b/src/components/CustomColumn.jsx @@ -1,26 +1,34 @@ import {Display} from './Display' +import RigMnemo from '../components/RigMnemo' + +const params = [ + {label:'Рот., об/мин', accessorName:'rotorSpeed', isArrowVisible:true}, + {label:'Долото, м', accessorName:'bitDepth', isArrowVisible:true, format:2}, + {label:'Забой, м', accessorName:'wellDepth', isArrowVisible:true, format:2}, + {label:'Расход, м³/ч', accessorName:'flow', isArrowVisible:true}, + {label:'Расход х.х., м³/ч', accessorName:'flowIdle', isArrowVisible:true}, + {label: 'Время', accessorName: 'date', format:'HH:mm:ss'}, +] export const CustomColumn = ({data}) => { const dataLast = data[data.length -1] - - const lines = [ - {label:'Рот., об/мин', accessorName:'rotorSpeed'}, - {label:'Долото, м', accessorName:'bitDepth'}, - {label:'Забой, м', accessorName:'wellDepth'}, - {label:'Расход, м³/ч', accessorName:'flow'}, - {label:'Расход х.х., м³/ч', accessorName:'flowIdle'}, - ] if(dataLast) - lines.forEach(line => line.value = dataLast[line.accessorName]?.toPrecision(4)??'-' ) + params.forEach(param => param.value = dataLast[param.accessorName]) else - lines.forEach(line => line.value = '-' ) + params.forEach(param => param.value = '-' ) return (<> - {lines.map(line => )} + {params.map(param => )} + ) } \ No newline at end of file diff --git a/src/components/Display.jsx b/src/components/Display.jsx index 8b0993f..6ba5862 100644 --- a/src/components/Display.jsx +++ b/src/components/Display.jsx @@ -1,43 +1,70 @@ import { useState, useEffect } from 'react'; -import {CaretUpOutlined, CaretDownOutlined} from '@ant-design/icons' +import {CaretUpOutlined, CaretDownOutlined, CaretRightOutlined} from '@ant-design/icons' +import moment from 'moment'; -export const ValueDisplay = ({prefix, value, suffix, isArrowVisible}) =>{ - const [oldVal, setOldVal] = useState(NaN) +export const formatNumber = (value, format) => + Number.isInteger(format) && Number.isFinite(value) + ? (+value).toFixed(format) + : (+value).toPrecision(4) + +export const ValueDisplay = ({prefix, value, suffix, isArrowVisible, format}) =>{ const [val, setVal] = useState('---') - const [arrowState, setArrowState] = useState(0) + const [arrowState, setArrowState] = useState({ + preVal: NaN, + preTimestamp: Date.now(), + direction: 0, + }) useEffect(()=>{ - if(value){ - if(Number.isFinite(+value)){ - if (isArrowVisible) - { - let newArrowState = 0 - if (value > oldVal) - newArrowState = 1 - if (value < oldVal) - newArrowState = -1 - setArrowState(newArrowState) - setOldVal(value) - } - setVal((+value).toPrecision(4)??'---') - } - else - setVal(value) + if(value === undefined || value === null){ + setVal('---') + return } - },[value, isArrowVisible, oldVal]) + if(Number.isFinite(+value)){ + if ((isArrowVisible) && (arrowState.preTimestamp + 1000 < Date.now())) + { + let direction = 0 + if (value > arrowState.preVal) + direction = 1 + if (value < arrowState.preVal) + direction = -1 + + setArrowState({ + preVal: value, + preTimestamp: Date.now(), + direction: direction, + }) + } + + setVal(formatNumber(value, format)) + return + } + + let valueDate = moment(value) + if(valueDate.isValid()){ + setVal(valueDate.format(format)) + return + } + + setVal(value) + },[value, isArrowVisible, arrowState, format]) let arrow = null - switch (arrowState){ - case 1: - arrow = - break - case -1: - arrow = - break - default: - break - } + if(isArrowVisible) + switch (arrowState.direction){ + case 0: + arrow = + break + case 1: + arrow = + break + case -1: + arrow = + break + default: + break + } return({prefix} {val} {suffix}{arrow}) } diff --git a/src/components/Disposition.jsx b/src/components/Disposition.jsx new file mode 100644 index 0000000..b40e30b --- /dev/null +++ b/src/components/Disposition.jsx @@ -0,0 +1,19 @@ +let date = new Date().toLocaleString() + + +export default function Disposition() { + return ( + <> +

Распоряжение

+ +

+ Текст +

+ +

Ф.И.О.

+

Должность

+

Компания

+

{date}

+ + ) +} \ No newline at end of file diff --git a/src/components/Documents.jsx b/src/components/Documents.jsx new file mode 100644 index 0000000..b7cb274 --- /dev/null +++ b/src/components/Documents.jsx @@ -0,0 +1,230 @@ +import {Table, DatePicker, Form, Button, Upload, ConfigProvider} from 'antd' +import { UploadOutlined } from '@ant-design/icons' +import MenuDocuments from "./MenuDocuments" +import { FileService } from '../services/api' +import {useState, useEffect} from "react" +import {useParams} from 'react-router-dom' +import notify from './notify' +import LoaderPortal from './LoaderPortal' +import locale from "antd/lib/locale/ru_RU" +import moment from 'moment' + +const pageSize = 12 +const {RangePicker} = DatePicker; + + +export default function Documents({selectedFileCategory}) { + let {id} = useParams() + + const [page, setPage] = useState(1) + const [range, setRange] = useState([]) + const [pagination, setPagination] = useState(null) + const [files, setFiles] = useState([]) + const [selectedFiles, setSelectedFiles] = useState([]) + const [isTableUpdating, setTableUpdating] = useState(false) + + const [loader, setLoader] = useState(false) + const [form] = Form.useForm(); + + const handleFileNameCLick = async (event, row) => { + const element = event.target + + if(!element.href.length) { + try { + setLoader(true) + + await fetch(`/api/files/${id}/${row.id}`, { + headers: { + Authorization: 'Bearer ' + localStorage['token'] + } + }) + .then(async (response) => { + const blob = await response.blob(); + + let reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onload = function (e) { + element.href = e.target.result + element.click() + }; + setLoader(false) + }); + } catch (error) { + notify(`Не удалось скачать файл ${row}`, 'error') + console.log(error) + } + } + } + + const columns = [ + { + title: 'Документ', + key: 'document', + dataIndex: 'name', + render: (name, row) => + handleFileNameCLick(ev, row)} download={name}>{name} + }, + { + title: 'Дата загрузки', + key: 'uploadDate', + dataIndex: 'uploadDate', + render: (item) => moment.utc(item).local().format('DD MMM YYYY, HH:mm:ss') + }, + { + title: 'Ф.И.О.', + key: 'userName', + dataIndex: 'userName', + } + ]; + + const submitFileFormProps = { + progress: { + strokeColor: { + '0%': '#108ee9', + '100%': '#87d068', + }, + strokeWidth: 3, + format: percent => `${parseFloat(percent.toFixed(2))}%`, + }, + onChange({ file, fileList }) { + if (file.status !== 'uploading') { + setSelectedFiles(fileList) + } + } + } + + const onChangeRange = (range) => { + setRange(range) + } + + const onFinish = (values, form) => { + var fileList = values.fileInput.fileList + + if (fileList.length > 0) + { + setLoader(true) + const formData = new FormData(); + + fileList.forEach(val => { + formData.append('files', val.originFileObj) + }) + + fetch(`/api/files/${id}/files?idCategory=${selectedFileCategory}&idUser=${localStorage['userId']}`, { + headers: { + Authorization: 'Bearer ' + localStorage['token'] + }, + method: 'POST', + body: formData + }) + .then(async (response) => { + setLoader(false) + form.resetFields() + setTableUpdating(true) + }); + } + } + + const onFinishFailed = (errorInfo) => { + notify(`Не удалось отправить файлы по скважине "${id}".`, 'error') + } + + useEffect(() => { + const GetDocuments = async () => { + setLoader(true) + + try { + let begin = null + let end = null + if (range?.length > 1) { + begin = range[0].toISOString() + end = range[1].toISOString() + } + + await FileService.getFilesInfo( + `${id}`, + (page - 1) * pageSize, + pageSize, + selectedFileCategory, + begin, + end + ).then((paginatedFiles) => { + setFiles(paginatedFiles?.items.map(f => { + return { + key: f.id, + begin: f.date, + ...f + } + })) + + setPagination({ + total: paginatedFiles?.count, + current: Math.floor(paginatedFiles?.skip / pageSize), + }) + + setTableUpdating(false) + setLoader(false) + } + ) + } catch (ex) { + notify(`Не удалось загрузить файлы по скважине "${id}"`, 'error') + console.log(ex) + } + } + GetDocuments() + }, [id, range,page, selectedFileCategory, isTableUpdating]) + + return ( +
+ +
+

Фильтр документов:

+ + + +
+ +
 
+
onFinish(values, form)} + onFinishFailed={onFinishFailed} + style={{width: '300px'}} + > + + + + + + + + +
+
 
+ setPage(page) + }} + rowKey={(record) => record.id} + /> + ); +} \ No newline at end of file diff --git a/src/components/LayoutPortal.jsx b/src/components/LayoutPortal.jsx new file mode 100644 index 0000000..d6cc868 --- /dev/null +++ b/src/components/LayoutPortal.jsx @@ -0,0 +1,20 @@ +import {Layout} from 'antd' +import PageHeader from './PageHeader' + +const {Content} = Layout + +export default function LayoutPortal({title, noSheet, children}) { + const content = noSheet + ? {children} + : + + {children} + + + + return ( + + + {content} + ) +} \ No newline at end of file diff --git a/src/components/MenuDocuments.jsx b/src/components/MenuDocuments.jsx new file mode 100644 index 0000000..8aa1ad9 --- /dev/null +++ b/src/components/MenuDocuments.jsx @@ -0,0 +1,50 @@ +import {Menu} from "antd"; +import {FolderOutlined} from "@ant-design/icons"; +import {Link} from "react-router-dom"; +import {useState} from "react" + + +export default function MenuDocuments() { + + const [selectedItem, setSelectedItem] = useState(1) + + const handleClick = e => { + setSelectedItem({ current: e.key }); + }; + + return( + <> + + }> + Растворный сервис + + }> + Цементирование + + }> + ННБ + + }> + ГТИ + + }> + Документы по скважине + + }> + Супервайзер + + }> + Мастер + + }> + Последние данные + + + ) +} diff --git a/src/components/NnbTable.jsx b/src/components/NnbTable.jsx new file mode 100644 index 0000000..978e7c6 --- /dev/null +++ b/src/components/NnbTable.jsx @@ -0,0 +1,250 @@ +let date = new Date().toLocaleString() + +export function NnbTable() { + return (<> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Глубина по + стволу, мЗенитный + угол, градАзимут + магнитный, градАзимут + истинный, градАзимут + дирекц., градГлубина по + вертикали, мАбсолютная + отметка, мЛок. + смещение к северу, мЛок. + смещение к востоку, мОтклонение + от устья, мАзимут + смещения, градОтклонение + от устья, мПространст. + интенсивность, град/10 мУгол + установки отклон., градИнтенсив. + по зениту, град/10 мКомментарийРазница вертикальных глубин + между ХХХ (план) и ХХХ (факт)Расстояние в пространстве между + ХХХ (план) и ХХХ (факт)


















+
 
+

{date}

+ ) +} \ No newline at end of file diff --git a/src/pages/Header.jsx b/src/components/PageHeader.jsx similarity index 84% rename from src/pages/Header.jsx rename to src/components/PageHeader.jsx index 854ca55..f8b82cc 100644 --- a/src/pages/Header.jsx +++ b/src/components/PageHeader.jsx @@ -2,7 +2,7 @@ import { Layout, Button } from 'antd' import { UserOutlined } from '@ant-design/icons' import logo from '../images/logo_32.png' import { Link } from "react-router-dom" -import WellTreeSelector from '../components/WellTreeSelector' +import WellTreeSelector from './WellTreeSelector' const { Header } = Layout @@ -17,10 +17,11 @@ export default function PageHeader({title='Мониторинг', wellsList}){ return(
- АСБ + + АСБ +

{title}

-
 
) + }, + { + title: 'Таблица по операциям', + render: _ => () + }, + { + title: 'Подрядчики', + key: 'companies', + dataIndex: 'companies', + render: (item) => item.map(company => {company.caption}) + }, +]; + +export default function Cluster() { + let { id } = useParams() + const [clusterTitle, setClusterTitle] = useState("") + const [wellsStat, setWellsStat] = useState(null) + const [showLoader, setShowLoader] = useState(false) + + useEffect(()=>{ + const updateWellsStat = async() => { + setShowLoader(true) + try{ + const msInDay = 1000*60*60*24 + const data = await ClusterService.getStat(id) + const wellsStat = data.wellsStat.map(w=>({...w, + periodPlan: (new Date(w.planEnd) - new Date(w.planStart))/msInDay, + periodFact: (new Date(w.factEnd) - new Date(w.factStart))/msInDay, + })) + setWellsStat(wellsStat) + setClusterTitle(data.caption) + } + catch(ex) { + notify(`Не удалось загрузить статистику по скважинам куста "${id}"`, 'error') + console.log(ex) + } + setShowLoader(false) + } + updateWellsStat() + },[id]) + + return( + +

{clusterTitle}

+ record.id} + /> + ) +} \ No newline at end of file diff --git a/src/pages/Deposit.jsx b/src/pages/Deposit.jsx new file mode 100644 index 0000000..26818fb --- /dev/null +++ b/src/pages/Deposit.jsx @@ -0,0 +1,74 @@ +import { Map, Overlay } from "pigeon-maps" +import pointer from '../images/pointer.svg' +import {Link} from "react-router-dom"; +import LoaderPortal from '../components/LoaderPortal' +import { useState, useEffect } from "react"; +import {ClusterService} from '../services/api' +import notify from '../components/notify' + +const calcViewParams = (clusters) => { + if ((!clusters) || clusters.length === 0) + return {center:[60.81226, 70.0562], zoom: 5} + + const center = clusters.reduce((sum, cluster) => { + sum[0] += (cluster.latitude / clusters.length) + sum[1] += (cluster.longitude / clusters.length) + return sum + }, [0, 0]) + + const maxDeg = clusters.reduce((max, cluster) => { + const dLatitude = Math.abs(center[0] - cluster.latitude) + const dLongitude = Math.abs(center[1] - cluster.longitude) + const d = dLatitude > dLongitude ? dLatitude : dLongitude + return d > max ? d : max + }, 0) + + return {center, zoom: maxDeg*25} +} + +export default function Deposit() { + const [clustersData, setClustersData] = useState([]) + const [showLoader, setShowLoader] = useState(false) + + useEffect(()=>{ + const updateClusters = async()=>{ + setShowLoader(true) + try{ + const data = await ClusterService.getClusters() + setClustersData(data) + } + catch(ex) { + notify(`Не удалось загрузить список кустов`, 'error') + console.log(ex) + } + setShowLoader(false) + } + updateClusters() + }, []) + + const viewParams = calcViewParams(clustersData) + + const markers = clustersData.map(cluster => + + + + + {cluster.caption} + + + ) + + return ( + + + {markers} + + + ); +} diff --git a/src/pages/FluidService.jsx b/src/pages/FluidService.jsx new file mode 100644 index 0000000..2022289 --- /dev/null +++ b/src/pages/FluidService.jsx @@ -0,0 +1,8 @@ +import Documents from "../components/Documents" + +export default function FluidService({selectedFileCategory}) { + + return( + + ) +} \ No newline at end of file diff --git a/src/pages/LastData.jsx b/src/pages/LastData.jsx new file mode 100644 index 0000000..a331594 --- /dev/null +++ b/src/pages/LastData.jsx @@ -0,0 +1,94 @@ +import {Button, Modal, Checkbox } from "antd"; +import {CementFluid} from "../components/CementFluid"; +import React, {useState} from "react"; +import {Sludge} from "../components/Sludge"; +import {NnbTable} from "../components/NnbTable" +import Disposition from "../components/Disposition"; +import MenuDocuments from "../components/MenuDocuments"; + + +export default function LastData() { + const [tableVisible, setTableVisible] = useState(false) + const [tableSludgeVisible, setTableSludgeVisible] = useState(false) + const [tableNNBVisible, setTableNNBVisible] = useState(false) + const [dispositionVisible, setDispositionVisible] = useState(false) + + return ( + <> +
+ +
+
 
+ + setTableVisible(false)} + onCancel={() => setTableVisible(false)} + width={1800} + okText='Ок' + cancelText='Отмена' + > + + + + setTableSludgeVisible(false)} + onCancel={() => setTableSludgeVisible(false)} + width={1600} + okText='Ок' + cancelText='Отмена' + > + + + + setTableNNBVisible(false)} + onCancel={() => setTableNNBVisible(false)} + width={1400} + okText='Ок' + cancelText='Отмена' + > + + + + setDispositionVisible(false)} + onCancel={() => setDispositionVisible(false)} + width={850} + okText='Ок' + cancelText='Отмена' + footer={[ + Принять распоряжение, + , + + ]} + > + + + ) +} \ No newline at end of file diff --git a/src/pages/LayoutPortal.jsx b/src/pages/LayoutPortal.jsx deleted file mode 100644 index b1ff72e..0000000 --- a/src/pages/LayoutPortal.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import {Layout} from 'antd' -import PageHeader from './Header' - -const {Content} = Layout - -export default function LayoutPortal({title, children}) { - return ( - - - - - {children} - - - ) -} \ No newline at end of file diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx index a604aa6..8675561 100644 --- a/src/pages/Login.jsx +++ b/src/pages/Login.jsx @@ -17,6 +17,7 @@ const openNotificationError = (message, title) => { const setUser = (user) =>{ OpenAPI.TOKEN = user.token + localStorage['userId'] = user.id localStorage['token'] = user.token localStorage['login'] = user.login } diff --git a/src/pages/Main.jsx b/src/pages/Main.jsx index adf515f..4fbbac8 100644 --- a/src/pages/Main.jsx +++ b/src/pages/Main.jsx @@ -1,25 +1,31 @@ -import Wells from './Wells' -import Well from "../components/Well"; -import LayoutPortal from './LayoutPortal' +import Deposit from './Deposit' +import Cluster from './Cluster' +import Well from "./Well"; +import LayoutPortal from '../components/LayoutPortal' import {Redirect, Route, Switch} from "react-router-dom"; export default function Main() { - return ( - - - - - - - - - - - - - - - + return ( + + + + + + + + + + + + + + + + + + + + ) } diff --git a/src/pages/Messages.jsx b/src/pages/Messages.jsx index ad5940a..9a37f56 100644 --- a/src/pages/Messages.jsx +++ b/src/pages/Messages.jsx @@ -117,7 +117,7 @@ export default function Messages() { return ( <>
-

Фильтр сообщений

+

Фильтр сообщений

+ {children} + + + + +
+ +
setPage(page) + }} + rowKey={(record) => record.id} + /> + + ) + } \ No newline at end of file diff --git a/src/pages/Wells.jsx b/src/pages/Wells.jsx deleted file mode 100644 index 4bf4e9a..0000000 --- a/src/pages/Wells.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useState, useEffect } from 'react' -import { WellService } from '../services/api' -import LoaderPortal from '../components/LoaderPortal' -import { Table } from 'antd' // TreeSelect -import { useHistory } from 'react-router-dom' -import notify from '../components/notify' - -const columns = [ - { - title: 'Месторождение', - dataIndex: 'deposit', - key: 'deposit', - }, - { - title: 'Куст', - dataIndex: 'cluster', - key: 'cluster', - }, - { - title: 'Скважина', - dataIndex: 'caption', - key: 'caption', - }, - { - title: 'Данные', - dataIndex: 'lastData', - key: 'lastData', - }, -]; - -export default function Wells(props){ - const [wells, setWells] = useState([]) - const [loader, setLoader] = useState(false) - const history = useHistory() - - const updateWellsList = async () => { - setLoader(true) - try{ - let newWells = (await WellService.getWells()).map(w =>{return {key:w.id, ...w}}) - console.log(newWells) - setWells( newWells ) - } - catch(e){ - notify('Не удалось загрузить список скважин', 'error') - console.error(`${e}`); - } - setLoader(false) - } - - useEffect(()=>updateWellsList(), []) - - return(<> -

Скважины

- -
{ - return { - onClick: event => {history.push(`/well/${record.id}/`)}, - }; - }}/> - - ) -} \ No newline at end of file diff --git a/src/services/api/index.ts b/src/services/api/index.ts index 619b824..18cdace 100644 --- a/src/services/api/index.ts +++ b/src/services/api/index.ts @@ -5,11 +5,19 @@ export { ApiError } from './core/ApiError'; export { OpenAPI } from './core/OpenAPI'; export type { AuthDto } from './models/AuthDto'; +export type { ClusterDto } from './models/ClusterDto'; +export type { ClusterStatDto } from './models/ClusterStatDto'; +export type { CompanyDto } from './models/CompanyDto'; export type { DataSaubBaseDto } from './models/DataSaubBaseDto'; export type { DatesRangeDto } from './models/DatesRangeDto'; +export type { DepositDto } from './models/DepositDto'; export type { EventDto } from './models/EventDto'; +export type { FilePropertiesDto } from './models/FilePropertiesDto'; +export type { FilePropertiesDtoPaginationContainer } from './models/FilePropertiesDtoPaginationContainer'; export type { MessageDto } from './models/MessageDto'; export type { MessageDtoPaginationContainer } from './models/MessageDtoPaginationContainer'; +export type { OperationDto } from './models/OperationDto'; +export type { OperationDtoPaginationContainer } from './models/OperationDtoPaginationContainer'; export type { OperationDurationDto } from './models/OperationDurationDto'; export type { TelemetryInfoDto } from './models/TelemetryInfoDto'; export type { TelemetryMessageDto } from './models/TelemetryMessageDto'; @@ -18,10 +26,15 @@ export type { UserTokenDto } from './models/UserTokenDto'; export type { WellDepthToDayDto } from './models/WellDepthToDayDto'; export type { WellDepthToIntervalDto } from './models/WellDepthToIntervalDto'; export type { WellDto } from './models/WellDto'; +export type { WellSectionDto } from './models/WellSectionDto'; +export type { WellStatDto } from './models/WellStatDto'; export { AnalyticsService } from './services/AnalyticsService'; export { AuthService } from './services/AuthService'; +export { ClusterService } from './services/ClusterService'; export { DataService } from './services/DataService'; +export { DepositService } from './services/DepositService'; +export { FileService } from './services/FileService'; export { MessageService } from './services/MessageService'; export { ReportService } from './services/ReportService'; export { TelemetryService } from './services/TelemetryService'; diff --git a/src/services/api/models/ClusterDto.ts b/src/services/api/models/ClusterDto.ts new file mode 100644 index 0000000..ec20834 --- /dev/null +++ b/src/services/api/models/ClusterDto.ts @@ -0,0 +1,14 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { WellDto } from './WellDto'; + +export type ClusterDto = { + id?: number; + caption?: string | null; + description?: string | null; + latitude?: number | null; + longitude?: number | null; + wells?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/models/ClusterStatDto.ts b/src/services/api/models/ClusterStatDto.ts new file mode 100644 index 0000000..911a264 --- /dev/null +++ b/src/services/api/models/ClusterStatDto.ts @@ -0,0 +1,16 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { WellDto } from './WellDto'; +import type { WellStatDto } from './WellStatDto'; + +export type ClusterStatDto = { + id?: number; + caption?: string | null; + description?: string | null; + latitude?: number | null; + longitude?: number | null; + wells?: Array | null; + wellsStat?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/models/CompanyDto.ts b/src/services/api/models/CompanyDto.ts new file mode 100644 index 0000000..fcd415a --- /dev/null +++ b/src/services/api/models/CompanyDto.ts @@ -0,0 +1,9 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type CompanyDto = { + id?: number; + caption?: string | null; + companyType?: string | null; +} \ No newline at end of file diff --git a/src/services/api/models/DataSaubBaseDto.ts b/src/services/api/models/DataSaubBaseDto.ts index 0a9e94f..e12e1c5 100644 --- a/src/services/api/models/DataSaubBaseDto.ts +++ b/src/services/api/models/DataSaubBaseDto.ts @@ -38,4 +38,6 @@ export type DataSaubBaseDto = { flow?: number | null; flowIdle?: number | null; flowDeltaLimitMax?: number | null; + idFeedRegulator?: number | null; + mseState?: number | null; } \ No newline at end of file diff --git a/src/services/api/models/DepositDto.ts b/src/services/api/models/DepositDto.ts new file mode 100644 index 0000000..c142448 --- /dev/null +++ b/src/services/api/models/DepositDto.ts @@ -0,0 +1,14 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ClusterDto } from './ClusterDto'; + +export type DepositDto = { + id?: number; + caption?: string | null; + description?: string | null; + latitude?: number | null; + longitude?: number | null; + clusters?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/models/FilePropertiesDto.ts b/src/services/api/models/FilePropertiesDto.ts new file mode 100644 index 0000000..59ed185 --- /dev/null +++ b/src/services/api/models/FilePropertiesDto.ts @@ -0,0 +1,11 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type FilePropertiesDto = { + id?: number; + name?: string | null; + idCategory?: number; + uploadDate?: string; + userName?: string | null; +} \ No newline at end of file diff --git a/src/services/api/models/FilePropertiesDtoPaginationContainer.ts b/src/services/api/models/FilePropertiesDtoPaginationContainer.ts new file mode 100644 index 0000000..b2226ef --- /dev/null +++ b/src/services/api/models/FilePropertiesDtoPaginationContainer.ts @@ -0,0 +1,12 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { FilePropertiesDto } from './FilePropertiesDto'; + +export type FilePropertiesDtoPaginationContainer = { + skip?: number; + take?: number; + count?: number; + items?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/models/OperationDto.ts b/src/services/api/models/OperationDto.ts new file mode 100644 index 0000000..9481988 --- /dev/null +++ b/src/services/api/models/OperationDto.ts @@ -0,0 +1,12 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type OperationDto = { + id?: number; + name?: string | null; + beginDate?: string; + endDate?: string; + startWellDepth?: number; + endWellDepth?: number; +} \ No newline at end of file diff --git a/src/services/api/models/OperationDtoPaginationContainer.ts b/src/services/api/models/OperationDtoPaginationContainer.ts new file mode 100644 index 0000000..64fcf00 --- /dev/null +++ b/src/services/api/models/OperationDtoPaginationContainer.ts @@ -0,0 +1,12 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { OperationDto } from './OperationDto'; + +export type OperationDtoPaginationContainer = { + skip?: number; + take?: number; + count?: number; + items?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/models/OperationDurationDto.ts b/src/services/api/models/OperationDurationDto.ts index 7f061a0..5be7a04 100644 --- a/src/services/api/models/OperationDurationDto.ts +++ b/src/services/api/models/OperationDurationDto.ts @@ -3,6 +3,6 @@ /* eslint-disable */ export type OperationDurationDto = { - processName?: string | null; + operationName?: string | null; duration?: number; } \ No newline at end of file diff --git a/src/services/api/models/UserTokenDto.ts b/src/services/api/models/UserTokenDto.ts index 9b4db8f..1439c28 100644 --- a/src/services/api/models/UserTokenDto.ts +++ b/src/services/api/models/UserTokenDto.ts @@ -9,7 +9,7 @@ export type UserTokenDto = { surname?: string | null; patronymic?: string | null; id?: number; - customerName?: string | null; + companyName?: string | null; roleName?: string | null; token?: string | null; } \ No newline at end of file diff --git a/src/services/api/models/WellDto.ts b/src/services/api/models/WellDto.ts index c161219..d681ec5 100644 --- a/src/services/api/models/WellDto.ts +++ b/src/services/api/models/WellDto.ts @@ -7,5 +7,7 @@ export type WellDto = { cluster?: string | null; deposit?: string | null; id?: number; - lastData?: any; + latitude?: number | null; + longitude?: number | null; + wellType?: string | null; } \ No newline at end of file diff --git a/src/services/api/models/WellSectionDto.ts b/src/services/api/models/WellSectionDto.ts new file mode 100644 index 0000000..684e7e5 --- /dev/null +++ b/src/services/api/models/WellSectionDto.ts @@ -0,0 +1,21 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type WellSectionDto = { + sectionType?: string | null; + wellDepthPlan?: number; + wellDepthFact?: number; + buildDaysPlan?: number; + buildDaysFact?: number; + rateOfPenetrationPlan?: number; + rateOfPenetrationFact?: number; + routeSpeedPlan?: number; + routeSpeedFact?: number; + bhaUpSpeedPlan?: number; + bhaUpSpeedFact?: number; + bhaDownSpeedPlan?: number; + bhaDownSpeedFact?: number; + casingDownSpeedPlan?: number; + casingDownSpeedFact?: number; +} \ No newline at end of file diff --git a/src/services/api/models/WellStatDto.ts b/src/services/api/models/WellStatDto.ts new file mode 100644 index 0000000..7293b43 --- /dev/null +++ b/src/services/api/models/WellStatDto.ts @@ -0,0 +1,27 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { CompanyDto } from './CompanyDto'; +import type { WellSectionDto } from './WellSectionDto'; + +export type WellStatDto = { + caption?: string | null; + cluster?: string | null; + deposit?: string | null; + id?: number; + latitude?: number | null; + longitude?: number | null; + wellType?: string | null; + planStart?: string | null; + planEnd?: string | null; + factStart?: string | null; + factEnd?: string | null; + unProductiveDays?: number | null; + rateOfPenetrationPlan?: number | null; + rateOfPenetrationFact?: number | null; + routeSpeedPlan?: number | null; + routeSpeedFact?: number | null; + sections?: Array | null; + companies?: Array | null; +} \ No newline at end of file diff --git a/src/services/api/services/AnalyticsService.ts b/src/services/api/services/AnalyticsService.ts index e9d0d87..8c52822 100644 --- a/src/services/api/services/AnalyticsService.ts +++ b/src/services/api/services/AnalyticsService.ts @@ -1,6 +1,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { OperationDtoPaginationContainer } from '../models/OperationDtoPaginationContainer'; import type { OperationDurationDto } from '../models/OperationDurationDto'; import type { WellDepthToDayDto } from '../models/WellDepthToDayDto'; import type { WellDepthToIntervalDto } from '../models/WellDepthToIntervalDto'; @@ -8,6 +9,39 @@ import { request as __request } from '../core/request'; export class AnalyticsService { + /** + * Возвращает список операций на скважине за все время + * @param wellId id скважины + * @param skip для пагинации кол-во записей пропустить + * @param take для пагинации кол-во записей + * @param categoryIds список категорий + * @param begin дата начала + * @param end окончание + * @returns OperationDtoPaginationContainer Success + * @throws ApiError + */ + public static async getOperationsByWell( +wellId: number, +skip: number, +take: number = 32, +categoryIds?: Array, +begin?: string, +end?: string, +): Promise { + const result = await __request({ + method: 'GET', + path: `/api/analytics/${wellId}/operationsByWell`, + query: { + 'skip': skip, + 'take': take, + 'categoryIds': categoryIds, + 'begin': begin, + 'end': end, + }, + }); + return result.body; + } + /** * Возвращает данные по скважине "глубина-день" * @param wellId id скважины @@ -27,22 +61,22 @@ wellId: number, /** * Возвращает данные по глубине скважины за период * @param wellId id скважины - * @param intervalHoursTimestamp количество секунд в необходимом интервале времени - * @param workBeginTimestamp количество секунд в времени начала смены + * @param intervalSeconds количество секунд в необходимом интервале времени + * @param workBeginSeconds количество секунд в времени начала смены * @returns WellDepthToIntervalDto Success * @throws ApiError */ public static async getWellDepthToInterval( wellId: number, -intervalHoursTimestamp?: number, -workBeginTimestamp?: number, +intervalSeconds?: number, +workBeginSeconds?: number, ): Promise> { const result = await __request({ method: 'GET', path: `/api/analytics/${wellId}/wellDepthToInterval`, query: { - 'intervalHoursTimestamp': intervalHoursTimestamp, - 'workBeginTimestamp': workBeginTimestamp, + 'intervalSeconds': intervalSeconds, + 'workBeginSeconds': workBeginSeconds, }, }); return result.body; @@ -75,22 +109,22 @@ end?: string, /** * Возвращает детальные данные по операциям на скважине за период * @param wellId id скважины - * @param intervalHoursTimestamp количество секунд в необходимом интервале времени - * @param workBeginTimestamp количество секунд в времени начала смены + * @param intervalSeconds количество секунд в необходимом интервале времени + * @param workBeginSeconds количество секунд в времени начала смены * @returns OperationDurationDto Success * @throws ApiError */ public static async getOperationsToInterval( wellId: number, -intervalHoursTimestamp?: number, -workBeginTimestamp?: number, +intervalSeconds?: number, +workBeginSeconds?: number, ): Promise> { const result = await __request({ method: 'GET', path: `/api/analytics/${wellId}/operationsToInterval`, query: { - 'intervalHoursTimestamp': intervalHoursTimestamp, - 'workBeginTimestamp': workBeginTimestamp, + 'intervalSeconds': intervalSeconds, + 'workBeginSeconds': workBeginSeconds, }, }); return result.body; diff --git a/src/services/api/services/ClusterService.ts b/src/services/api/services/ClusterService.ts new file mode 100644 index 0000000..da970cc --- /dev/null +++ b/src/services/api/services/ClusterService.ts @@ -0,0 +1,56 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ClusterDto } from '../models/ClusterDto'; +import type { ClusterStatDto } from '../models/ClusterStatDto'; +import type { WellDto } from '../models/WellDto'; +import { request as __request } from '../core/request'; + +export class ClusterService { + + /** + * Получает список доступных пользователю кустов + * @returns ClusterDto Success + * @throws ApiError + */ + public static async getClusters(): Promise> { + const result = await __request({ + method: 'GET', + path: `/api/cluster`, + }); + return result.body; + } + + /** + * Получение доступных пользователю скважин + * @param idCluster + * @returns WellDto Success + * @throws ApiError + */ + public static async getWells( +idCluster: number, +): Promise> { + const result = await __request({ + method: 'GET', + path: `/api/cluster/${idCluster}`, + }); + return result.body; + } + + /** + * Получение обопщенной статистики по кусту (лучшая/худшая скважина) + * @param idCluster + * @returns ClusterStatDto Success + * @throws ApiError + */ + public static async getStat( +idCluster: number, +): Promise { + const result = await __request({ + method: 'GET', + path: `/api/cluster/${idCluster}/Stat`, + }); + return result.body; + } + +} \ No newline at end of file diff --git a/src/services/api/services/DataService.ts b/src/services/api/services/DataService.ts index fa8fc17..38d648a 100644 --- a/src/services/api/services/DataService.ts +++ b/src/services/api/services/DataService.ts @@ -13,7 +13,7 @@ export class DataService { * @param wellId id скважины * @param begin дата начала выборки. По умолчанию: текущее время - intervalSec * @param intervalSec интервал времени даты начала выборки, секунды - * @param approxPointsCount желаемое количество точек. Если в выборке точек будет больше, то выборка будет прорежена. + * @param approxPointsCount жела��мое количество точек. Если в выборке точек будет больше, то выборка будет прорежена. * @returns DataSaubBaseDto Success * @throws ApiError */ diff --git a/src/services/api/services/DepositService.ts b/src/services/api/services/DepositService.ts new file mode 100644 index 0000000..ca61820 --- /dev/null +++ b/src/services/api/services/DepositService.ts @@ -0,0 +1,39 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ClusterDto } from '../models/ClusterDto'; +import type { DepositDto } from '../models/DepositDto'; +import { request as __request } from '../core/request'; + +export class DepositService { + + /** + * Получает список доступных пользователю месторождений + * @returns DepositDto Success + * @throws ApiError + */ + public static async getDeposits(): Promise> { + const result = await __request({ + method: 'GET', + path: `/api/deposit`, + }); + return result.body; + } + + /** + * Получает список доступных пользователю кустов месторождения + * @param depositId + * @returns ClusterDto Success + * @throws ApiError + */ + public static async getClusters( +depositId: number, +): Promise> { + const result = await __request({ + method: 'GET', + path: `/api/deposit/${depositId}`, + }); + return result.body; + } + +} \ No newline at end of file diff --git a/src/services/api/services/FileService.ts b/src/services/api/services/FileService.ts new file mode 100644 index 0000000..60af0b4 --- /dev/null +++ b/src/services/api/services/FileService.ts @@ -0,0 +1,87 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { FilePropertiesDtoPaginationContainer } from '../models/FilePropertiesDtoPaginationContainer'; +import { request as __request } from '../core/request'; + +export class FileService { + + /** + * Сохраняет переданные файлы и информацию о них + * @param wellId id скважины + * @param idCategory id категории файла + * @param idUser id отправившего файл пользователя + * @param requestBody + * @returns number Success + * @throws ApiError + */ + public static async saveFiles( +wellId: number, +idCategory?: number, +idUser?: number, +requestBody?: any, +): Promise { + const result = await __request({ + method: 'POST', + path: `/api/files/${wellId}/files`, + query: { + 'idCategory': idCategory, + 'idUser': idUser, + }, + body: requestBody, + }); + return result.body; + } + + /** + * Возвращает информацию о файлах для сква��ины в выбраной категории + * @param wellId id скважины + * @param skip для пагинации кол-во записей пропустить + * @param take для пагинации кол-во записей взять + * @param idCategory id категории файла + * @param begin дата начала + * @param end дата окончания + * @returns FilePropertiesDtoPaginationContainer Success + * @throws ApiError + */ + public static async getFilesInfo( +wellId: number, +skip: number, +take: number = 32, +idCategory: number, +begin?: string, +end?: string, +): Promise { + const result = await __request({ + method: 'GET', + path: `/api/files/${wellId}`, + query: { + 'skip': skip, + 'take': take, + 'idCategory': idCategory, + 'begin': begin, + 'end': end, + }, + }); + return result.body; + } + + /** + * Возвращает файл с диска на сервере + * @param wellId id скважины + * @param fileId id запрашиваемого файла + * @returns string Success + * @throws ApiError + */ + public static async getFile( +wellId: number, +fileId: number, +): Promise { + const result = await __request({ + method: 'GET', + path: `/api/files/${wellId}/${fileId}`, + }); + return result.body; + } + +} \ No newline at end of file diff --git a/src/services/api/services/ReportService.ts b/src/services/api/services/ReportService.ts index e63a83e..e02c282 100644 --- a/src/services/api/services/ReportService.ts +++ b/src/services/api/services/ReportService.ts @@ -116,7 +116,7 @@ end?: string, } /** - * Возвращает даты самого старого и самого свежего отчетов в БД + * Возвра��ает даты самого старого и самого свежего отчетов в БД * @param wellId id скважины * @returns DatesRangeDto Success * @throws ApiError diff --git a/src/services/signalr/index.ts b/src/services/signalr/index.ts index 02aad65..72ed2fb 100644 --- a/src/services/signalr/index.ts +++ b/src/services/signalr/index.ts @@ -12,16 +12,21 @@ type ConnectionsDict = { [route: string]: HubConnection; }; +//var baseUrl = `http://192.168.1.70:5000` +var baseUrl = process.env.NODE_ENV === 'development' + ?'http://192.168.1.70:5000' + :'' + const Connections: ConnectionsDict = { 'hubs/telemetry': new HubConnectionBuilder() - .withUrl(`http://192.168.1.70:5000/hubs/telemetry`, ConnectionOptions) - .withAutomaticReconnect() - .build(), + .withUrl(`${baseUrl}/hubs/telemetry`, ConnectionOptions)// + .withAutomaticReconnect() + .build(), 'hubs/reports': new HubConnectionBuilder() - .withUrl(`http://192.168.1.70:5000/hubs/reports`, ConnectionOptions) - .withAutomaticReconnect() - .build() + .withUrl(`${baseUrl}/hubs/reports`, ConnectionOptions) + .withAutomaticReconnect() + .build() } let connectionPromise: Promise @@ -43,6 +48,21 @@ type handlerFunction = (...args: any[]) => void; type cleanFunction = (...args: any[]) => void; +const MakeUnsubscribeFunction = ( + connection: HubConnection, + methodName: string, + groupName: (string|null)):cleanFunction => { + return async() => { + if(connection.state === HubConnectionState.Connected) + { + if(groupName) + await connection.send('RemoveFromGroup', groupName) + connection.off(methodName) + } + connection.stop() + } +} + /** Subscribe on some SignalR method (topic). * @example useEffect(() => Subscribe('methodName', `${id}`, handleNewData), [id]); * @param {string} methodName name of the method @@ -61,12 +81,7 @@ const Subscribe = ( connection.on(methodName, handler) }) - if(groupName) - return () => { - Connections[hubUrl].send('RemoveFromGroup', groupName) - .finally(()=>Connections[hubUrl].off(methodName)) - } - return () => Connections[hubUrl].off(methodName) + return MakeUnsubscribeFunction(Connections[hubUrl],methodName,groupName) } /** Invokes some SignalR method. diff --git a/src/styles/App.less b/src/styles/App.less index 1ed41b2..25c6ad0 100644 --- a/src/styles/App.less +++ b/src/styles/App.less @@ -163,6 +163,7 @@ tr.table_row_size { } .header-tree-select{ + width: 300px; border: 1px solid rgba(255, 255, 255, 0.2); background-color: rgba(0, 0, 0, 0.3); } diff --git a/src/styles/index.css b/src/styles/index.css index 8d31ab7..9a60f46 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -48,3 +48,11 @@ code { monospace; } +.linkDocuments { + color: #000; +} + +.linkDocuments:hover { + color: #c32828; +} + diff --git a/src/styles/message.css b/src/styles/message.css index fb003b0..cd0e395 100644 --- a/src/styles/message.css +++ b/src/styles/message.css @@ -33,7 +33,7 @@ margin: 0 0 5px 0; } -.filter-group__heading { +.filter-group-heading { margin: 5px auto; align-items: center; }