diff --git a/package-lock.json b/package-lock.json index 5bf896665..a52fe0bcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "angular-xeditable": "^0.10.0", "angularjs-slider": "^7.0.0", "autofill-event": "0.0.1", - "d3": "4.2.1", + "d3": "4.13.0", "font-awesome": "^4.7.0", "jquery": "^3.4.1", "jsrsasign": "^10.3.0", @@ -2875,8 +2875,7 @@ "node_modules/commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" }, "node_modules/commondir": { "version": "1.0.1", @@ -3739,56 +3738,56 @@ "dev": true }, "node_modules/d3": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.2.1.tgz", - "integrity": "sha512-jpJO6QJZDUpLqST066xFPS5rEpYAK7VmTqQLfmuF+1NR95gxe2EwUmHsRT4HR237FpR0e+r8h904hpISBnnqEA==", - "dependencies": { - "d3-array": "1.0.1", - "d3-axis": "1.0.3", - "d3-brush": "1.0.2", - "d3-chord": "1.0.2", - "d3-collection": "1.0.1", - "d3-color": "1.0.1", - "d3-dispatch": "1.0.1", - "d3-drag": "1.0.1", - "d3-dsv": "1.0.1", - "d3-ease": "1.0.1", - "d3-force": "1.0.2", - "d3-format": "1.0.2", - "d3-geo": "1.2.2", - "d3-hierarchy": "1.0.2", - "d3-interpolate": "1.1.1", - "d3-path": "1.0.1", - "d3-polygon": "1.0.1", - "d3-quadtree": "1.0.1", - "d3-queue": "3.0.2", - "d3-random": "1.0.1", - "d3-request": "1.0.2", - "d3-scale": "1.0.3", - "d3-selection": "1.0.2", - "d3-shape": "1.0.2", - "d3-time": "1.0.2", - "d3-time-format": "2.0.2", - "d3-timer": "1.0.2", - "d3-transition": "1.0.1", - "d3-voronoi": "1.0.2", - "d3-zoom": "1.0.3" + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", + "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", + "dependencies": { + "d3-array": "1.2.1", + "d3-axis": "1.0.8", + "d3-brush": "1.0.4", + "d3-chord": "1.0.4", + "d3-collection": "1.0.4", + "d3-color": "1.0.3", + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-dsv": "1.0.8", + "d3-ease": "1.0.3", + "d3-force": "1.1.0", + "d3-format": "1.2.2", + "d3-geo": "1.9.1", + "d3-hierarchy": "1.1.5", + "d3-interpolate": "1.1.6", + "d3-path": "1.0.5", + "d3-polygon": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-queue": "3.0.7", + "d3-random": "1.1.0", + "d3-request": "1.0.6", + "d3-scale": "1.0.7", + "d3-selection": "1.3.0", + "d3-shape": "1.2.0", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1", + "d3-timer": "1.0.7", + "d3-transition": "1.1.1", + "d3-voronoi": "1.1.2", + "d3-zoom": "1.7.1" } }, "node_modules/d3-array": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.0.1.tgz", - "integrity": "sha512-VPS5OH5Xb43tkFkxHEc4r5yWhlDwST47zh1q+qvgTj7xB9xDXn+UEcofhvNC7s8gD55y9Q/MCSPSBUVvnzo3Dw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" }, "node_modules/d3-axis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.3.tgz", - "integrity": "sha512-ssSKWVgy3PUBsTitxvgCmaQJHKYN4Iww2lmMiGskRdxfoNKhdU3LDPkSB1Wt2PlRieBY1CAtPS0oT3LtWdABOw==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", + "integrity": "sha512-K0djTb26iQ6AsuD2d6Ka08wBHf4V30awIxV4XFuB/iLzYtTqqJlE/nIN0DBJJCX7lbOqbt2/oeX3r+sU5k2veg==" }, "node_modules/d3-brush": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.2.tgz", - "integrity": "sha512-+PVv7qAd0X/FPcQ2MVFj7uXMt62ymnwvDnOxFOjsHRB/ybcn0ayRyvSOSi+u3IxVlLvhD4jB39QwP6Yv19vcCQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", + "integrity": "sha512-nUFueDzOlvwFvuOBynGSyJM7Wt1H9fKgJeoWFSg3ScS4c7FJBch92FKUJKum4xtgPYHdgH2C3bRg3GzSVltCJQ==", "dependencies": { "d3-dispatch": "1", "d3-drag": "1", @@ -3798,61 +3797,68 @@ } }, "node_modules/d3-chord": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.2.tgz", - "integrity": "sha512-XyGDYtf4gooHSk9+Hf46V66uX1Z7DeJhcvibN4wOkfN4qgt3mEgOLD8IsRDf6h7KpDBdsypT3/jJtV3ZGP9qIg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", + "integrity": "sha512-o0ExexkK1N0KikUakKrQwttP5Flu8AYD6iBUh3AdPJqnTh6xlvcX5wFRuuo29sLOAr9+T4yZPUH1S3CCQJ1SlQ==", "dependencies": { "d3-array": "1", "d3-path": "1" } }, "node_modules/d3-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.1.tgz", - "integrity": "sha512-972LMBhCpNYrmDnarBJDFltizsSMTYPNB1pFIuIPN8RSJz8xHuZa0RB8mhZpjYtOlnWFFBnYQog5bBl4ziolpg==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", + "integrity": "sha512-+TPxaBFzbzfpLF3Hjz8JPeuStNmJnyWAufu8VUfpDCDn5RieIgY+OQDjhKMDorf2naLgAjjZXLUQN7XFp/kgog==" }, "node_modules/d3-color": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.1.tgz", - "integrity": "sha512-HtofmWZaI2kHwzF4cQnQ6RZ509jg3R2U4iit2/7nuMxMWvpNRlcg3LHLPA4XQGzR0i/JkoKTifJuGRRhkcbRHg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", + "integrity": "sha512-t+rSOrshj6m2AUOe8kHvTwfUQ5TFoInEkBfmsHHAHPof58dmbRXNpicB7XAyPbMQbcC7i09p2BxeCEdgBd8xmw==" }, "node_modules/d3-dispatch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.1.tgz", - "integrity": "sha512-BRTp95mobTSKx8EtpOLbxXuYVtNNr0PmelkH9Uzg5cgcO5O1M0i3+2C0FeM2I95BwQoIlsuZXQTPIoIt5xOtmw==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", + "integrity": "sha512-Qh2DR3neW3lq/ug4oymXHYoIsA91nYt47ERb+fPKjRg6zLij06aP7KqHHl2NyziK9ASxrR3GLkHCtZvXe/jMVg==" }, "node_modules/d3-drag": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.0.1.tgz", - "integrity": "sha512-uWFg2X3PD0uOttYzJTdT/BVKMgCED4Y4swz5a2Nc89m4BQ7s0DK17zRe7LciZ0PpAi2Zjy40oFIMBnfXkI0h6g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", + "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", "dependencies": { "d3-dispatch": "1", "d3-selection": "1" } }, "node_modules/d3-dsv": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.1.tgz", - "integrity": "sha512-VjRi8bmInbdZsnNr5inlWEEd7GutNcQUb+gXgr4LUyt+8lZjAxU2PBPMNMBBLHCPwosiFcmdwBfnWFpN4/khsQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", + "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", "dependencies": { + "commander": "2", + "iconv-lite": "0.4", "rw": "1" }, "bin": { - "csv2json": "bin/csv2json", - "csv2tsv": "bin/csv2tsv", - "tsv2csv": "bin/tsv2csv", - "tsv2json": "bin/tsv2json" + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" } }, "node_modules/d3-ease": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.1.tgz", - "integrity": "sha512-ORtme6srMxINZj98uIW6EKBub/9JCgWJPC3rM464rvabKGNbYIA6AIAgir1Czo5zHUOo+/9DJvGUaPQO4/Ld2A==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", + "integrity": "sha512-io3QwOJwVPAxRF2UXpKpCdz2wm/7VLFCQQ1yy+GzX6YCtt3vi2BGnimI8agSF5jyUrHsADyF303d2S+ps7zU8w==" }, "node_modules/d3-force": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.0.2.tgz", - "integrity": "sha512-fvAAPGOAvtZhdrGjHXX1LjCwhaifJCv8SHKvosfTDKuRmHOzMO9k+0UtB1rJfZv7shdQD0IjMnhkU5CpWT5deQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", + "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", "dependencies": { "d3-collection": "1", "d3-dispatch": "1", @@ -3861,60 +3867,60 @@ } }, "node_modules/d3-format": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.0.2.tgz", - "integrity": "sha512-VHFdLLjGkeGrRL8T/rlIIDhI3vvVX/oOTM/GaDJfB1sIb4dU5ZgiEjg3EeidJdQ/70u60tM015TSWa1gqqLRhg==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", + "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==" }, "node_modules/d3-geo": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.2.2.tgz", - "integrity": "sha512-n5XCdF6Kjl/6UWz0WlWUnNK99JnVdTOFR/g5brN7fgOr5ZHrAxxIcbWEx5KNjZd04iwoFeRKccOWkl4HwumIOw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", + "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", "dependencies": { "d3-array": "1" } }, "node_modules/d3-hierarchy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.0.2.tgz", - "integrity": "sha512-kFZpTy/gba+CaR+86hyWfHZtB4VXcad+Bkxcsp6nRQWjJCorcvc+vsUBFRJkt+iOCGHe8qn7GN8rM1v0hilH+Q==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", + "integrity": "sha512-PcsLIhThc60mWnxlojIOH7Sc0tQ2DgLWfEwEAyzCtej5f3H9wSsRmrg5pEhKZLrwiJnI2zyw/pznJxL9a/Eugw==" }, "node_modules/d3-interpolate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.1.tgz", - "integrity": "sha512-wCYUl4cTSv4jZKfo+s+Y02Fn0/ykwg+jFx2FEF26m/Dhe+z7cVK96aErNRd3jKbBie1urAh9TIhlM6LJ4iFjCg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", "dependencies": { "d3-color": "1" } }, "node_modules/d3-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.1.tgz", - "integrity": "sha512-IVMzFUJW3MCJqfATod5ZE+6MGdVSH2aMj75yRm5BNJJ2L8bV4P9ZmhD2n0mLN9W/x99UrUvhUJypsV/bM4yfsA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", + "integrity": "sha512-eD76prgnTKYkLzHlY2UMyOEZXTpC+WOanCr1BLxo38w4fPPPq/LgCFqRQvqFU3AJngfZmmKR7rgKPZ4EGJ9Atw==" }, "node_modules/d3-polygon": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.1.tgz", - "integrity": "sha512-Bndhc5jt+OMVMtNo2IiWSjSRNOR3no6+1Fpml9GHXeCOYuO7o/mqL8UVF8midD0OcCf2pwibDHj+0htfzuiM5A==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", + "integrity": "sha512-2zP7GOvf4XOWTeQouK7fCO534yQxyhYYTw6GTqcXifIalHgA6qV/es+4GRQii9m6XxEPFcht4loobD/o2iEo1A==" }, "node_modules/d3-quadtree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.1.tgz", - "integrity": "sha512-87W0Y2y3fxpRTtCLIp8r4hM5es1WDORrCaCkjKJTPgyksz4zqgx1Ymz/+rW21ZrRjxWrXLtF7PHruY9lRazS0w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", + "integrity": "sha512-U2Jc3jF3JOBGXIOnvWY9C4ekRwRX9hEVpMMmeduJyaxAwPmoe7t84iZFTLn1RwYOyrXxJF55H/Hrg186TFQQdw==" }, "node_modules/d3-queue": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.2.tgz", - "integrity": "sha512-uTdfWFB8Hn0E0MKQgiifk57vg27+4d+P4EIvF2jN6mzpDB3eT0oAqLf9HydHqjY1uOADInJ5thtOm/VESNyJSQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", + "integrity": "sha512-2rs+6pNFKkrJhqe1rg5znw7dKJ7KZr62j9aLZfhondkrnz6U7VRmJj1UGcbD8MRc46c7H8m4SWhab8EalBQrkw==" }, "node_modules/d3-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.0.1.tgz", - "integrity": "sha512-q2q5mBCGhbHNQvDO32ODYNKTIC21GfpU2E23aal0XB9BaJEz4GTVyw2RiJw++8R0Quf6oxbLGDJN5pbWAcIM7w==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", + "integrity": "sha512-XuMbjx3Jq4EWfJP4g6nR7zns/bZfaVbWHWfR8auDkEiWCzVbWifmasfszV1ZRN3xXK3nY4RUFL2nTIhceGZSFQ==" }, "node_modules/d3-request": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.2.tgz", - "integrity": "sha512-hPuZc8fqP3PS+2YakYBecJ6A5wlmtazb/PtDSum2ASxMWfpR1tAB0+S2i3kHJvCjg2pxXlAghMQEbkGUWdjyBQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", + "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", "dependencies": { "d3-collection": "1", "d3-dispatch": "1", @@ -3923,11 +3929,11 @@ } }, "node_modules/d3-scale": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.3.tgz", - "integrity": "sha512-ah2Xqywu96gau2iET3T0ZTsu0/X0gfoB8vDTuZ1OaG5F0SgGJLXreBVBknSZf2HKnxjenRvFok3qY2FgY4RpFg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", + "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", "dependencies": { - "d3-array": "1", + "d3-array": "^1.2.0", "d3-collection": "1", "d3-color": "1", "d3-format": "1", @@ -3937,58 +3943,58 @@ } }, "node_modules/d3-selection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.0.2.tgz", - "integrity": "sha512-nInNdsdhljkDqkU/83bdWwtiJ7xsX3l57YZMlqsAOMeQROeCv7osPqQgYnao0NmRZEGc11hNakY+EOkaIdsWpQ==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", + "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==" }, "node_modules/d3-shape": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.0.2.tgz", - "integrity": "sha512-hNft7xu4Kd4sPhxHaUGUOsfidzANQzMFPddgQlZizFuRdBRwv2NqRD0/bfpptywPXHPBST7FfOpoNntUULSdbg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", + "integrity": "sha512-LP48zJ9ykPKjCdd0vSu5k2l4s8v1vI6vvdDeJtmgtTa+L6Ery0lzvOaV7pMunFuLv11hwSRZQnSnlhFl801aiw==", "dependencies": { "d3-path": "1" } }, "node_modules/d3-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.2.tgz", - "integrity": "sha512-UUVa1vppG6pnPlqespIXdcj/7QONWlVM7fnFNephLtN8t/v/Y7oEKSLsZo9GR65hgXBCoKBUYIQzDcIaRNEoOg==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", + "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==" }, "node_modules/d3-time-format": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.0.2.tgz", - "integrity": "sha512-6rbEDcTfCTe44f6H35xp+c2f8+0iUf8bjEItTcD2lFatqyEpuWKKb4eO67IWB2lrfjksP09uMug8ryfVmEgjAA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", + "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", "dependencies": { "d3-time": "1" } }, "node_modules/d3-timer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.2.tgz", - "integrity": "sha512-DBZ50J8ALbXNao9oD6ZBWrgxLLVQps8R7VoMFFa7JkVv/4eXzymq62LsHTh3bBGGTbrpYszHqj3VFTvOHulUew==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" }, "node_modules/d3-transition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.0.1.tgz", - "integrity": "sha512-/Q3YLm6X8gyXT0cFSY/95YKEGoU7R1m1tdj/DWANkNrtUvnCDrcCAIdV6uJEiXiP1eIomdSFPMMusy7ge7KdwA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", + "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", "dependencies": { "d3-color": "1", "d3-dispatch": "1", "d3-ease": "1", "d3-interpolate": "1", - "d3-selection": "1", + "d3-selection": "^1.1.0", "d3-timer": "1" } }, "node_modules/d3-voronoi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.0.2.tgz", - "integrity": "sha512-MASF6Gpgs+rWf5ege34eqWzeyevCpHtr+ZgJ6Je3Z9WSeYCnZtA7TblHbtwbNwiu2poWePmg4B12M/ayFTujag==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" }, "node_modules/d3-zoom": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.0.3.tgz", - "integrity": "sha512-LltBg3RBKQADHcniEi3EifSneqY5/luUXcEVgPyUlK+MVpLlHwlAPd3wpk/niPexQdeFtvMi4OFhvmZZ9TqC+w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", + "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", "dependencies": { "d3-dispatch": "1", "d3-drag": "1", @@ -7040,7 +7046,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -12104,8 +12109,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { "version": "1.2.4", @@ -18854,8 +18858,7 @@ "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" }, "commondir": { "version": "1.0.1", @@ -19542,56 +19545,56 @@ "dev": true }, "d3": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.2.1.tgz", - "integrity": "sha512-jpJO6QJZDUpLqST066xFPS5rEpYAK7VmTqQLfmuF+1NR95gxe2EwUmHsRT4HR237FpR0e+r8h904hpISBnnqEA==", - "requires": { - "d3-array": "1.0.1", - "d3-axis": "1.0.3", - "d3-brush": "1.0.2", - "d3-chord": "1.0.2", - "d3-collection": "1.0.1", - "d3-color": "1.0.1", - "d3-dispatch": "1.0.1", - "d3-drag": "1.0.1", - "d3-dsv": "1.0.1", - "d3-ease": "1.0.1", - "d3-force": "1.0.2", - "d3-format": "1.0.2", - "d3-geo": "1.2.2", - "d3-hierarchy": "1.0.2", - "d3-interpolate": "1.1.1", - "d3-path": "1.0.1", - "d3-polygon": "1.0.1", - "d3-quadtree": "1.0.1", - "d3-queue": "3.0.2", - "d3-random": "1.0.1", - "d3-request": "1.0.2", - "d3-scale": "1.0.3", - "d3-selection": "1.0.2", - "d3-shape": "1.0.2", - "d3-time": "1.0.2", - "d3-time-format": "2.0.2", - "d3-timer": "1.0.2", - "d3-transition": "1.0.1", - "d3-voronoi": "1.0.2", - "d3-zoom": "1.0.3" + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", + "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", + "requires": { + "d3-array": "1.2.1", + "d3-axis": "1.0.8", + "d3-brush": "1.0.4", + "d3-chord": "1.0.4", + "d3-collection": "1.0.4", + "d3-color": "1.0.3", + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-dsv": "1.0.8", + "d3-ease": "1.0.3", + "d3-force": "1.1.0", + "d3-format": "1.2.2", + "d3-geo": "1.9.1", + "d3-hierarchy": "1.1.5", + "d3-interpolate": "1.1.6", + "d3-path": "1.0.5", + "d3-polygon": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-queue": "3.0.7", + "d3-random": "1.1.0", + "d3-request": "1.0.6", + "d3-scale": "1.0.7", + "d3-selection": "1.3.0", + "d3-shape": "1.2.0", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1", + "d3-timer": "1.0.7", + "d3-transition": "1.1.1", + "d3-voronoi": "1.1.2", + "d3-zoom": "1.7.1" } }, "d3-array": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.0.1.tgz", - "integrity": "sha512-VPS5OH5Xb43tkFkxHEc4r5yWhlDwST47zh1q+qvgTj7xB9xDXn+UEcofhvNC7s8gD55y9Q/MCSPSBUVvnzo3Dw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" }, "d3-axis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.3.tgz", - "integrity": "sha512-ssSKWVgy3PUBsTitxvgCmaQJHKYN4Iww2lmMiGskRdxfoNKhdU3LDPkSB1Wt2PlRieBY1CAtPS0oT3LtWdABOw==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", + "integrity": "sha512-K0djTb26iQ6AsuD2d6Ka08wBHf4V30awIxV4XFuB/iLzYtTqqJlE/nIN0DBJJCX7lbOqbt2/oeX3r+sU5k2veg==" }, "d3-brush": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.2.tgz", - "integrity": "sha512-+PVv7qAd0X/FPcQ2MVFj7uXMt62ymnwvDnOxFOjsHRB/ybcn0ayRyvSOSi+u3IxVlLvhD4jB39QwP6Yv19vcCQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", + "integrity": "sha512-nUFueDzOlvwFvuOBynGSyJM7Wt1H9fKgJeoWFSg3ScS4c7FJBch92FKUJKum4xtgPYHdgH2C3bRg3GzSVltCJQ==", "requires": { "d3-dispatch": "1", "d3-drag": "1", @@ -19601,55 +19604,57 @@ } }, "d3-chord": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.2.tgz", - "integrity": "sha512-XyGDYtf4gooHSk9+Hf46V66uX1Z7DeJhcvibN4wOkfN4qgt3mEgOLD8IsRDf6h7KpDBdsypT3/jJtV3ZGP9qIg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", + "integrity": "sha512-o0ExexkK1N0KikUakKrQwttP5Flu8AYD6iBUh3AdPJqnTh6xlvcX5wFRuuo29sLOAr9+T4yZPUH1S3CCQJ1SlQ==", "requires": { "d3-array": "1", "d3-path": "1" } }, "d3-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.1.tgz", - "integrity": "sha512-972LMBhCpNYrmDnarBJDFltizsSMTYPNB1pFIuIPN8RSJz8xHuZa0RB8mhZpjYtOlnWFFBnYQog5bBl4ziolpg==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", + "integrity": "sha512-+TPxaBFzbzfpLF3Hjz8JPeuStNmJnyWAufu8VUfpDCDn5RieIgY+OQDjhKMDorf2naLgAjjZXLUQN7XFp/kgog==" }, "d3-color": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.1.tgz", - "integrity": "sha512-HtofmWZaI2kHwzF4cQnQ6RZ509jg3R2U4iit2/7nuMxMWvpNRlcg3LHLPA4XQGzR0i/JkoKTifJuGRRhkcbRHg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", + "integrity": "sha512-t+rSOrshj6m2AUOe8kHvTwfUQ5TFoInEkBfmsHHAHPof58dmbRXNpicB7XAyPbMQbcC7i09p2BxeCEdgBd8xmw==" }, "d3-dispatch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.1.tgz", - "integrity": "sha512-BRTp95mobTSKx8EtpOLbxXuYVtNNr0PmelkH9Uzg5cgcO5O1M0i3+2C0FeM2I95BwQoIlsuZXQTPIoIt5xOtmw==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", + "integrity": "sha512-Qh2DR3neW3lq/ug4oymXHYoIsA91nYt47ERb+fPKjRg6zLij06aP7KqHHl2NyziK9ASxrR3GLkHCtZvXe/jMVg==" }, "d3-drag": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.0.1.tgz", - "integrity": "sha512-uWFg2X3PD0uOttYzJTdT/BVKMgCED4Y4swz5a2Nc89m4BQ7s0DK17zRe7LciZ0PpAi2Zjy40oFIMBnfXkI0h6g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", + "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", "requires": { "d3-dispatch": "1", "d3-selection": "1" } }, "d3-dsv": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.1.tgz", - "integrity": "sha512-VjRi8bmInbdZsnNr5inlWEEd7GutNcQUb+gXgr4LUyt+8lZjAxU2PBPMNMBBLHCPwosiFcmdwBfnWFpN4/khsQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", + "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", "requires": { + "commander": "2", + "iconv-lite": "0.4", "rw": "1" } }, "d3-ease": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.1.tgz", - "integrity": "sha512-ORtme6srMxINZj98uIW6EKBub/9JCgWJPC3rM464rvabKGNbYIA6AIAgir1Czo5zHUOo+/9DJvGUaPQO4/Ld2A==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", + "integrity": "sha512-io3QwOJwVPAxRF2UXpKpCdz2wm/7VLFCQQ1yy+GzX6YCtt3vi2BGnimI8agSF5jyUrHsADyF303d2S+ps7zU8w==" }, "d3-force": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.0.2.tgz", - "integrity": "sha512-fvAAPGOAvtZhdrGjHXX1LjCwhaifJCv8SHKvosfTDKuRmHOzMO9k+0UtB1rJfZv7shdQD0IjMnhkU5CpWT5deQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", + "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", "requires": { "d3-collection": "1", "d3-dispatch": "1", @@ -19658,60 +19663,60 @@ } }, "d3-format": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.0.2.tgz", - "integrity": "sha512-VHFdLLjGkeGrRL8T/rlIIDhI3vvVX/oOTM/GaDJfB1sIb4dU5ZgiEjg3EeidJdQ/70u60tM015TSWa1gqqLRhg==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", + "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==" }, "d3-geo": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.2.2.tgz", - "integrity": "sha512-n5XCdF6Kjl/6UWz0WlWUnNK99JnVdTOFR/g5brN7fgOr5ZHrAxxIcbWEx5KNjZd04iwoFeRKccOWkl4HwumIOw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", + "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", "requires": { "d3-array": "1" } }, "d3-hierarchy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.0.2.tgz", - "integrity": "sha512-kFZpTy/gba+CaR+86hyWfHZtB4VXcad+Bkxcsp6nRQWjJCorcvc+vsUBFRJkt+iOCGHe8qn7GN8rM1v0hilH+Q==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", + "integrity": "sha512-PcsLIhThc60mWnxlojIOH7Sc0tQ2DgLWfEwEAyzCtej5f3H9wSsRmrg5pEhKZLrwiJnI2zyw/pznJxL9a/Eugw==" }, "d3-interpolate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.1.tgz", - "integrity": "sha512-wCYUl4cTSv4jZKfo+s+Y02Fn0/ykwg+jFx2FEF26m/Dhe+z7cVK96aErNRd3jKbBie1urAh9TIhlM6LJ4iFjCg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", "requires": { "d3-color": "1" } }, "d3-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.1.tgz", - "integrity": "sha512-IVMzFUJW3MCJqfATod5ZE+6MGdVSH2aMj75yRm5BNJJ2L8bV4P9ZmhD2n0mLN9W/x99UrUvhUJypsV/bM4yfsA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", + "integrity": "sha512-eD76prgnTKYkLzHlY2UMyOEZXTpC+WOanCr1BLxo38w4fPPPq/LgCFqRQvqFU3AJngfZmmKR7rgKPZ4EGJ9Atw==" }, "d3-polygon": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.1.tgz", - "integrity": "sha512-Bndhc5jt+OMVMtNo2IiWSjSRNOR3no6+1Fpml9GHXeCOYuO7o/mqL8UVF8midD0OcCf2pwibDHj+0htfzuiM5A==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", + "integrity": "sha512-2zP7GOvf4XOWTeQouK7fCO534yQxyhYYTw6GTqcXifIalHgA6qV/es+4GRQii9m6XxEPFcht4loobD/o2iEo1A==" }, "d3-quadtree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.1.tgz", - "integrity": "sha512-87W0Y2y3fxpRTtCLIp8r4hM5es1WDORrCaCkjKJTPgyksz4zqgx1Ymz/+rW21ZrRjxWrXLtF7PHruY9lRazS0w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", + "integrity": "sha512-U2Jc3jF3JOBGXIOnvWY9C4ekRwRX9hEVpMMmeduJyaxAwPmoe7t84iZFTLn1RwYOyrXxJF55H/Hrg186TFQQdw==" }, "d3-queue": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.2.tgz", - "integrity": "sha512-uTdfWFB8Hn0E0MKQgiifk57vg27+4d+P4EIvF2jN6mzpDB3eT0oAqLf9HydHqjY1uOADInJ5thtOm/VESNyJSQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", + "integrity": "sha512-2rs+6pNFKkrJhqe1rg5znw7dKJ7KZr62j9aLZfhondkrnz6U7VRmJj1UGcbD8MRc46c7H8m4SWhab8EalBQrkw==" }, "d3-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.0.1.tgz", - "integrity": "sha512-q2q5mBCGhbHNQvDO32ODYNKTIC21GfpU2E23aal0XB9BaJEz4GTVyw2RiJw++8R0Quf6oxbLGDJN5pbWAcIM7w==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", + "integrity": "sha512-XuMbjx3Jq4EWfJP4g6nR7zns/bZfaVbWHWfR8auDkEiWCzVbWifmasfszV1ZRN3xXK3nY4RUFL2nTIhceGZSFQ==" }, "d3-request": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.2.tgz", - "integrity": "sha512-hPuZc8fqP3PS+2YakYBecJ6A5wlmtazb/PtDSum2ASxMWfpR1tAB0+S2i3kHJvCjg2pxXlAghMQEbkGUWdjyBQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", + "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", "requires": { "d3-collection": "1", "d3-dispatch": "1", @@ -19720,11 +19725,11 @@ } }, "d3-scale": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.3.tgz", - "integrity": "sha512-ah2Xqywu96gau2iET3T0ZTsu0/X0gfoB8vDTuZ1OaG5F0SgGJLXreBVBknSZf2HKnxjenRvFok3qY2FgY4RpFg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", + "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", "requires": { - "d3-array": "1", + "d3-array": "^1.2.0", "d3-collection": "1", "d3-color": "1", "d3-format": "1", @@ -19734,58 +19739,58 @@ } }, "d3-selection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.0.2.tgz", - "integrity": "sha512-nInNdsdhljkDqkU/83bdWwtiJ7xsX3l57YZMlqsAOMeQROeCv7osPqQgYnao0NmRZEGc11hNakY+EOkaIdsWpQ==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", + "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==" }, "d3-shape": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.0.2.tgz", - "integrity": "sha512-hNft7xu4Kd4sPhxHaUGUOsfidzANQzMFPddgQlZizFuRdBRwv2NqRD0/bfpptywPXHPBST7FfOpoNntUULSdbg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", + "integrity": "sha512-LP48zJ9ykPKjCdd0vSu5k2l4s8v1vI6vvdDeJtmgtTa+L6Ery0lzvOaV7pMunFuLv11hwSRZQnSnlhFl801aiw==", "requires": { "d3-path": "1" } }, "d3-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.2.tgz", - "integrity": "sha512-UUVa1vppG6pnPlqespIXdcj/7QONWlVM7fnFNephLtN8t/v/Y7oEKSLsZo9GR65hgXBCoKBUYIQzDcIaRNEoOg==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", + "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==" }, "d3-time-format": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.0.2.tgz", - "integrity": "sha512-6rbEDcTfCTe44f6H35xp+c2f8+0iUf8bjEItTcD2lFatqyEpuWKKb4eO67IWB2lrfjksP09uMug8ryfVmEgjAA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", + "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", "requires": { "d3-time": "1" } }, "d3-timer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.2.tgz", - "integrity": "sha512-DBZ50J8ALbXNao9oD6ZBWrgxLLVQps8R7VoMFFa7JkVv/4eXzymq62LsHTh3bBGGTbrpYszHqj3VFTvOHulUew==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" }, "d3-transition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.0.1.tgz", - "integrity": "sha512-/Q3YLm6X8gyXT0cFSY/95YKEGoU7R1m1tdj/DWANkNrtUvnCDrcCAIdV6uJEiXiP1eIomdSFPMMusy7ge7KdwA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", + "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", "requires": { "d3-color": "1", "d3-dispatch": "1", "d3-ease": "1", "d3-interpolate": "1", - "d3-selection": "1", + "d3-selection": "^1.1.0", "d3-timer": "1" } }, "d3-voronoi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.0.2.tgz", - "integrity": "sha512-MASF6Gpgs+rWf5ege34eqWzeyevCpHtr+ZgJ6Je3Z9WSeYCnZtA7TblHbtwbNwiu2poWePmg4B12M/ayFTujag==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" }, "d3-zoom": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.0.3.tgz", - "integrity": "sha512-LltBg3RBKQADHcniEi3EifSneqY5/luUXcEVgPyUlK+MVpLlHwlAPd3wpk/niPexQdeFtvMi4OFhvmZZ9TqC+w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", + "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", "requires": { "d3-dispatch": "1", "d3-drag": "1", @@ -22181,7 +22186,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -26205,8 +26209,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sax": { "version": "1.2.4", diff --git a/package.json b/package.json index 5071e8657..85dcacbed 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "angular-xeditable": "^0.10.0", "angularjs-slider": "^7.0.0", "autofill-event": "0.0.1", - "d3": "4.2.1", + "d3": "4.13.0", "font-awesome": "^4.7.0", "jquery": "^3.4.1", "jsrsasign": "^10.3.0", diff --git a/src/css/graphs-vizualizations.css b/src/css/graphs-vizualizations.css index b77e84624..fed35eb47 100644 --- a/src/css/graphs-vizualizations.css +++ b/src/css/graphs-vizualizations.css @@ -76,7 +76,7 @@ } .graph-visualization { - height: calc(100vh - 120px); + height: calc(100vh - 190px); } .graph-visualization svg { diff --git a/src/js/angular/clustermanagement/app.js b/src/js/angular/clustermanagement/app.js index 657a8d28d..9061ee334 100644 --- a/src/js/angular/clustermanagement/app.js +++ b/src/js/angular/clustermanagement/app.js @@ -3,8 +3,7 @@ import 'angular/core/directives'; import 'angular/clustermanagement/controllers'; import 'angular/clustermanagement/directives'; import 'angular/core/services/repositories.service'; -import 'd3/build/d3'; -import 'lib/d3-ONTO-chord-patch'; +import 'lib/d3.patch.js'; import 'angular-pageslide-directive/dist/angular-pageslide-directive'; const modules = [ diff --git a/src/js/angular/clustermanagement/cluster-drawing.service.js b/src/js/angular/clustermanagement/cluster-drawing.service.js index 3c5dcf827..a3865a06c 100644 --- a/src/js/angular/clustermanagement/cluster-drawing.service.js +++ b/src/js/angular/clustermanagement/cluster-drawing.service.js @@ -80,6 +80,11 @@ export function createNodes(nodesDataBinding, nodeRadius, isLegend) { .attr('id', 'node-group') .classed('legend', isLegend); + const nodeUpdateElements = nodeGroup + .merge(nodesDataBinding) + .attr('id', 'node-group') + .classed('legend', isLegend); + createHexagon(nodeGroup, nodeRadius); nodesDataBinding.exit().remove(); @@ -88,6 +93,7 @@ export function createNodes(nodesDataBinding, nodeRadius, isLegend) { .attr('class', 'icon-any node-icon'); addHostnameToNodes(nodeGroup, nodeRadius, isLegend); + return nodeUpdateElements } function addHostnameToNodes(nodeElements, nodeRadius, isLegend) { @@ -314,14 +320,14 @@ function getLinkCoordinates(link, nodes) { return 'M' + sourceX + ',' + sourceY + 'L' + targetX + ',' + targetY; } -export function positionNodesOnClusterZone(nodes, clusterZoneX, clusterZoneY, clusterZoneRadius) { - nodes +export function positionNodesOnClusterZone(nodeElements, clusterZoneX, clusterZoneY, clusterZoneRadius) { + nodeElements .attr('transform', (node, index) => { // Calculate initial positions for the new nodes based on // spreading them evenly on a circle around the center of the page. - const theta = 2 * Math.PI * index / nodes[0].length; - var x = clusterZoneX + Math.cos(theta) * clusterZoneRadius; - var y = clusterZoneY + Math.sin(theta) * clusterZoneRadius; + const theta = 2 * Math.PI * index / nodeElements.size(); + const x = clusterZoneX + Math.cos(theta) * clusterZoneRadius; + const y = clusterZoneY + Math.sin(theta) * clusterZoneRadius; node.x = x; node.y = y; return `translate(${x}, ${y})`; @@ -342,5 +348,5 @@ function createHexagon(nodeGroup, radius) { .enter() .append("path") .attr('class', 'node member') - .attr("d", d3.svg.line()); + .attr("d", d3.line()); } diff --git a/src/js/angular/clustermanagement/directives.js b/src/js/angular/clustermanagement/directives.js index bf2fdcc59..afcfc1118 100644 --- a/src/js/angular/clustermanagement/directives.js +++ b/src/js/angular/clustermanagement/directives.js @@ -236,17 +236,17 @@ clusterManagementDirectives.directive('clusterGraphicalView', ['$window', 'Local .text(getLabelFor('link_state')); const legendNodeData = legendGroup.selectAll('#node-group').data(legendNodes); - CDS.createNodes(legendNodeData, legendNodeRadius, true); - CDS.updateNodes(legendNodeData); + const legendNodesElements = CDS.createNodes(legendNodeData, legendNodeRadius, true); + CDS.updateNodes(legendNodesElements); - legendNodeData.select('.node.member') + legendNodesElements.select('.node.member') .on("mouseover", function (d) { d3.event.stopPropagation(); showLegendTooltip(d, this); }) .on('mouseout', hideLegendTooltip); - legendNodeData + legendNodesElements .attr('transform', function (d) { const row = Math.floor(d.id / legendColumns); const column = d.id % legendColumns; @@ -257,8 +257,8 @@ clusterManagementDirectives.directive('clusterGraphicalView', ['$window', 'Local }); legendGroup - .call(function () { - legendWidth = this.node().getBBox().width; + .call(function (d) { + legendWidth = d.node().getBBox().width; }); // Position node/link state labels @@ -317,8 +317,8 @@ clusterManagementDirectives.directive('clusterGraphicalView', ['$window', 'Local legendGroup .call(function (d) { - legendHeight = this.node().getBBox().height; - legendWidth = this.node().getBBox().width; + legendHeight = d.node().getBBox().height; + legendWidth = d.node().getBBox().width; }); legendGroup.select('.legend-background') @@ -343,7 +343,9 @@ clusterManagementDirectives.directive('clusterGraphicalView', ['$window', 'Local } }); const nodeData = nodesGroup.selectAll('#node-group').data(nodes, (node) => node.address); - nodeData + const nodesElements = CDS.createNodes(nodeData, nodeRadius); + + nodesElements .on('click', (d) => { scope.childContext.selectNode(d); @@ -361,9 +363,8 @@ clusterManagementDirectives.directive('clusterGraphicalView', ['$window', 'Local } tooltip.style("top", (d3.event.pageY - 28) + "px"); }); - CDS.createNodes(nodeData, nodeRadius); - CDS.updateNodes(nodeData); - CDS.positionNodesOnClusterZone(nodeData, clusterZoneX, clusterZoneY, clusterZoneRadius); + CDS.updateNodes(nodesElements); + CDS.positionNodesOnClusterZone(nodesElements, clusterZoneX, clusterZoneY, clusterZoneRadius); } function drawLinks(links, nodes) { diff --git a/src/js/angular/graphexplore/app.js b/src/js/angular/graphexplore/app.js index b9aa002e5..b0503074d 100644 --- a/src/js/angular/graphexplore/app.js +++ b/src/js/angular/graphexplore/app.js @@ -4,8 +4,7 @@ import 'angular/core/directives'; import 'angular/core/services/repositories.service'; import 'angular-ui-scroll/dist/ui-scroll.min'; import 'angular-ui-scroll/dist/ui-scroll-jqlite.min'; -import 'd3/build/d3'; -import 'lib/d3-ONTO-chord-patch'; +import 'lib/d3.patch.js'; import 'lib/d3-tip/d3-tip-patch'; import 'angular-pageslide-directive/dist/angular-pageslide-directive'; import 'angularjs-slider/dist/rzslider.min'; diff --git a/src/js/angular/graphexplore/controllers/graphs-config.controller.js b/src/js/angular/graphexplore/controllers/graphs-config.controller.js index e91c2255d..1ba99f824 100644 --- a/src/js/angular/graphexplore/controllers/graphs-config.controller.js +++ b/src/js/angular/graphexplore/controllers/graphs-config.controller.js @@ -653,6 +653,10 @@ function GraphConfigCtrl($scope, $timeout, $location, toastr, $repositories, Spa } function loadTab() { + if (!window.editor) { + $timeout(() => loadTab()); + return; + } $scope.tabsData = [$scope.currentQuery]; let tab = $scope.currentQuery; diff --git a/src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js b/src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js index 4bc038d0f..7a5fa9984 100644 --- a/src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js +++ b/src/js/angular/graphexplore/controllers/graphs-visualizations.controller.js @@ -68,9 +68,22 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer let colorIndex = 0; const nodeLabelMinFontSize = 16; // pixels // define zoom and drag behavior; keep this out of draw() to preserve state when nodes are added/removed - const panAndZoom = d3.behavior.zoom() - .scaleExtent([0.5, 10]); - let transformValues; + var zoomLayout = d3.zoom().scaleExtent([0.5, 10]); + var container; + var INITIAL_CONTAINER_TRANSFORM = d3.zoomIdentity.translate(0, -70).scale(1); + + function zoomed() { + if (GuidesService.isActive()) { + // disable zooming if a guide is active. + return; + } + transformValues = d3.event.transform; + container.attr("transform", transformValues); + } + + zoomLayout.on("zoom", zoomed); + + let transformValues = INITIAL_CONTAINER_TRANSFORM; // build svg element const width = 1000; const height = 1000; @@ -811,8 +824,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer tripleLinksCopy: tripleLinksCopy, colorIndex: colorIndex, type2color: type2color, - scale: panAndZoom.scale(), - translate: panAndZoom.translate() + transform: transformValues }; }; @@ -838,10 +850,8 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer type2color = angular.copy(state.type2color); } - if (angular.isDefined(state.translate) && angular.isDefined(state.scale)) { - transformValues = "translate(" + state.translate[0] + ", " + state.translate[1] + ") scale(" + state.scale + ")"; - panAndZoom.translate(state.translate); - panAndZoom.scale(state.scale); + if (angular.isDefined(state.transform)) { + transformValues = d3.zoomIdentity.translate(state.transform.x, state.transform.y).scale(state.transform.k) } draw(); @@ -991,9 +1001,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer graph = new Graph(); const rootNode = graph.addNode(response.data, width / 2, height / 2); - transformValues = "translate(0, -70) scale(1)"; - panAndZoom.translate([0, -70]); - panAndZoom.scale(1); + transformValues = INITIAL_CONTAINER_TRANSFORM; expandNode(rootNode, true); }).catch(function (err) { @@ -1178,12 +1186,12 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer const nodeLabelRectScaleX = 1.75; - const color1 = d3.scale.linear() + const color1 = d3.scaleLinear() .domain([0, 9]) .range(["hsl(0, 100%, 75%)", "hsl(360, 90%, 82%)"]) .interpolate(d3.interpolateHslLong); - const color2 = d3.scale.linear() + const color2 = d3.scaleLinear() .domain([0, 9]) .range(["hsl(180, 50%, 75%)", "hsl(540, 40%, 82%)"]) .interpolate(d3.interpolateHslLong); @@ -1204,14 +1212,33 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer } }; - const force = d3.layout.force() - .gravity(0.07) - .size([width, height]); + const forceX = d3.forceX(width / 2).strength(0.005) + const forceY = d3.forceY(height / 2).strength(0.005) + + const force = d3.forceSimulation() + .force('x', forceX) + .force('y', forceY); const svg = d3.select(".main-container .graph-visualization").append("svg") .attr("viewBox", "0 0 " + width + " " + height) .attr("preserveAspectRatio", "xMidYMid meet"); + // building rectangular so we can bind zoom and drag effects + svg.append("rect") + .attr("width", width * 10) + .attr("height", height * 10) + .attr("x", -(width * 10 - width) / 2) + .attr("y", -(height * 10 - height) / 2) + .style("fill", "none") + .style("pointer-events", "all") + .call(zoomLayout) + .on("click", function () { + d3.event.stopPropagation(); + removeMenuIfVisible(); + // Clicking outside the graph stops the layout + force.stop(); + }); + let showNodeTipAndIconsTimer = 0; let removeIconsTimer = 0; @@ -1220,31 +1247,11 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer function draw(resetRootNode) { // remove all group elements and rec to rebuild the graph when the user clicks on it d3.selectAll("svg g").remove(); - d3.selectAll("svg rect").remove(); d3.selectAll('.d3-tip').remove(); d3.selectAll('.menu-events').remove(); - // zoom and drag event - panAndZoom.on("zoom", panAndZoomed); - - // building rectangular so we can bind zoom and drag effects - svg.append("rect") - .attr("width", width * 10) - .attr("height", height * 10) - .attr("x", -(width * 10 - width) / 2) - .attr("y", -(height * 10 - height) / 2) - .style("fill", "none") - .style("pointer-events", "all") - .call(panAndZoom) - .on("click", function () { - d3.event.stopPropagation(); - removeMenuIfVisible(); - // Clicking outside the graph stops the layout - force.stop(); - }); - - const container = svg.append("g").attr("class", "nodes-container") + container = svg.append("g").attr("class", "nodes-container") .attr("transform", function () { if (angular.isDefined(transformValues) && !resetRootNode) { return transformValues; @@ -1393,20 +1400,26 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer let link = svg.selectAll(".link"); let node = svg.selectAll(".node"); - force.nodes(graph.nodes).charge(-3000); - - force.links(graph.links).linkDistance(function (l) { - if (l.source.isTriple || l.target.isTriple) { - return 0; - } - // link distance depends on length of text with an added bonus for strongly connected nodes, - // i.e. they will be pushed further from each other so that their common nodes can cluster up - return getPredicateTextLength(l) + 30 * l.connectedness; - }); + const collisionForce = d3.forceCollide((d) => d.size + 5).strength(0.5) + const chargeForce = d3.forceManyBody().strength(-300); + const centerForce = d3.forceCenter(width/2, height/2) + + force.nodes(graph.nodes) + .force("charge", chargeForce) + .force("collide", collisionForce) + .force("center", centerForce) + .force("link", d3.forceLink(graph.links).distance(function (l) { + if (l.source.isTriple || l.target.isTriple) { + return 0; + } + // link distance depends on length of text with an added bonus for strongly connected nodes, + // i.e. they will be pushed further from each other so that their common nodes can cluster up + return getPredicateTextLength(l) + 30 * l.connectedness; + })); // arrow markers container.append("defs").selectAll("marker") - .data(force.links()) + .data(graph.links) .enter().append("marker") .attr("class", "arrow-marker") .attr("id", function (d) { @@ -1466,49 +1479,64 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer }); // node events and variables - let mouseEventTimer; + let touchHoldEventTimer; let upEventLast = 0; - let virtualClickEventTimer = 0; let moveEventCount = 0; + let singleClickTimer = null; + let clickTarget = null; - // tracks mousedown and touchstart events in order to count single or double click - // (checked in upEventHandler) - const downEventHandler = function () { + // track single and double click events + const clickEventHandler = function (d) { if (d3.event.button && d3.event.button !== 0) { return; } - hideTipForNode(); - $timeout.cancel(mouseEventTimer); - $scope.showPredicates = false; - if (d3.event.timeStamp - upEventLast < multiClickDelay) { - virtualClickEventTimer++; - } else { - virtualClickEventTimer = 1; + const event = d3.event; + const element = this; + + if (singleClickTimer && clickTarget === element) { + $timeout.cancel(singleClickTimer); + singleClickTimer = null; + // expand node + expandEventHandler(d, 0, element.parentNode); + return; } - upEventLast = d3.event.timeStamp; + clickTarget = element; - d3.event.preventDefault(); + + hideTipForNode(); + $scope.showPredicates = false; + + if (!GuidesService.isActive()) { + $timeout.cancel(singleClickTimer); + // Show node info + singleClickTimer = $timeout(function () { + clickedNode(d, element, event); + singleClickTimer = null; + }, 40 + multiClickDelay) + } }; - // builds upon downEventHandler and adds additional functionality for touch devices + // builds upon clickEventHandler and adds additional functionality for touch devices const touchStartEventHandler = function (d) { - downEventHandler(); - // for touch devices we track touch and hold for 1s in order to remove a node moveEventCount = 0; - mouseEventTimer = $timeout(function () { + touchHoldEventTimer = $timeout(function () { if (moveEventCount < 5) { // remove the node only if not many move events were fired, // this avoids conflict with dragging nodes hideNode(d); } - mouseEventTimer = null; - virtualClickEventTimer = 0; + touchHoldEventTimer = null; }, 1000); }; + const touchEndEventHandler = function (d) { + $timeout.cancel(touchHoldEventTimer); + touchHoldEventTimer = null; + }; + // tracks the number of move events (checked in the touchend event handler) const moveEventHandler = function () { moveEventCount++; @@ -1527,40 +1555,19 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer }; const expandEventHandler = function (d, i, parentNode) { + let parent = parentNode || this.parentNode; + if (Array.isArray(parentNode)) { + parent = parentNode[i] + } const shownLinks = graph.countLinks(d, graph.links); if (shownLinks <= getSettings()['linksLimit']) { - expandNode(d, false, parentNode ? parentNode : this.parentNode); + expandNode(d, false, parent); } else { toastr.info($translate.instant('graphexplore.increase.limit'), $translate.instant('graphexplore.node.at.max')); } $scope.closeInfoPanel(); }; - const upEventHandler = function (d) { - if (d3.event.button && d3.event.button !== 0) { - return; - } - - $timeout.cancel(mouseEventTimer); - - const event = d3.event; - const element = this; - if (!GuidesService.isActive()) { - if (d3.event.timeStamp - upEventLast < multiClickDelay) { - if (virtualClickEventTimer === 1) { - mouseEventTimer = $timeout(function () { - clickedNode(d, element, event); - }, 40 + multiClickDelay - (d3.event.timeStamp - upEventLast)); - } else if (virtualClickEventTimer === 2) { - // expand node - expandEventHandler(d, 0, element.parentNode); - } - } - } - - d3.event.preventDefault(); - }; - // Shows growing or shrinking pin animation function showPinAnimation(d, type) { let startSize; @@ -1646,8 +1653,10 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer // unpin $scope.numberOfPinnedNodes--; d.fixed = false; + d.fx =null; + d.fy =null; showPinAnimation(d, 'up'); - force.resume(); + force.alpha(1).restart(); } else { // pin down $scope.numberOfPinnedNodes++; @@ -1658,13 +1667,13 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer updateTipForNode(d); }; - const drag = d3.behavior.drag() - .origin(function (d) { + const drag = d3.drag() + .subject(function (d) { return d; }) - .on("dragstart", dragstarted) + .on("start", dragstarted) .on("drag", dragged) - .on("dragend", dragended); + .on("end", dragended); function dragstarted(d) { @@ -1677,18 +1686,15 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer d.isBeingDragged = true; d.beginDragging = true; removeMenuIfVisible(); - d3.event.sourceEvent.stopPropagation(); d3.select(this).classed("dragging", true); + force.alphaTarget(0.3).restart(); } } function dragged(d) { if (d.isBeingDragged) { - // reset click counter to avoid conflicts between clicks and drags - virtualClickEventTimer = 0; - - d.px = d3.event.x; - d.py = d3.event.y; + d.fx = d3.event.x; + d.fy = d3.event.y; if (!d.fixed) { $scope.numberOfPinnedNodes++; d.fixed = true; @@ -1698,8 +1704,6 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer } d.pinWasFixed = true; d.beginDragging = null; - - force.resume(); } } @@ -1712,6 +1716,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer d.isBeingDragged = false; d3.select(this).classed("dragging", false); } + force.alphaTarget(0) } node = container.selectAll(".node") @@ -1732,20 +1737,19 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer } return $scope.getColor(d.types[0]); }) - .call(drag) .on('mouseover', showNodeTipAndIcons) .on('mouseout', hideTipForNode) - .on("mousedown", downEventHandler) + .on("click", clickEventHandler) .on("touchstart", touchStartEventHandler) // no need to track move for mouse .on("touchmove", moveEventHandler) - .on("mouseup", upEventHandler) - .on("touchend", upEventHandler) + .on("touchend", touchEndEventHandler) .on("contextmenu", rightClickHandler) // custom event used when user is following a guide .on("gdb-expand-node", expandEventHandler) // custom event used when user is following a guide - .on("gdb-show-node-info", showNodeInfo); + .on("gdb-show-node-info", showNodeInfo) + .call(drag); const nodeLabels = container.selectAll(".node-wrapper").append("foreignObject") .style("pointer-events", "none") @@ -1759,12 +1763,6 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer updateNodeLabels(nodeLabels); force.on("tick", function () { - // recalculate nodes positions and repel them if they collide - let q = d3.geom.quadtree(graph.nodes); - let i = 0; - const n = graph.nodes.length; - // FIXME while (++i < n) q.visit(collide(graph.nodes[i])); - // recalculate links attributes link.attr("x1", function (d) { return getNodeX(d.source); @@ -1828,15 +1826,6 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer updateAlphaInScope(); }); - function panAndZoomed() { - if (GuidesService.isActive()) { - // disable zooming if a guide is active. - return; - } - transformValues = "translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")"; - container.attr("transform", transformValues); - } - if (angular.isDefined(loader)) { loader.setLoadingState(false); } @@ -1864,7 +1853,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer d3.selectAll('.d3-actions-tip').remove(); - force.start(); + force.alpha(0.3).restart(); } @@ -1873,30 +1862,6 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer $rootScope.d3alpha = force.alpha(); } - /* FIXME - // check for collision of the nodes - function collide(node, bigger) { - return function (quad, x1, y1, x2, y2) { - if (quad.point && (quad.point !== node)) { - var x = node.x - quad.point.x, - y = node.y - quad.point.y, - l = Math.sqrt(x * x + y * y), - r = node.size + quad.point.size; - if (l < r) { - l = (l - r) / l * .5; - node.x -= x *= l; - node.y -= y *= l; - quad.point.x += x; - quad.point.y += y; - } - } - return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; - }; - } - */ - - draw(); - // find angle between pair of nodes so we can position predicates function findAngleBetweenNodes(linkedNodes, direction) { const p1 = { @@ -1962,9 +1927,9 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer // If nodes are still rearranging result of force.alpha() is more than 0.02 // and we don't want to show node's icons on mouse over and stop rearrangement. - // The chosen value 0.02 is somewhat magic and works well with 0.02 in awaitAlphaDropD3() + // The chosen value 0.1 is somewhat magic and works well with 0.02 in awaitAlphaDropD3() // in the guides code. - if (force.alpha() < 0.02) { + if (force.alpha() < 0.1) { menuEvents.initIcons(d, element.parentNode); force.stop(); updateAlphaInScope(); @@ -1992,9 +1957,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer response.data.types = "greyColor"; } graph = new Graph(); - transformValues = "translate(0, -70) scale(1)"; - panAndZoom.translate([0, -70]); - panAndZoom.scale(1); + transformValues = INITIAL_CONTAINER_TRANSFORM; } function initGraphFromResponse(response) { @@ -2360,8 +2323,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer this.animateMenu = function (node) { const animationDuration = 100; - const easeEffects = ["linear", "quad", "cubic", "sin", "exp", "circle", "elastic", "back", "bounce"]; // https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#easing - const easeEffect = easeEffects[3]; + const easeEffect = d3.easeSin; let delay = 0; const dellayAddition = 35; let angle = 20; // angle of the first icon 0 is at 12 o'clock @@ -2802,7 +2764,7 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer removeMenuIfVisible(); // compute common rotation math such as the angle, its sine and cosine and the pivot point - const theta = (isLeft ? 1 : -1) * 2 * Math.PI / 180; // + rotates left, - rotates right + const theta = (isLeft ? 1 : -1) * 10 * Math.PI / 180; // + rotates left, - rotates right const cos = Math.cos(theta); const sin = Math.sin(theta); const pivotX = width / 2; // i.e. centre of viewport @@ -2815,12 +2777,12 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer d.y = pivotY + (-sin * (d.x - pivotX) + cos * (d.y - pivotY)); if (d.fixed) { // Fixed nodes need their px and py updated too - d.px = d.x; - d.py = d.y; + d.fx = d.x; + d.fy = d.y; } }); - force.resume(); + force.alpha(1).restart(); }; $scope.openUri = function (uri, noHistory) { @@ -3000,17 +2962,22 @@ function GraphsVisualizationsCtrl($scope, $rootScope, $repositories, $licenseSer $scope.togglePinAllNodes = function () { removeMenuIfVisible(); - const value = $scope.numberOfPinnedNodes <= 0; + const value = angular.isUndefined($scope.numberOfPinnedNodes) || $scope.numberOfPinnedNodes <= 0; $scope.numberOfPinnedNodes = 0; d3.selectAll('.node').each(function (d) { d.fixed = value; if (value) { $scope.numberOfPinnedNodes++; + d.fx = d.x; + d.fy = d.y; + } else { + d.fx = null; + d.fy = null; } }); - force.resume(); + force.alpha(1).restart(); }; // event for capturing left and right arrows used for rotation diff --git a/src/js/angular/graphexplore/controllers/rdf-class-hierarchy.controller.js b/src/js/angular/graphexplore/controllers/rdf-class-hierarchy.controller.js index 62597c6da..d2a320515 100644 --- a/src/js/angular/graphexplore/controllers/rdf-class-hierarchy.controller.js +++ b/src/js/angular/graphexplore/controllers/rdf-class-hierarchy.controller.js @@ -251,8 +251,8 @@ function RdfClassHierarchyCtlr($scope, $rootScope, $location, $repositories, $li } function goToDomainRangeGraphView(selectedClass) { - const uri = selectedClass.fullName; - const name = selectedClass.name; + const uri = selectedClass.data.fullName; + const name = selectedClass.data.name; GraphDataRestService.checkDomainRangeData(uri) .success(function (response, status) { @@ -281,8 +281,8 @@ function RdfClassHierarchyCtlr($scope, $rootScope, $location, $repositories, $li function prepareDataForClassInfoSidePanel(selectedClass) { // generate SPARQL query for listing class instances in sparql view - const uri = selectedClass.fullName; - let name = selectedClass.name; + const uri = selectedClass.data.fullName; + let name = selectedClass.data.name; // in case of no prefix available both name and uri are the same // so only take the local name of the uri a tab name for the SPARQL view diff --git a/src/js/angular/graphexplore/directives/dependencies-chord.directive.js b/src/js/angular/graphexplore/directives/dependencies-chord.directive.js index 30bf6435f..d5a69cc57 100644 --- a/src/js/angular/graphexplore/directives/dependencies-chord.directive.js +++ b/src/js/angular/graphexplore/directives/dependencies-chord.directive.js @@ -30,7 +30,7 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { return; } - const fill = d3.scale.category20(); + const fill = d3.scaleOrdinal(d3.schemeCategory20); const tooltip = d3.select("body").append("div") .attr("class", "tooltip") @@ -44,16 +44,16 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { const outerRadius = Math.min(width, height) / 2.8; const innerRadius = outerRadius - 24; - const arc = d3.svg.arc() + const arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); - const layout = d3.layout.chord() - .padding(.04) + const chordGraph = d3.chord() + .padAngle(.04) .sortSubgroups(d3.descending) .sortChords(d3.ascending); - const path = d3.svg.chord() + const path = d3.ribbon() .radius(innerRadius); const svg = d3.select("#dependencies-chord").append("svg") @@ -69,7 +69,7 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { .style("fill", "none"); // Compute the chord layout. - layout.matrix(matrix); + const layout = chordGraph(matrix); // Add a group per neighborhood. const group = svg.selectAll(".group") @@ -112,7 +112,7 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { // Add the chords. const chord = svg.selectAll(".chord") - .data(layout.chords) + .data(layout) .enter().append("path") .attr("class", "chord") .style("fill", function (d) { @@ -125,11 +125,11 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { .attr("d", path); chord.on("mouseover", function () { - d3.select(this).style({"fill-opacity": "1"}); + d3.select(this).style("fill-opacity", "1"); }); chord.on("mouseout", function () { - d3.select(this).style({"fill-opacity": ".67"}); + d3.select(this).style("fill-opacity", ".67"); }); chord.on("click", function (d) { @@ -199,7 +199,7 @@ function dependenciesChordDirective($repositories, GraphDataRestService) { // convert selected html to base64 const imgSrc = SVG.Export.generateBase64ImageSource('.dependencies-chord svg'); // set the binary image and a name for the downloadable file on the export button - d3.select(this).attr({ + d3.select(this).attrs({ href: imgSrc, download: "dependencies-" + $repositories.getActiveRepository() + ".svg" }); diff --git a/src/js/angular/graphexplore/directives/domain-range-graph.directive.js b/src/js/angular/graphexplore/directives/domain-range-graph.directive.js index 71a27eccd..26cde7377 100644 --- a/src/js/angular/graphexplore/directives/domain-range-graph.directive.js +++ b/src/js/angular/graphexplore/directives/domain-range-graph.directive.js @@ -38,21 +38,6 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData } function renderDomainRangeGraph(scope) { - d3.selection.prototype.moveToFront = function () { - return this.each(function () { - d3.select(this.parentNode.appendChild(this)); - }); - }; - - d3.selection.prototype.moveToBack = function () { - return this.each(function () { - const firstChild = this.parentNode.firstChild; - if (firstChild) { - this.parentNode.insertBefore(this, firstChild); - } - }); - }; - var width = 1200, height = 600; @@ -63,75 +48,80 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData basicArrowStrokeWidth = width / 1000, collapsedArrowStrokeWidth = width / 600; - - var force = d3.layout.force() - .size([width, height]) - .charge(-900); - - var drag = force.drag() - .on("dragstart", dragstart); - var svg = d3.select("#domain-range") .append("svg") .attr("viewBox", "0 0 " + width + " " + height) .attr("preserveAspectRatio", "xMidYMid meet") .on("dblclick.zoom", null); - var defs = svg.append("defs"); + var force = d3.forceSimulation(); - defs.append("marker") - .attr({ - id: "arrow", - viewBox: "0 -5 10 10", - refX: 10, - refY: 0, - markerUnits: "strokeWidth", - markerWidth: 5, - markerHeight: 5, - orient: "auto", - fill: ONTO_BLUE + var drag = d3.drag() + .subject(function (d) { + return d; }) - .append("path") - .attr({ - d: "M0,-5L10,0L0,5", - class: "arrowHead" - }); + .on("start", dragStart) + .on("end", dragEnd) + .on("drag", dragged); - defs.append("marker") - .attr({ - id: "collapsed-arrow", - viewBox: "0 -5 10 10", - refX: 9, - refY: 0, - markerUnits: "strokeWidth", - markerWidth: 4, - markerHeight: 4, - orient: "auto", - fill: ONTO_BLUE - }) - .append("path") - .attr({ - d: "M0,-5L10,0L0,5", - class: "arrowHead" - }); + var defs = svg.append("defs"); + generateMarkers(defs); + + function generateMarkers(defElement) { + defs.append("marker") + .attrs({ + id: "arrow", + viewBox: "0 -5 10 10", + refX: 10, + refY: 0, + markerUnits: "strokeWidth", + markerWidth: 5, + markerHeight: 5, + orient: "auto", + fill: ONTO_BLUE + }) + .append("path") + .attrs({ + d: "M0,-5L10,0L0,5", + class: "arrowHead" + }); - defs.append("marker") - .attr({ - id: "arrow-loop", - viewBox: "0 -5 10 10", - refX: 7, - refY: 0, - markerUnits: "strokeWidth", - markerWidth: 5, - markerHeight: 5, - orient: "auto", - fill: ONTO_BLUE - }) - .append("path") - .attr({ - d: "M0,-5L10,0L0,5", - class: "arrowHead" - }); + defs.append("marker") + .attrs({ + id: "collapsed-arrow", + viewBox: "0 -5 10 10", + refX: 9, + refY: 0, + markerUnits: "strokeWidth", + markerWidth: 4, + markerHeight: 4, + orient: "auto", + fill: ONTO_BLUE + }) + .append("path") + .attrs({ + d: "M0,-5L10,0L0,5", + class: "arrowHead" + }); + + defs.append("marker") + .attrs({ + id: "arrow-loop", + viewBox: "0 -5 10 10", + refX: 7, + refY: 0, + markerUnits: "strokeWidth", + markerWidth: 5, + markerHeight: 5, + orient: "auto", + fill: ONTO_BLUE + }) + .append("path") + .attrs({ + d: "M0,-5L10,0L0,5", + class: "arrowHead" + }); + } /* * Prepares SVG document image export by adding xml namespaces and @@ -148,7 +138,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData var imgSrc = SVG.Export.generateBase64ImageSource("#domain-range svg"); // set the binary image and a name for the downloadable file on the export button - d3.select(this).attr({ + d3.select(this).attrs({ href: imgSrc, download: "domain-range-graph-" + $repositories.getActiveRepository() + ".svg" }); @@ -157,173 +147,178 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData d3.select("#download-svg") .on("mouseover", prepareForSVGImageExport); - // start of code for legend - var legendBackgroundWidth = width / 7; - var legendBackgroundHeight = legendBackgroundWidth * 1.2; + generateLegend(); - var svgLegend = d3.select(".legend-container") - .append("svg") - .attr("viewBox", "0 0 " + legendBackgroundWidth + " " + legendBackgroundHeight) - .attr("preserveAspectRatio", "xMidYMid meet"); + function generateLegend() { + // start of code for legend - var legendCellGroup = svgLegend; + var legendBackgroundWidth = width / 7; + var legendBackgroundHeight = legendBackgroundWidth * 1.2; - legendCellGroup.append("rect") - .attr({ - width: legendBackgroundWidth, - height: legendBackgroundHeight - }) - .style("fill", "rgba(235, 235, 235, 0.9)"); - - var sourceX = width / 75; - var sourceY = width / 40; - var targetX = sourceX + mainClassSize / 2.5; - var targetY = sourceY; - - var legendTextX = targetX + width / 90; - var legendLabelFontSize = labelFontSize / 1.1; - - var classNodeY = sourceY; - var legendClassNode = legendCellGroup - .append("circle") - .attr({ - class: "legend-class-node", - cx: (sourceX + targetX) / 2, - cy: classNodeY, - r: mainClassSize / 4.5 - }); + var svgLegend = d3.select(".legend-container") + .append("svg") + .attr("viewBox", "0 0 " + legendBackgroundWidth + " " + legendBackgroundHeight) + .attr("preserveAspectRatio", "xMidYMid meet"); - var classNodeTextY = targetY + width / 370; - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: classNodeTextY - }) - .style('font-size', legendLabelFontSize + 'px') - .text("main class node"); - - var objectNodeY = classNodeY + width / 30; - legendCellGroup - .append("circle") - .attr({ - class: "legend-object-node", - cx: (sourceX + targetX) / 2, - cy: objectNodeY, - r: otherClassSize / 1.25 - }); + var legendCellGroup = svgLegend; - var objectNodeTextY = classNodeTextY + width / 30; - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: objectNodeTextY - }) - .style('font-size', legendLabelFontSize + 'px') - .text("class node"); - - var datatypeNodeY = objectNodeY + width / 45; - legendCellGroup - .append("circle") - .attr({ - class: "legend-datatype-node", - cx: (sourceX + targetX) / 2, - cy: datatypeNodeY, - r: datatypeSize - }); + legendCellGroup.append("rect") + .attrs({ + width: legendBackgroundWidth, + height: legendBackgroundHeight + }) + .style("fill", "rgba(235, 235, 235, 0.9)"); - var datatypeNodeTextY = objectNodeTextY + width / 45; - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: datatypeNodeTextY - }) - .style('font-size', legendLabelFontSize + 'px') - .text("datatype node"); - - var basicPropertyArrowY = datatypeNodeY + width / 45; - var classNodeSel = d3.select('.legend-class-node'); - legendCellGroup - .append("line") - .attr({ - class: "property-arrow", - x1: sourceX, - y1: basicPropertyArrowY, - x2: targetX, - y2: basicPropertyArrowY - }) - .style("stroke-width", basicArrowStrokeWidth) - .attr("marker-end", "url(" + $location.absUrl() + "#arrow)"); - - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: basicPropertyArrowY + (width / 370) - }) - .style('font-size', legendLabelFontSize + 'px') - .text("explicit property"); - - var implicitPropArrowY = basicPropertyArrowY + width / 45; - legendCellGroup - .append("line") - .attr({ - class: "implicit-property-arrow", - x1: sourceX, - y1: implicitPropArrowY, - x2: targetX, - y2: implicitPropArrowY - }) - .style("stroke-width", basicArrowStrokeWidth) - .attr("marker-end", "url(" + $location.absUrl() + "#arrow)"); - - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: implicitPropArrowY + (width / 370) - }) - .style('font-size', legendLabelFontSize + 'px') - .text("implicit property"); - - var collapsedPropArrowY = implicitPropArrowY + width / 45; - legendCellGroup - .append("line") - .attr({ - class: "collapsed-property-arrow", - x1: sourceX, - y1: collapsedPropArrowY, - x2: targetX, - y2: collapsedPropArrowY - }) - .style("stroke-width", collapsedArrowStrokeWidth) - .attr("marker-end", "url(" + $location.absUrl() + "#collapsed-arrow)"); - - legendCellGroup - .append("text") - .attr({ - x: legendTextX, - y: collapsedPropArrowY + (width / 370) - }) - .style('font-size', legendLabelFontSize + 'px') - .text("collapsed property"); - // end of code for legend + var sourceX = width / 75; + var sourceY = width / 40; + var targetX = sourceX + mainClassSize / 2.5; + var targetY = sourceY; - // there doesn't seem to be a need for a separate group - var g = svg; //svg.append("g"); + var legendTextX = targetX + width / 90; + var legendLabelFontSize = labelFontSize / 1.1; + + var classNodeY = sourceY; + var legendClassNode = legendCellGroup + .append("circle") + .attrs({ + class: "legend-class-node", + cx: (sourceX + targetX) / 2, + cy: classNodeY, + r: mainClassSize / 4.5 + }); + + var classNodeTextY = targetY + width / 370; + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: classNodeTextY + }) + .style('font-size', legendLabelFontSize + 'px') + .text("main class node"); + + var objectNodeY = classNodeY + width / 30; + legendCellGroup + .append("circle") + .attrs({ + class: "legend-object-node", + cx: (sourceX + targetX) / 2, + cy: objectNodeY, + r: otherClassSize / 1.25 + }); + + var objectNodeTextY = classNodeTextY + width / 30; + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: objectNodeTextY + }) + .style('font-size', legendLabelFontSize + 'px') + .text("class node"); + + var datatypeNodeY = objectNodeY + width / 45; + legendCellGroup + .append("circle") + .attrs({ + class: "legend-datatype-node", + cx: (sourceX + targetX) / 2, + cy: datatypeNodeY, + r: datatypeSize + }); + + var datatypeNodeTextY = objectNodeTextY + width / 45; + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: datatypeNodeTextY + }) + .style('font-size', legendLabelFontSize + 'px') + .text("datatype node"); + + var basicPropertyArrowY = datatypeNodeY + width / 45; + legendCellGroup + .append("line") + .attrs({ + class: "property-arrow", + x1: sourceX, + y1: basicPropertyArrowY, + x2: targetX, + y2: basicPropertyArrowY + }) + .style("stroke-width", basicArrowStrokeWidth) + .attr("marker-end", "url(" + $location.absUrl() + "#arrow)"); + + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: basicPropertyArrowY + (width / 370) + }) + .style('font-size', legendLabelFontSize + 'px') + .text("explicit property"); + + var implicitPropArrowY = basicPropertyArrowY + width / 45; + legendCellGroup + .append("line") + .attrs({ + class: "implicit-property-arrow", + x1: sourceX, + y1: implicitPropArrowY, + x2: targetX, + y2: implicitPropArrowY + }) + .style("stroke-width", basicArrowStrokeWidth) + .attr("marker-end", "url(" + $location.absUrl() + "#arrow)"); + + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: implicitPropArrowY + (width / 370) + }) + .style('font-size', legendLabelFontSize + 'px') + .text("implicit property"); + + var collapsedPropArrowY = implicitPropArrowY + width / 45; + legendCellGroup + .append("line") + .attrs({ + class: "collapsed-property-arrow", + x1: sourceX, + y1: collapsedPropArrowY, + x2: targetX, + y2: collapsedPropArrowY + }) + .style("stroke-width", collapsedArrowStrokeWidth) + .attr("marker-end", "url(" + $location.absUrl() + "#collapsed-arrow)"); + + legendCellGroup + .append("text") + .attrs({ + x: legendTextX, + y: collapsedPropArrowY + (width / 370) + }) + .style('font-size', legendLabelFontSize + 'px') + .text("collapsed property"); + // end of code for legend + } var selectedRdfUri = $location.search().uri; var classNodeLabel = $location.search().name; - var collapsed = $location.search().collapsed; + const collapsed = $location.search().collapsed; - GraphDataRestService.getDomainRangeData(selectedRdfUri, collapsed) - .success(function (response, status, headers) { - scope.domainRangeGraphData = response; - }).error(function (response) { - toastr.error("Request for " + classNodeLabel + " failed!"); - }); + getDomainRangeData(selectedRdfUri, collapsed); + + function getDomainRangeData(selectedRdfUri, collapsed) { + GraphDataRestService.getDomainRangeData(selectedRdfUri, collapsed) + .success(function (response, status, headers) { + scope.domainRangeGraphData = response; + }).error(function (response) { + toastr.error("Request for " + classNodeLabel + " failed!"); + }); + } function switchEdgeMode(collapsed) { $rootScope.$broadcast('switchEdgeMode', { @@ -365,12 +360,17 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData if (scope.domainRangeGraphData) { var graph = angular.copy(scope.domainRangeGraphData); - force - .nodes(graph.nodes) - .links(graph.links); + const nodes = graph.nodes; + const links = graph.links; + + force.nodes(nodes) + .force('x', d3.forceX(width / 2)) + .force('y', d3.forceY(height / 2)) + .force("charge", d3.forceManyBody().strength(-800)) + .force("link", d3.forceLink(links).distance(width / 3.5)) - var linkGroup = g.selectAll(".link") - .data(graph.links) + var linkGroup = svg.selectAll(".link") + .data(links) .enter() .append("g"); @@ -390,7 +390,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData if (d.objectPropNodeClassUri !== selectedRdfUri) { link = linkGroup .append("line") - .attr({ + .attrs({ class: "link", // absolute url needed because angular inserts a tag "marker-end": "url(" + $location.absUrl() + "#arrow)" @@ -422,7 +422,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData var loopLinkSize = mainClassSize / 2; loopLink = d3.select(this) .append("path") - .attr({ + .attrs({ d: "M 0 0 A " + loopLinkSize + " " + loopLinkSize + " 0 1 1 0 " + loopLinkSize, class: "loop-link", fill: "none", @@ -535,8 +535,8 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData }); - var nodeGroup = g.selectAll(".node") - .data(graph.nodes) + var nodeGroup = svg.selectAll(".node") + .data(nodes) .enter() .append("g"); @@ -548,18 +548,18 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData .each(function (d) { var sel = d3.select(this); if (d.classPosition === "main") { - sel.attr({ + sel.attrs({ class: "class-node", r: mainClassSize }) .attr("marker-end", "url(" + $location.absUrl() + "#loop-link)"); } else if (d.objectPropClassName === null) { - sel.attr({ + sel.attrs({ class: "datatype-node", r: datatypeSize }); } else { - sel.attr({ + sel.attrs({ class: "object-prop-node", r: otherClassSize }); @@ -596,7 +596,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData var objectPropClassName = nodeGroup.select("text"); - g.select(".class-node") + svg.select(".class-node") .each(function () { d3.select(this.parentNode) .append("text") @@ -611,7 +611,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData }); - var rdfClassName = g.select(".class-node + text"), + var rdfClassName = svg.select(".class-node + text"), classNode = d3.select(".class-node"), loopLinkBackgroundSel = d3.selectAll(".loop-link-background"), loopLinkPropertyName = d3.selectAll(".loop-link-property-name"); @@ -632,7 +632,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData } function tick(e) { - var k = 8 * e.alpha; + var k = 8 * force.alpha(); function pushEdgesToLeftAndRight(d) { if (d.propertyType === "objectLeft") { @@ -690,7 +690,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData loopLinkLabelY = d.y - mainClassSize * 2.1 - currentBackgroundHeight; sel - .attr({ + .attrs({ x: loopLinkLabelX, y: loopLinkLabelY }) @@ -764,7 +764,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData } sel - .attr({ + .attrs({ transform: "rotate(270, " + d.x + "," + d.y + ") translate(" + loopLinkBackgroundY + "," + loopLinkBackgroundX + ")", width: foundLoopLinkBackgroundProps[0].height, height: foundLoopLinkBackgroundProps[0].width @@ -781,7 +781,7 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData function adjustViewMorePredicatesLabel(allLoopLinkEdges) { var viewMoreTextWidth; d3.select(".view-more-preds-label") - // make label bold to resemble a collapsed label + // make label bold to resemble a collapsed label .style("font-weight", "bold") .each(function (d) { // attach all reflexive links to the "view more" collapsed predicate @@ -794,8 +794,8 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData .on("click", onCollapsedPropertyNameClick); d3.select(".view-more-preds-rect") - // we modify height property instead of width because they are reversed - // when we repositioned loop link labels + // we modify height property instead of width because they are reversed + // when we repositioned loop link labels .attr("height", viewMoreTextWidth + 2 * textPadding); } @@ -912,18 +912,48 @@ function domainRangeGraphDirective($rootScope, $window, $repositories, GraphData .moveToFront(); } - - force - .on("tick", tick) - .linkDistance(width / 3.5) - .start(); + force.on("tick", tick) } }); - function dragstart(d) { - d3.select(this) - .classed("selected", d.selected = true); + let isDragged = false; + + function dragStart() { + const event = d3.event; + + force.stop(); + event.subject.fx = event.x; + event.subject.fy = event.y; + d3.select(this).classed("selected", true); + } + + // Update the subject (dragged node) position during drag. + function dragged() { + isDragged = true; + + force.alphaTarget(0).restart(); + const event = d3.event; + event.subject.fx = event.x; + event.subject.fy = event.y; + } + + // Restore the target alpha so the simulation cools after dragging ends. + // Unfix the subject position now that it’s no longer being dragged. + function dragEnd() { + const event = d3.event; + + event.subject.fx = null; + event.subject.fy = null; + d3.select(this).classed("selected", false); + if (isDragged) { + force.alpha(0.2).restart(); + isDragged = false; + } else { + force.restart(); + } + } + } } diff --git a/src/js/angular/graphexplore/directives/rdf-class-hierarchy.directive.js b/src/js/angular/graphexplore/directives/rdf-class-hierarchy.directive.js index 8f9107e4d..c1ad2bb8b 100644 --- a/src/js/angular/graphexplore/directives/rdf-class-hierarchy.directive.js +++ b/src/js/angular/graphexplore/directives/rdf-class-hierarchy.directive.js @@ -42,25 +42,13 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w height = 800, diameter = height, margin = 20, - node, - root; + tip, + rootHierarchy; - var pack = d3.layout.pack() - .size([diameter - margin, diameter - margin]) - .value(function (d) { - return d.size; - }); - - var colors = [ - "hsl(33, 75%, 75%)", - "hsl(213, 75%, 75%)", - "hsl(333, 75%, 75%)", - "hsl(153, 75%, 75%)", - "hsl(273, 75%, 75%)", - "hsl(93, 75%, 75%)" - ]; + var packLayout = d3.pack() + .size([diameter - margin, diameter - margin]); - var color = d3.scale.linear() + var color = d3.scaleLinear() .domain([0, 4]) .range(["hsl(19, 70%, 90%)", "hsl(19, 70%, 50%)"]) .interpolate(d3.interpolateHcl); @@ -73,7 +61,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w function appendMainGroup() { return svg.append("svg:g") - .attr({ + .attrs({ id: "main-group", transform: "translate(" + width / 2 + "," + height / 2 + ")" }); @@ -109,7 +97,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w var imgSrc = SVG.Export.generateBase64ImageSource("#classChart svg"); // set the binary image and a name for the downloadable file on the export button - d3.select(this).attr({ + d3.select(this).attrs({ href: imgSrc, download: "class-hierarchy-" + $repositories.getActiveRepository() + ".svg" }); @@ -145,8 +133,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w var autoZoomToPreviousState, doFocus; - var oldRoot, - focus, + var focus, rootFocusEvent, classSearchEvent, flattenedClassData = {}; @@ -162,9 +149,16 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // fix for single child classes CirclePacking.SingleChild.addPlaceholders(root, true); - focus = newFocus ? newFocus : root; - var nodes = pack.nodes(root), + rootHierarchy = d3.hierarchy(root); + rootHierarchy.sum(function (d) { + return d.size; + }) + focus = newFocus ? newFocus : rootHierarchy; + + packLayout(rootHierarchy) + + var nodes = rootHierarchy.descendants(), view; focus.isInFocusTransitive = true; @@ -174,21 +168,21 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w CirclePacking.SingleChild.centerNodes(nodes); CirclePacking.SingleChild.makePositionsRelativeToZero(nodes); - var tip = d3tip() - .attr('class', 'd3-tip') - //.offset([-10, 0]) - .customPosition(function (d) { - return { - top: 'inherit', - bottom: ($window.innerHeight - d3.event.clientY) + 'px', - right: ($window.innerWidth - d3.event.clientX) + 'px' - }; - }) - .html(function (d) { - return d.name; - }); - - svg.call(tip); + if (!tip) { + tip = d3tip() + .attr('class', 'd3-tip') + .customPosition(function (d) { + return { + top: 'inherit', + bottom: ($window.innerHeight - d3.event.clientY) + 'px', + right: ($window.innerWidth - d3.event.clientX) + 'px' + }; + }) + .html(function (d) { + return d.data.name; + }); + svg.call(tip); + } var circleGroup = g.selectAll("circle") .data(nodes) @@ -205,10 +199,10 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w var circle = circleGroup .append("circle") .attr("class", function (d) { - return d.role; + return d.data.role; }) .attr("guide-selector", function (d) { - return "class-" + d.name; + return "class-" + d.data.name; }) .style("fill", function (d) { //return colors[d.depth % 6]; @@ -216,8 +210,8 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w }) .each(function (d) { d.circle = d3.select(this); - if (d.name !== ROOT_OBJ_NAME) { - var key = d.name; + if (d.data.name !== ROOT_OBJ_NAME) { + var key = d.data.name; flattenedClassNames.push({name: key}); flattenedClassData[[key]] = d; @@ -266,13 +260,13 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w } var clickCancel = D3.Click.delayDblClick(); - var parentCircles = d3.selectAll(".parent, .topLevelParent, .child, .root") + d3.selectAll(".parent, .topLevelParent, .child, .root") .call(clickCancel); doFocus = function (obj) { zoom(obj); - if (obj.name === ROOT_OBJ_NAME) { + if (obj.data.name === ROOT_OBJ_NAME) { closeClassInfoPanel(); d3.selectAll(".selected").classed("selected", false); } else { @@ -291,8 +285,8 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w clickCancel.on("click", function (obj) { // add clicked class to browser history - if (obj.id) { - $window.history.pushState({id: obj.id}, "classHierarchyPage" + obj.id, "hierarchy#" + obj.id); + if (obj.data.id) { + $window.history.pushState({id: obj.data.id}, "classHierarchyPage" + obj.data.id, "hierarchy#" + obj.data.id); } //hide current d3-tip tooltip @@ -386,7 +380,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w } } - if (focus.name === ROOT_OBJ_NAME) { + if (focus.data.name === ROOT_OBJ_NAME) { $window.history.replaceState({id: 1}, "classHierarchyPage1", "hierarchy#1"); } @@ -405,22 +399,18 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w }); function trimPrefixes(d) { - var idx = d.name.indexOf(":"); - var absUriIdx = d.name.indexOf("http://"); + var idx = d.data.name.indexOf(":"); + var absUriIdx = d.data.name.indexOf("http://"); if (absUriIdx > -1) { // if we have no prefix available ignore - d.noPrefixName = d.name; + d.noPrefixName = d.data.name; } else if (idx > -1) { - d.noPrefixName = d.name.substring(idx + 1); + d.noPrefixName = d.data.name.substring(idx + 1); } } if (config.noPrefixes) { - if (oldRoot !== root) { - text.each(trimPrefixes); - oldRoot = root; - } - + text.each(trimPrefixes); text .style("font-size", function (d) { return D3.Text.calcFontSize(d.noPrefixName, d.r); @@ -431,16 +421,16 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w } else { text .style("font-size", function (d) { - return D3.Text.calcFontSize(d.name, d.r); + return D3.Text.calcFontSize(d.data.name, d.r); }) .text(function (d) { - return D3.Text.getTextWithElipsisIfNeeded(d.name, d.r / 3); + return D3.Text.getTextWithElipsisIfNeeded(d.data.name, d.r / 3); }) } // TODO: make this use the full version (same as zoom) text.style("display", function (d) { - if (d.parent === root) { + if (d.parent && d.parent.data === focus.data) { d.textHidden = this.textContent.indexOf("...") + 3 === this.textContent.length; return null; } else { @@ -459,7 +449,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w function focusOnCurrentClass(focusHistoryId) { if (focusHistoryId) { circle.each(function (d) { - if (focusHistoryId == d.id) { + if (+focusHistoryId === d.data.id) { doFocus(d); } }); @@ -497,7 +487,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // or your focus is a top level parent hide its label and if it is not // a child element show all of its child labels. If it is a child element // only show its label. - if (d.fullName === focus.topLevelParentUri || focus.topLevelParentUri === ROOT_OBJ_NAME) { + if (d.data.fullName === focus.data.topLevelParentUri || focus.data.topLevelParentUri === ROOT_OBJ_NAME) { d.textSel.style("display", "none"); if (focus.children && focus.children.length) { _.each(focus.children, function (c) { @@ -513,7 +503,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // its children if (focus.parent) { _.each(focus.parent.children, function (c) { - if (c.name !== focus.name) { + if (c.data.name !== focus.data.name) { c.textSel.style("display", "inline"); } }); @@ -530,13 +520,13 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w if (config.noPrefixes) { return D3.Text.calcFontSize(d.noPrefixName, d.r * k); } - return D3.Text.calcFontSize(d.name, d.r * k); + return D3.Text.calcFontSize(d.data.name, d.r * k); }) .text(function (d) { if (config.noPrefixes) { return D3.Text.getTextWithElipsisIfNeeded(d.noPrefixName, d.r * k / 3); } - return D3.Text.getTextWithElipsisIfNeeded(d.name, d.r * k / 3); + return D3.Text.getTextWithElipsisIfNeeded(d.data.name, d.r * k / 3); }); } @@ -552,18 +542,11 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w zoomTo([focus.x, focus.y, adjustRadius(focus.r)], switchPrefixes); - function textUpdateStart(d) { + function textUpdate(d) { if (d.isInFocusTransitive || !(d.parent && d.parent.isInFocusTransitive)) { // hide labels of classes that are in focus (including children) OR whose parents aren't in focus d.textHidden = true; this.style.display = "none"; - } - } - - function textUpdateEnd(d) { - if (d.isInFocusTransitive || !(d.parent && d.parent.isInFocusTransitive)) { - // hide labels of classes that are in focus (including children) OR whose parents aren't in focus - // this.style.display = "none"; } else { // show all other labels d.textHidden = this.textContent.indexOf("...") + 3 === this.textContent.length; @@ -575,7 +558,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // use empty timeout to force the following code to be executed on the next $digest cycle // in order to avoid '$digest in progress' error $timeout(function () { - scope.showExternalElements = (d.name === ROOT_OBJ_NAME); + scope.showExternalElements = (d.data.name === ROOT_OBJ_NAME); }); if (focus === d) { @@ -584,8 +567,8 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w return; } - if (d.id) { - $window.history.replaceState({id: d.id}, "classHierarchyPage" + d.id, "hierarchy#" + d.id); + if (d.data.id) { + $window.history.replaceState({id: d.data.id}, "classHierarchyPage" + d.data.id, "hierarchy#" + d.data.id); } if (!d.children) { @@ -612,7 +595,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w var p = d; while (p) { - p.isInFocusTransitive = p.children; + p.isInFocusTransitive = !!p.children; p = p.parent; } @@ -625,8 +608,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w zoomTo([focus.x, focus.y, adjustRadius(focus.r)]); text.each(function (d) { - textUpdateStart.call(this, d); - textUpdateEnd.call(this, d); + textUpdate.call(this, d) }); } else { // the fancy version for faster browsers @@ -641,14 +623,13 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w transition.selectAll("text") // Experimental: hide texts to be hidden on "start", show texts to be shown on "end" - .each("start", textUpdateStart) - .each("end", textUpdateEnd); + .each(textUpdate) } } rootFocusEvent = scope.$on('rootFocus', function () { $window.history.pushState({id: 1}, "classHierarchyPage1", "hierarchy#1"); - doFocus(root); + doFocus(rootHierarchy); }); classSearchEvent = scope.$on('classSearch', function (selectedClass) { @@ -657,7 +638,7 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w } function sendSliderData() { - var currentClassCount = scope.classHierarchyData.classCount; + const currentClassCount = scope.classHierarchyData.classCount; let currentSliderValue = LocalStorageAdapter.get(LSKeys.CLASS_HIERARCHY_CURRENT_SLIDER_VALUE); if (!currentSliderValue || currentSliderValue > currentClassCount) { @@ -696,21 +677,23 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w if (scope.classHierarchyData.classCount) { sendSliderData(); - var root = angular.copy(scope.classHierarchyData); + var rootData = angular.copy(scope.classHierarchyData); + + var root = d3.hierarchy(rootData); function sortRoot(root) { // add all classes to a flat array, add parent information // and sort according to instancesCount DESC, depth ASC - return pack - .nodes(root) + + return root.descendants() .sort(function (a, b) { - if (a.sortingRank > b.sortingRank) { + if (a.data.sortingRank > b.data.sortingRank) { return -1; - } else if (a.sortingRank < b.sortingRank) { + } else if (a.data.sortingRank < b.data.sortingRank) { return 1; - } else if (a.depth > b.depth) { + } else if (a.data.depth > b.data.depth) { return 1; - } else if (a.depth < b.depth) { + } else if (a.data.depth < b.data.depth) { return -1; } else { return 0; @@ -718,15 +701,15 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w }); } - var sorted = sortRoot(root); + var sortedChildren = sortRoot(root); - // we start with an empty new root - var newRoot; + // we start with an empty new rootData + var filteredRootData; var noPrefixesGlobal; - function restoreDiagramState(currentRoot, switchPrefixes) { - var prefixesConfig = { + function restoreDiagramState(currentRootData, switchPrefixes) { + const prefixesConfig = { keepPrevState: true, noPrefixes: getPrefixesState() }; @@ -734,10 +717,10 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // get noPrefixes flag from drawDiagram configuration params noPrefixesGlobal = prefixesConfig.noPrefixes; - if (newRoot) { - drawDiagram(newRoot, prefixesConfig, focus, true); + if (filteredRootData) { + drawDiagram(filteredRootData, prefixesConfig, focus, true); } else { - drawDiagram(currentRoot, prefixesConfig, focus, true); + drawDiagram(currentRootData, prefixesConfig, focus, true); } $timeout(function () { @@ -746,76 +729,76 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w }, 70); } - function redrawFilteredDiagram(currentSliderValue, sortedRoot, useSlider) { + function redrawFilteredDiagram(currentSliderValue, sortedChildrenArray, useSlider) { if (!currentSliderValue) { return; } LocalStorageAdapter.set(LSKeys.CLASS_HIERARCHY_CURRENT_SLIDER_VALUE, currentSliderValue); - newRoot = { + filteredRootData = { name: ROOT_OBJ_NAME, children: [] }; - // walk through the given count of (sorted) classes + // walk through the given count of (sortedChildrenArray) classes // - record the id of each class we've seen - // - add the root level classes to the new root - var addedIds = new Set(); - for (var k = 1; k <= currentSliderValue; k++) { - addedIds.add(sortedRoot[k].id); - if (sortedRoot[k].parent === sortedRoot[0]) { // i.e. the parent is the "class hierarchy" - newRoot.children.push(sortedRoot[k]); + // - add the rootData level classes to the new rootData + const addedIds = new Set(); + for (let k = 1; k <= currentSliderValue; k++) { + addedIds.add(sortedChildrenArray[k].data.id); + if (sortedChildrenArray[k].parent === sortedChildrenArray[0]) { // i.e. the parent is the "class hierarchy" + filteredRootData.children.push(sortedChildrenArray[k].data); } } - // walk through all the classes in the new root and only keep those that have an "added id" + // walk through all the classes in the new rootData and only keep those that have an "added id" // we create separate copies of the arrays in order not to contaminate the original data // we also copy each class's object ($.extend ...) for the same reason function fixChildren(node) { if (!node.children) { return; } - var newChildren = []; - for (var i = 0; i < node.children.length; i++) { - if (addedIds.has(node.children[i].id)) { - newChildren.push($.extend({}, node.children[i])); + const newChildren = []; + for (const child of node.children) { + if (addedIds.has(child.id)) { + newChildren.push($.extend({}, child)); } } node.children = newChildren; - for (var i = 0; i < node.children.length; i++) { - fixChildren(node.children[i]); + for (const child of node.children) { + fixChildren(child); } } - fixChildren(newRoot); + fixChildren(filteredRootData); if (useSlider) { // redraw diagram when slider value changes and persist current state // in local storage noPrefixesGlobal = angular.isUndefined(noPrefixesGlobal) ? getPrefixesState() : noPrefixesGlobal; - var redrawConfig = { + const redrawConfig = { noPrefixes: noPrefixesGlobal }; - drawDiagram(newRoot, redrawConfig); + drawDiagram(filteredRootData, redrawConfig); } else { // if the user returns to the diagram with back browser button // read the saved state (show/hide prefixes, current slider value) // from local storage and render the diagram according to the saved metrics - restoreDiagramState(root); + restoreDiagramState(rootData); } } var currentSliderValue = LocalStorageAdapter.get(LSKeys.CLASS_HIERARCHY_CURRENT_SLIDER_VALUE); if (currentSliderValue) { - redrawFilteredDiagram(currentSliderValue, sorted); + redrawFilteredDiagram(currentSliderValue, sortedChildren); } else { var basicConfig = { doFade: true, keepPrevState: true, noPrefixes: getPrefixesState() }; - drawDiagram(root, basicConfig); + drawDiagram(rootData, basicConfig); autoZoomToPreviousState(); } @@ -827,12 +810,12 @@ function classHierarchyDirective($rootScope, $location, GraphDataRestService, $w // if digest overflows a possible fix might be wrapping this in $timeout $timeout(function () { savePrefixesState(hidePrefixes); - restoreDiagramState(root, true); + restoreDiagramState(rootData, true); }, 50); }, true); currentClassCountWatch = scope.$watch('currentSliderValue', function (currentSliderValue) { - redrawFilteredDiagram(currentSliderValue, sorted, true); + redrawFilteredDiagram(currentSliderValue, sortedChildren, true); }, true); // we handle this event for the cases where we already have searched for a given class and diff --git a/src/js/angular/guides/guide-utils.js b/src/js/angular/guides/guide-utils.js index fdb3b4bc9..973a25a05 100644 --- a/src/js/angular/guides/guide-utils.js +++ b/src/js/angular/guides/guide-utils.js @@ -78,10 +78,10 @@ const GuideUtils = (function () { * @param {string | null} elementSelector - a node selector. * @param {*}scope scope where the d3alpha property is set * @param {number} timeoutInSeconds maximum wait time for the alpha value to settle, the default is 2 seconds - * @param {number} alphaThreshold alpha value threshold, the default is 0.02 + * @param {number} alphaThreshold alpha value threshold, the default is 0.1 * @return {function(): Promise} */ - const awaitAlphaDropD3 = function (elementSelector, scope, timeoutInSeconds = 2, alphaThreshold = 0.02) { + const awaitAlphaDropD3 = function (elementSelector, scope, timeoutInSeconds = 2, alphaThreshold = 0.1) { return () => new Promise(function(resolve) { if (isVisible(elementSelector)) { resolve(); diff --git a/src/js/angular/resources/app.js b/src/js/angular/resources/app.js index 9c5fa707d..7351f6622 100644 --- a/src/js/angular/resources/app.js +++ b/src/js/angular/resources/app.js @@ -2,7 +2,6 @@ import 'angular/core/services'; import 'angular/core/directives'; import 'angular/resources/controllers'; import 'angular/core/services/repositories.service'; -import 'd3/build/d3'; import 'angular-nvd3-charts'; const modules = [ diff --git a/src/js/lib/common/circle-packing.js b/src/js/lib/common/circle-packing.js index 67452370e..679688c4f 100644 --- a/src/js/lib/common/circle-packing.js +++ b/src/js/lib/common/circle-packing.js @@ -29,7 +29,7 @@ CirclePacking.SingleChild = function () { for (var i = nodes.length - 1; i >= 0; i--) { var node = nodes[i]; - if (node.name === 'placeholder') { + if (node.data.name === 'placeholder') { nodes.splice(i, 1); } else { if (node.children) { diff --git a/src/js/lib/common/d3-utils.js b/src/js/lib/common/d3-utils.js index f70455c50..ce8229899 100644 --- a/src/js/lib/common/d3-utils.js +++ b/src/js/lib/common/d3-utils.js @@ -1,3 +1,5 @@ +import 'lib/d3.patch.js' + var D3 = D3 || {}; D3.Text = function () { @@ -110,11 +112,11 @@ D3.Click = function () { if (wait) { window.clearTimeout(wait); wait = null; - event.dblclick(d); + event.call('dblclick', d3.event, d); } else { wait = window.setTimeout((function (e) { return function () { - event.click(d); + event.call('click', e, d) wait = null; }; })(d3.event), 250); @@ -123,7 +125,27 @@ D3.Click = function () { }); } - return d3.rebind(cc, event, 'on'); + return rebind(cc, event, 'on'); + } + + // Copies a variable number of methods from source to target. + const rebind = function (target, source) { + let i = 1, n = arguments.length, method; + while (++i < n) { + method = arguments[i] + target[method] = d3_rebind(target, source, source[method]); + } + return target; + } + + // Method is assumed to be a standard D3 getter-setter: + // If passed with no arguments, gets the value. + // If passed with arguments, sets the value and returns the target. + function d3_rebind(target, source, method) { + return function () { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; } return { diff --git a/src/js/lib/common/svg-export.js b/src/js/lib/common/svg-export.js index ea0133860..6c7dfb6a7 100644 --- a/src/js/lib/common/svg-export.js +++ b/src/js/lib/common/svg-export.js @@ -1,4 +1,4 @@ -import * as d3 from "d3/build/d3"; +import 'lib/d3.patch.js' var SVG = SVG || {}; diff --git a/src/js/lib/d3-tip/d3-tip-patch.js b/src/js/lib/d3-tip/d3-tip-patch.js index 5ee4c0c05..6bb64b851 100644 --- a/src/js/lib/d3-tip/d3-tip-patch.js +++ b/src/js/lib/d3-tip/d3-tip-patch.js @@ -3,335 +3,335 @@ // // Tooltips for d3.js SVG visualizations -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module with d3 as a dependency. - define([], factory) - } else if (typeof module === 'object' && module.exports) { - // CommonJS - module.exports = function(d3) { - d3.tip = factory(d3) - return d3.tip - } - } else { - // Browser global. - root.d3.tip = factory(root.d3) +// Public - contructs a new tooltip +// +// Returns a tip +var d3tip = function () { + var direction = d3_tip_direction, + offset = d3_tip_offset, + html = d3_tip_html, + node = initNode(), + svg = null, + point = null, + target = null, + customPosition = null + + function tip(vis) { + svg = getSVGNode(vis) + point = svg.createSVGPoint() + document.body.appendChild(node) } -}(this, function () { - // Public - contructs a new tooltip + + // Public - show the tooltip on the screen // // Returns a tip - return function() { - var direction = d3_tip_direction, - offset = d3_tip_offset, - html = d3_tip_html, - node = initNode(), - svg = null, - point = null, - target = null, - customPosition = null - - function tip(vis) { - svg = getSVGNode(vis) - point = svg.createSVGPoint() - document.body.appendChild(node) + tip.show = function () { + var args = Array.prototype.slice.call(arguments) + if (args[args.length - 1] instanceof SVGElement) target = args.pop() + + var content = html.apply(this, args), + poffset = offset.apply(this, args), + dir = direction.apply(this, args), + nodel = getNodeEl(), + i = directions.length, + coords, + scrollTop = document.documentElement.scrollTop || document.body.scrollTop, + scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft, + customPos = customPosition.apply(this, args) + + nodel.html(content) + .style('opacity', 1) + .style('pointer-events', 'all') + + while (i--) nodel.classed(directions[i], false) + coords = direction_callbacks.get(dir).apply(this) + + if (customPos) { + Object.keys(customPos).forEach(function (key) { + nodel.style(key, customPos[key]); + }) + } else { + nodel.classed(dir, true) + .style("top", (coords.top + poffset[0]) + scrollTop + 'px') + .style("left", (coords.left + poffset[1]) + scrollLeft + 'px') } - // Public - show the tooltip on the screen - // - // Returns a tip - tip.show = function() { + return tip + } + + // Public - hide the tooltip + // + // Returns a tip + tip.hide = function () { + var nodel = getNodeEl() + nodel + .style('opacity', 0) + .style('pointer-events', 'none') + + return tip + } + + // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. + // + // n - name of the attribute + // v - value of the attribute + // + // Returns tip or attribute value + tip.attr = function (n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return getNodeEl().attr(n) + } else { var args = Array.prototype.slice.call(arguments) - if(args[args.length - 1] instanceof SVGElement) target = args.pop() - - var content = html.apply(this, args), - poffset = offset.apply(this, args), - dir = direction.apply(this, args), - nodel = getNodeEl(), - i = directions.length, - coords, - scrollTop = document.documentElement.scrollTop || document.body.scrollTop, - scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft, - customPos = customPosition.apply(this, args) - - nodel.html(content) - .style({ opacity: 1, 'pointer-events': 'all' }) - - while(i--) nodel.classed(directions[i], false) - coords = direction_callbacks.get(dir).apply(this) - - if (customPos) { - nodel.style(customPos) - } else { - nodel.classed(dir, true).style({ - top: (coords.top + poffset[0]) + scrollTop + 'px', - left: (coords.left + poffset[1]) + scrollLeft + 'px' - }) - } - - return tip + d3.selection.prototype.attr.apply(getNodeEl(), args) } - // Public - hide the tooltip - // - // Returns a tip - tip.hide = function() { - var nodel = getNodeEl() - nodel.style({ opacity: 0, 'pointer-events': 'none' }) - return tip - } + return tip + } - // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. - // - // n - name of the attribute - // v - value of the attribute - // - // Returns tip or attribute value - tip.attr = function(n, v) { - if (arguments.length < 2 && typeof n === 'string') { - return getNodeEl().attr(n) - } else { - var args = Array.prototype.slice.call(arguments) - d3.selection.prototype.attr.apply(getNodeEl(), args) - } - - return tip + // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. + // + // n - name of the property + // v - value of the property + // + // Returns tip or style property value + tip.style = function (n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return getNodeEl().style(n) + } else { + var args = Array.prototype.slice.call(arguments) + d3.selection.prototype.style.apply(getNodeEl(), args) } - // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. - // - // n - name of the property - // v - value of the property - // - // Returns tip or style property value - tip.style = function(n, v) { - if (arguments.length < 2 && typeof n === 'string') { - return getNodeEl().style(n) - } else { - var args = Array.prototype.slice.call(arguments) - d3.selection.prototype.style.apply(getNodeEl(), args) - } - - return tip - } + return tip + } - // Public: Set or get the direction of the tooltip - // - // v - One of n(north), s(south), e(east), or w(west), nw(northwest), - // sw(southwest), ne(northeast) or se(southeast) - // - // Returns tip or direction - tip.direction = function(v) { - if (!arguments.length) return direction - direction = v == null ? v : d3.functor(v) - - return tip - } + // Public: Set or get the direction of the tooltip + // + // v - One of n(north), s(south), e(east), or w(west), nw(northwest), + // sw(southwest), ne(northeast) or se(southeast) + // + // Returns tip or direction + tip.direction = function (v) { + if (!arguments.length) return direction + direction = v == null ? v : d3_functor(v) - // Public: Sets or gets the offset of the tip - // - // v - Array of [x, y] offset - // - // Returns offset or - tip.offset = function(v) { - if (!arguments.length) return offset - offset = v == null ? v : d3.functor(v) + return tip + } - return tip - } + // Public: Sets or gets the offset of the tip + // + // v - Array of [x, y] offset + // + // Returns offset or + tip.offset = function (v) { + if (!arguments.length) return offset + offset = v == null ? v : d3_functor(v) - // Public: sets or gets the html value of the tooltip - // - // v - String value of the tip - // - // Returns html value or tip - tip.html = function(v) { - if (!arguments.length) return html - html = v == null ? v : d3.functor(v) + return tip + } - return tip - } + // Public: sets or gets the html value of the tooltip + // + // v - String value of the tip + // + // Returns html value or tip + tip.html = function (v) { + if (!arguments.length) return html + html = v == null ? v : d3_functor(v) - tip.customPosition = function(v) { - if (!arguments.length) return customPosition - customPosition = v == null ? v : d3.functor(v) + return tip + } - return tip - } + tip.customPosition = function (v) { + if (!arguments.length) return customPosition + customPosition = v == null ? v : d3_functor(v) + + return tip + } - // Public: destroys the tooltip and removes it from the DOM - // - // Returns a tip - tip.destroy = function() { - if(node) { - getNodeEl().remove(); - node = null; - } - return tip; + // Public: destroys the tooltip and removes it from the DOM + // + // Returns a tip + tip.destroy = function () { + if (node) { + getNodeEl().remove(); + node = null; } + return tip; + } - function d3_tip_direction() { return 'n' } - function d3_tip_offset() { return [0, 0] } - function d3_tip_html() { return ' ' } - - var direction_callbacks = d3.map({ - n: direction_n, - s: direction_s, - e: direction_e, - w: direction_w, - nw: direction_nw, - ne: direction_ne, - sw: direction_sw, - se: direction_se - }), - - directions = direction_callbacks.keys() - - function direction_n() { - var bbox = getScreenBBox() - return { - top: bbox.n.y - node.offsetHeight, - left: bbox.n.x - node.offsetWidth / 2 - } + function d3_tip_direction() { + return 'n' + } + + function d3_tip_offset() { + return [0, 0] + } + + function d3_tip_html() { + return ' ' + } + + var direction_callbacks = d3.map({ + n: direction_n, + s: direction_s, + e: direction_e, + w: direction_w, + nw: direction_nw, + ne: direction_ne, + sw: direction_sw, + se: direction_se + }), + + directions = direction_callbacks.keys() + + function direction_n() { + var bbox = getScreenBBox() + return { + top: bbox.n.y - node.offsetHeight, + left: bbox.n.x - node.offsetWidth / 2 } + } - function direction_s() { - var bbox = getScreenBBox() - return { - top: bbox.s.y, - left: bbox.s.x - node.offsetWidth / 2 - } + function direction_s() { + var bbox = getScreenBBox() + return { + top: bbox.s.y, + left: bbox.s.x - node.offsetWidth / 2 } + } - function direction_e() { - var bbox = getScreenBBox() - return { - top: bbox.e.y - node.offsetHeight / 2, - left: bbox.e.x - } + function direction_e() { + var bbox = getScreenBBox() + return { + top: bbox.e.y - node.offsetHeight / 2, + left: bbox.e.x } + } - function direction_w() { - var bbox = getScreenBBox() - return { - top: bbox.w.y - node.offsetHeight / 2, - left: bbox.w.x - node.offsetWidth - } + function direction_w() { + var bbox = getScreenBBox() + return { + top: bbox.w.y - node.offsetHeight / 2, + left: bbox.w.x - node.offsetWidth } + } - function direction_nw() { - var bbox = getScreenBBox() - return { - top: bbox.nw.y - node.offsetHeight, - left: bbox.nw.x - node.offsetWidth - } + function direction_nw() { + var bbox = getScreenBBox() + return { + top: bbox.nw.y - node.offsetHeight, + left: bbox.nw.x - node.offsetWidth } + } - function direction_ne() { - var bbox = getScreenBBox() - return { - top: bbox.ne.y - node.offsetHeight, - left: bbox.ne.x - } + function direction_ne() { + var bbox = getScreenBBox() + return { + top: bbox.ne.y - node.offsetHeight, + left: bbox.ne.x } + } - function direction_sw() { - var bbox = getScreenBBox() - return { - top: bbox.sw.y, - left: bbox.sw.x - node.offsetWidth - } + function direction_sw() { + var bbox = getScreenBBox() + return { + top: bbox.sw.y, + left: bbox.sw.x - node.offsetWidth } + } - function direction_se() { - var bbox = getScreenBBox() - return { - top: bbox.se.y, - left: bbox.e.x - } + function direction_se() { + var bbox = getScreenBBox() + return { + top: bbox.se.y, + left: bbox.e.x } + } - function initNode() { - var node = d3.select(document.createElement('div')) - node.style({ - position: 'absolute', - top: 0, - opacity: 0, - 'pointer-events': 'none', - 'box-sizing': 'border-box' - }) + function initNode() { + var node = d3.select(document.createElement('div')) + node.style("position", 'absolute') + .style("top", 0) + .style("opacity", 0) + .style("pointer-events", 'none') + .style("box-sizing", 'border-box'); - return node.node() - } + return node.node() + } - function getSVGNode(el) { - el = el.node() - if(el.tagName.toLowerCase() === 'svg') - return el + function getSVGNode(el) { + el = el.node() + if (el.tagName.toLowerCase() === 'svg') + return el - return el.ownerSVGElement - } + return el.ownerSVGElement + } - function getNodeEl() { - if(node === null) { - node = initNode(); - // re-add node to DOM - document.body.appendChild(node); - }; - return d3.select(node); + function getNodeEl() { + if (node === null) { + node = initNode(); + // re-add node to DOM + document.body.appendChild(node); } + ; + return d3.select(node); + } + + // Private - gets the screen coordinates of a shape + // + // Given a shape on the screen, will return an SVGPoint for the directions + // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), + // sw(southwest). + // + // +-+-+ + // | | + // + + + // | | + // +-+-+ + // + // Returns an Object {n, s, e, w, nw, sw, ne, se} + function getScreenBBox() { + var targetel = target || d3.event.target; - // Private - gets the screen coordinates of a shape - // - // Given a shape on the screen, will return an SVGPoint for the directions - // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), - // sw(southwest). - // - // +-+-+ - // | | - // + + - // | | - // +-+-+ - // - // Returns an Object {n, s, e, w, nw, sw, ne, se} - function getScreenBBox() { - var targetel = target || d3.event.target; - - while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) { - targetel = targetel.parentNode; - } - - var bbox = {}, - matrix = targetel.getScreenCTM(), - tbbox = targetel.getBBox(), - width = tbbox.width, - height = tbbox.height, - x = tbbox.x, - y = tbbox.y - - point.x = x - point.y = y - bbox.nw = point.matrixTransform(matrix) - point.x += width - bbox.ne = point.matrixTransform(matrix) - point.y += height - bbox.se = point.matrixTransform(matrix) - point.x -= width - bbox.sw = point.matrixTransform(matrix) - point.y -= height / 2 - bbox.w = point.matrixTransform(matrix) - point.x += width - bbox.e = point.matrixTransform(matrix) - point.x -= width / 2 - point.y -= height / 2 - bbox.n = point.matrixTransform(matrix) - point.y += height - bbox.s = point.matrixTransform(matrix) - - return bbox + while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) { + targetel = targetel.parentNode; } - return tip - }; + var bbox = {}, + matrix = targetel.getScreenCTM(), + tbbox = targetel.getBBox(), + width = tbbox.width, + height = tbbox.height, + x = tbbox.x, + y = tbbox.y + + point.x = x + point.y = y + bbox.nw = point.matrixTransform(matrix) + point.x += width + bbox.ne = point.matrixTransform(matrix) + point.y += height + bbox.se = point.matrixTransform(matrix) + point.x -= width + bbox.sw = point.matrixTransform(matrix) + point.y -= height / 2 + bbox.w = point.matrixTransform(matrix) + point.x += width + bbox.e = point.matrixTransform(matrix) + point.x -= width / 2 + point.y -= height / 2 + bbox.n = point.matrixTransform(matrix) + point.y += height + bbox.s = point.matrixTransform(matrix) + + return bbox + } + + function d3_functor(v) { + return typeof v === "function" ? v : function() { return v; }; + } -})); \ No newline at end of file + return tip +}; +export default d3tip; diff --git a/src/js/lib/d3.patch.js b/src/js/lib/d3.patch.js new file mode 100644 index 000000000..4a9070ec7 --- /dev/null +++ b/src/js/lib/d3.patch.js @@ -0,0 +1,46 @@ +define(['d3/build/d3'], + function() { + /* nvd3 version 1.8.6 (https://github.com/novus/nvd3) 2017-08-23 */ + (function() { + + // Node/CommonJS - require D3 + if (typeof (module) !== 'undefined' && typeof (exports) !== 'undefined' && typeof (d3) == 'undefined') { + d3 = require('d3'); + } + })(); + + function attrsFunction(selection, map) { + return selection.each(function () { + var x = map.apply(this, arguments), s = select(this); + for (var name in x) s.attr(name, x[name]); + }); + } + + function attrsObject(selection, map) { + for (var name in map) selection.attr(name, map[name]); + return selection; + } + + function selection_attrs(map) { + return (typeof map === "function" ? attrsFunction : attrsObject)(this, map); + } + + d3.selection.prototype.attrs = selection_attrs + + d3.selection.prototype.moveToFront = function () { + return this.each(function () { + d3.select(this.parentNode.appendChild(this)); + }); + }; + + d3.selection.prototype.moveToBack = function () { + return this.each(function () { + const firstChild = this.parentNode.firstChild; + if (firstChild) { + this.parentNode.insertBefore(this, firstChild); + } + }); + }; + + return d3; + }); diff --git a/src/pages/rdfClassHierarchyInfo.html b/src/pages/rdfClassHierarchyInfo.html index a794e77de..e34926a55 100644 --- a/src/pages/rdfClassHierarchyInfo.html +++ b/src/pages/rdfClassHierarchyInfo.html @@ -152,9 +152,9 @@

ng-click="toggleClassInfoSidePanel(); $event.stopPropagation();" guide-selector="close-info-panel">

- {{selectedClass.name}} + {{selectedClass.data.name}} @@ -171,17 +171,17 @@

expanded="expanded"> -
+

{{'no.instances.for.selected.class.type' | translate}}

{{'view.instance.in.sparql.label' | translate}}

-

{{'view.all.label' | translate}} {{selectedClass.instancesCount | number}} {{'instances.in.sparql' | translate}}

+

{{'view.all.label' | translate}} {{selectedClass.data.instancesCount | number}} {{'instances.in.sparql' | translate}}

-
+
{ cy.visit('graphs-visualizations'); getCreateCustomGraphLink().click(); cy.url().should('include', '/config/save'); - getGraphConfigName().type(graphConfigName); cy.get('[data-cy="graph-config-by-graph-query-checkbox"]').check(); - cy.pasteQuery('CONSTRUCT WHERE {?s ?p ?o} LIMIT 10').then( () => { - getSaveConfig().click(); - } - ); + getGraphConfigName().type(graphConfigName, {force: true}); + + cy.waitUntil(() => getGraphConfigName().should('have.value', graphConfigName)); + cy.pasteQuery('CONSTRUCT WHERE {?s ?p ?o} LIMIT 10'); + cy.waitUntilQueryIsVisible(); + getSaveConfig().click(); cy.url().should('include', 'graphs-visualizations'); cy.contains('td', graphConfigName).should('be.visible').parent().within(() => { diff --git a/test-cypress/integration/explore/class.hierarchy.spec.js b/test-cypress/integration/explore/class.hierarchy.spec.js index 5b825b720..9deb355c9 100644 --- a/test-cypress/integration/explore/class.hierarchy.spec.js +++ b/test-cypress/integration/explore/class.hierarchy.spec.js @@ -242,7 +242,7 @@ describe('Class hierarchy screen validation', () => { cy.get(CLASS_LABEL_SELECTOR) .each(($element) => { let data = $element.prop('__data__'); - if (data.name === className) { + if (data.data.name === className) { cy.wrap($element).as('classInHierarchy'); } }); diff --git a/test-cypress/integration/explore/visual.graph.spec.js b/test-cypress/integration/explore/visual.graph.spec.js index 8ccd93f3f..21fe1c8aa 100644 --- a/test-cypress/integration/explore/visual.graph.spec.js +++ b/test-cypress/integration/explore/visual.graph.spec.js @@ -231,9 +231,7 @@ describe('Visual graph screen validation', () => { // Double click on collapsed node // This is ugly but unfortunately I couldn't make cypress's dblclick to work reliably here - getTargetNodeElement().click().then(() => { - getTargetNodeElement().click(); - }); + getTargetNodeElement().dblclick() // Verify that all links to the USRegion node are expanded getPredicates().should('have.length', 3);