Commit 548b5799 authored by Matija Obreza's avatar Matija Obreza

Merge branch '322-admin-bulk-ops' into 'master'

Resolve "Admin bulk ops"

Closes #322

See merge request genesys-pgr/genesys-server!216
parents 8e3ee85b 427d6f17
......@@ -7,7 +7,7 @@
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=",
"dev": true
},
"accepts": {
......@@ -34,7 +34,7 @@
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
......@@ -181,7 +181,7 @@
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
......@@ -255,7 +255,7 @@
"chalk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
......@@ -363,7 +363,7 @@
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
......@@ -454,7 +454,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"dev": true,
"requires": {
"ms": "2.0.0"
......@@ -578,7 +578,7 @@
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=",
"requires": {
"is-arrayish": "^0.2.1"
}
......@@ -750,7 +750,7 @@
"gaze": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
"integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
"integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=",
"dev": true,
"requires": {
"globule": "^1.0.0"
......@@ -759,7 +759,7 @@
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
"integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o="
},
"get-stdin": {
"version": "4.0.1",
......@@ -790,7 +790,7 @@
"globule": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
"integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
"integrity": "sha1-Xf+xsZHyLSB5epNptJ6rTpg5aW0=",
"dev": true,
"requires": {
"glob": "~7.1.1",
......@@ -815,7 +815,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
}
}
......@@ -828,7 +828,7 @@
"grunt": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz",
"integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==",
"integrity": "sha1-s8mSYMUdG0KDV2bnllJ7YPe7o3Q=",
"dev": true,
"requires": {
"coffeescript": "~1.10.0",
......@@ -1058,7 +1058,7 @@
"grunt-contrib-cssmin": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-2.2.1.tgz",
"integrity": "sha512-IXNomhQ5ekVZbDbj/ik5YccoD9khU6LT2fDXqO1+/Txjq8cp0tQKjVS8i8EAbHOrSDkL7/UD6A7b+xj98gqh9w==",
"integrity": "sha1-ZMvr5gE0vBJwykFUUU7EAHzBb38=",
"dev": true,
"requires": {
"chalk": "^1.0.0",
......@@ -1238,7 +1238,7 @@
"grunt-contrib-watch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz",
"integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==",
"integrity": "sha1-wUPKW4JLKIoCS4VmOaU0Wu23jtQ=",
"dev": true,
"requires": {
"async": "^2.6.0",
......@@ -1250,7 +1250,7 @@
"async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
"integrity": "sha1-skWiPKcZMAROxT+kaqAKPofGphA=",
"dev": true,
"requires": {
"lodash": "^4.17.10"
......@@ -1259,7 +1259,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
}
}
......@@ -1273,7 +1273,7 @@
"grunt-legacy-log": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz",
"integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==",
"integrity": "sha1-yM0sbIGkRlubvy2HTZY/73pZ/7k=",
"dev": true,
"requires": {
"colors": "~1.1.2",
......@@ -1285,7 +1285,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
}
}
......@@ -1293,7 +1293,7 @@
"grunt-legacy-log-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz",
"integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==",
"integrity": "sha1-0vRCx8AVAGXZAEsI/XQQ03UZGU4=",
"dev": true,
"requires": {
"chalk": "~2.4.1",
......@@ -1303,7 +1303,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
}
}
......@@ -1311,7 +1311,7 @@
"grunt-legacy-util": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz",
"integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==",
"integrity": "sha1-4QYk58hgNOW4cMioYWdD8KCEXkI=",
"dev": true,
"requires": {
"async": "~1.5.2",
......@@ -1326,7 +1326,7 @@
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
},
"underscore.string": {
......@@ -1403,7 +1403,7 @@
"hosted-git-info": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
"integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc="
},
"htmlparser2": {
"version": "3.8.3",
......@@ -1473,7 +1473,7 @@
"http2": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/http2/-/http2-3.3.7.tgz",
"integrity": "sha512-puSi8M8WNlFJm9Pk4c/Mbz9Gwparuj3gO9/RRO5zv6piQ0FY+9Qywp0PdWshYgsMJSalixFY7eC6oPu0zRxLAQ==",
"integrity": "sha1-eDluseC80dsfSxONmXxoLiNBT7w=",
"dev": true
},
"iconv-lite": {
......@@ -1600,7 +1600,7 @@
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
......@@ -1667,13 +1667,13 @@
"livereload-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz",
"integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==",
"integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=",
"dev": true
},
"load-grunt-tasks": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-4.0.0.tgz",
"integrity": "sha512-w5JYPHpZgMxu9XFR9N9MEzyX8E0mLhQkwQ1qVP4mb3gmuomw8Ww8J49NHMbXqyQliq2LUCqdU7/wW96IVuPCKw==",
"integrity": "sha1-9JS8D6xJURW1yMbJV8Xx8P/X7s4=",
"dev": true,
"requires": {
"arrify": "^1.0.0",
......@@ -1810,7 +1810,7 @@
"mime": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
"integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=",
"dev": true
},
"mime-db": {
......@@ -1831,7 +1831,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
......@@ -1914,7 +1914,7 @@
"normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
"integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
"integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=",
"requires": {
"hosted-git-info": "^2.1.4",
"is-builtin-module": "^1.0.0",
......@@ -2001,7 +2001,7 @@
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=",
"dev": true,
"requires": {
"p-try": "^1.0.0"
......@@ -2159,13 +2159,13 @@
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
"dev": true
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=",
"dev": true
},
"range-parser": {
......@@ -2293,7 +2293,7 @@
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
"dev": true,
"requires": {
"glob": "^7.0.5"
......@@ -2302,7 +2302,7 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=",
"dev": true
},
"safe-json-parse": {
......@@ -2314,7 +2314,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
"dev": true
},
"semver": {
......@@ -2340,7 +2340,7 @@
"send": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
"integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=",
"dev": true,
"requires": {
"debug": "2.6.9",
......@@ -2361,7 +2361,7 @@
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
"integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=",
"dev": true
}
}
......@@ -2384,7 +2384,7 @@
"serve-static": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
"integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=",
"dev": true,
"requires": {
"encodeurl": "~1.0.2",
......@@ -2401,7 +2401,7 @@
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
"integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=",
"dev": true
},
"shelljs": {
......@@ -2428,7 +2428,7 @@
"spdx-correct": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
"integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
"integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=",
"requires": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
......@@ -2437,12 +2437,12 @@
"spdx-exceptions": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
"integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg=="
"integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k="
},
"spdx-expression-parse": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
"integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
"integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=",
"requires": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
......@@ -2596,7 +2596,7 @@
"tiny-lr": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz",
"integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==",
"integrity": "sha1-n6VHQS8jj+2waO4pWvi2gsmLKqs=",
"dev": true,
"requires": {
"body": "^5.1.0",
......@@ -2610,7 +2610,7 @@
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"dev": true,
"requires": {
"ms": "2.0.0"
......@@ -2657,7 +2657,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
}
}
......@@ -2718,13 +2718,13 @@
"websocket-extensions": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
"integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=",
"dev": true
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
"dev": true,
"requires": {
"isexe": "^2.0.0"
......
......@@ -75,7 +75,7 @@ public class ElasticJPAListener {
*/
@AfterReturning(value = "execution(* org.springframework.data.jpa.repository.JpaRepository.save(..))", returning = "result")
public void afterPersist(final JoinPoint joinPoint, final Object result) {
LOG.debug("JPA afterPersist {} {}", joinPoint.toLongString(), joinPoint.getTarget());
LOG.trace("JPA afterPersist {} {}", joinPoint.toLongString(), joinPoint.getTarget());
try {
scheduleReindexing(result);
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys2.server.mvc.admin;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.apache.commons.lang3.time.StopWatch;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.QAccession;
import org.genesys2.server.persistence.AccessionRepository;
import org.genesys2.server.service.AccessionService;
import org.genesys2.server.service.AccessionService.IAccessionAction;
import org.genesys2.server.service.filter.AccessionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.support.Querydsl;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.core.types.dsl.PathBuilderFactory;
import com.querydsl.jpa.JPQLQuery;
/**
* Executes actions on filtered accessions.
*/
@Component
public class AccessionProcessor {
private static final Logger LOG = LoggerFactory.getLogger(AccessionProcessor.class);
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private AccessionService accessionService;
@Autowired
private AccessionRepository accessionRepository;
@Autowired
private EntityManager em;
/// Size of database batch scan for IDs
private int batchSize = 1000;
/**
* Apply action on accessions matching the provided filter.
*
* @param filter the filter
* @param action the action
*/
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
public void apply(AccessionFilter filter, IAccessionAction action) {
Predicate predicate = filter.buildQuery();
long count = accessionRepository.count(predicate);
PathBuilder<Accession> builder = new PathBuilderFactory().create(Accession.class);
Querydsl querydsl = new Querydsl(em, builder);
JPQLQuery<Long> query = querydsl.createQuery(QAccession.accession)
// select id only
.select(QAccession.accession.id)
// order by id
.orderBy(QAccession.accession.id.asc());
// apply filter
query.where(predicate);
int startPosition = 0;
query.offset(startPosition);
query.limit(batchSize);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
List<Long> results;
do {
stopWatch.split();
LOG.debug("Reading Accessions. Stopwatch={}s {}+{} of {}. Processing at {} accessions/s", stopWatch.getSplitTime() / 1000, startPosition, batchSize, count, (double)(startPosition+batchSize)/(stopWatch.getSplitTime() / 1000));
results = query.fetch();
asyncUpdate(results, action);
// Next page
query.offset(startPosition += results.size());
// Clear anything cached in the entity manager
em.clear();
} while (results.size() > 0);
stopWatch.stop();
LOG.info("Processing Accessions for filter {} took {}ms", filter, stopWatch.getTime());
}
private void asyncUpdate(List<Long> accessionIds, IAccessionAction action) {
if (accessionIds.size() == 0) {
return;
}
final ArrayList<Long> copy = new ArrayList<>(accessionIds);
threadPoolTaskExecutor.execute(() -> {
try {
LOG.trace("Executing action on {} Accessions.", copy.size());
accessionService.processAccessions(copy, action);
} catch (Throwable e) {
LOG.warn("Error executing action on batch: {}", e.getMessage(), e);
} finally {
LOG.trace("Done executing action on {} accessions.", copy.size());
}
});
}
}
......@@ -29,8 +29,11 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang.time.StopWatch;
import org.genesys.catalog.service.DatasetService;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.genesys.PDCI;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.persistence.AccessionRepository;
import org.genesys2.server.persistence.PDCIRepository;
import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.CountryNamesUpdater;
import org.genesys2.server.service.CropService;
......@@ -39,9 +42,11 @@ import org.genesys2.server.service.GeoRegionService;
import org.genesys2.server.service.GeoService;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.filter.AccessionFilter;
import org.genesys2.server.service.worker.ITPGRFAStatusUpdater;
import org.genesys2.server.service.worker.InstituteUpdater;
import org.genesys2.server.service.worker.SGSVUpdate;
import org.genesys2.util.PDCICalculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -53,8 +58,11 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.xml.sax.SAXException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
......@@ -111,6 +119,12 @@ public class AdminController {
@Autowired
private ContentService contentService;
@Autowired
private AccessionProcessor accessionProcessor;
@Autowired
private PDCIRepository pdciRepository;
@RequestMapping("/")
public String root(Model model) {
return "/admin/index";
......@@ -212,7 +226,7 @@ public class AdminController {
return "redirect:/admin/";
}
@RequestMapping(value = "/pdci", method = RequestMethod.POST, params = "updatePdciStats")
@RequestMapping(value = "/pdci", method = RequestMethod.POST, params = "action=institute-pdci")
public String updatePDCI() {
for (FaoInstitute institute: instituteService.listActive(new PageRequest(0, Integer.MAX_VALUE))) {
LOG.info("Updating PDCI for {}", institute.getCode());
......@@ -222,6 +236,37 @@ public class AdminController {
return "redirect:/admin/";
}
@RequestMapping(value = "/pdci", method = RequestMethod.POST, params = "action=filtered-pdci")
public String updateFilteredPDCI(@RequestParam(name = "filter") String filters) throws JsonParseException, JsonMappingException, IOException {
AccessionFilter filter = mapper.readValue(filters, AccessionFilter.class);
LOG.warn("Recalculating PDCI for accessions matching filter: {}", filter);
accessionProcessor.apply(filter, (accession) -> {