Compare commits
	
		
			3 Commits
		
	
	
		
			4c014a7200
			...
			0ab53c1800
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0ab53c1800 | |||
| 8a272a9626 | |||
| 4137362501 | 
| @ -123,6 +123,10 @@ const resolve = (plugins = []) => { | ||||
| 
 | ||||
|     let res = { | ||||
|         extensions: [ ".tsx", '.ts', '.js' ], | ||||
|         fallback: { | ||||
|             'react/jsx-runtime': 'react/jsx-runtime.js', | ||||
|             'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js', | ||||
|         }, | ||||
|         plugins: plugins | ||||
|     }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										190
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										190
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -16,6 +16,8 @@ | ||||
|         "express": "^4.17.3", | ||||
|         "gl-matrix": "^3.4.3", | ||||
|         "react": "^17.0.2", | ||||
|         "react-dnd": "^16.0.1", | ||||
|         "react-dnd-html5-backend": "^16.0.1", | ||||
|         "react-dom": "^17.0.2", | ||||
|         "uuid": "^8.3.2" | ||||
|       }, | ||||
| @ -726,6 +728,17 @@ | ||||
|         "node": ">=4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@babel/runtime": { | ||||
|       "version": "7.17.9", | ||||
|       "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz", | ||||
|       "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", | ||||
|       "dependencies": { | ||||
|         "regenerator-runtime": "^0.13.4" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=6.9.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@discoveryjs/json-ext": { | ||||
|       "version": "0.5.6", | ||||
|       "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", | ||||
| @ -1023,6 +1036,21 @@ | ||||
|         "node": ">=10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@react-dnd/asap": { | ||||
|       "version": "5.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/asap/-/asap-5.0.2.tgz", | ||||
|       "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" | ||||
|     }, | ||||
|     "node_modules/@react-dnd/invariant": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/invariant/-/invariant-4.0.2.tgz", | ||||
|       "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" | ||||
|     }, | ||||
|     "node_modules/@react-dnd/shallowequal": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", | ||||
|       "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" | ||||
|     }, | ||||
|     "node_modules/@sindresorhus/is": { | ||||
|       "version": "0.14.0", | ||||
|       "resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz", | ||||
| @ -1195,7 +1223,7 @@ | ||||
|       "version": "17.0.21", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", | ||||
|       "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", | ||||
|       "dev": true | ||||
|       "devOptional": true | ||||
|     }, | ||||
|     "node_modules/@types/normalize-package-data": { | ||||
|       "version": "2.4.1", | ||||
| @ -2817,6 +2845,16 @@ | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dnd-core": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/dnd-core/-/dnd-core-16.0.1.tgz", | ||||
|       "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", | ||||
|       "dependencies": { | ||||
|         "@react-dnd/asap": "^5.0.1", | ||||
|         "@react-dnd/invariant": "^4.0.1", | ||||
|         "redux": "^4.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dns-equal": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", | ||||
| @ -3317,8 +3355,7 @@ | ||||
|     "node_modules/fast-deep-equal": { | ||||
|       "version": "3.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", | ||||
|       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", | ||||
|       "dev": true | ||||
|       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" | ||||
|     }, | ||||
|     "node_modules/fast-glob": { | ||||
|       "version": "3.2.11", | ||||
| @ -3945,6 +3982,14 @@ | ||||
|         "he": "bin/he" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/hoist-non-react-statics": { | ||||
|       "version": "3.3.2", | ||||
|       "resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", | ||||
|       "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", | ||||
|       "dependencies": { | ||||
|         "react-is": "^16.7.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/hosted-git-info": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", | ||||
| @ -6164,6 +6209,43 @@ | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/react-dnd": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-dnd/-/react-dnd-16.0.1.tgz", | ||||
|       "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", | ||||
|       "dependencies": { | ||||
|         "@react-dnd/invariant": "^4.0.1", | ||||
|         "@react-dnd/shallowequal": "^4.0.1", | ||||
|         "dnd-core": "^16.0.1", | ||||
|         "fast-deep-equal": "^3.1.3", | ||||
|         "hoist-non-react-statics": "^3.3.2" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "@types/hoist-non-react-statics": ">= 3.3.1", | ||||
|         "@types/node": ">= 12", | ||||
|         "@types/react": ">= 16", | ||||
|         "react": ">= 16.14" | ||||
|       }, | ||||
|       "peerDependenciesMeta": { | ||||
|         "@types/hoist-non-react-statics": { | ||||
|           "optional": true | ||||
|         }, | ||||
|         "@types/node": { | ||||
|           "optional": true | ||||
|         }, | ||||
|         "@types/react": { | ||||
|           "optional": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/react-dnd-html5-backend": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", | ||||
|       "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", | ||||
|       "dependencies": { | ||||
|         "dnd-core": "^16.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/react-dom": { | ||||
|       "version": "17.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", | ||||
| @ -6177,6 +6259,11 @@ | ||||
|         "react": "17.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/react-is": { | ||||
|       "version": "16.13.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", | ||||
|       "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" | ||||
|     }, | ||||
|     "node_modules/read-pkg": { | ||||
|       "version": "5.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", | ||||
| @ -6305,6 +6392,19 @@ | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/redux": { | ||||
|       "version": "4.2.0", | ||||
|       "resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.0.tgz", | ||||
|       "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", | ||||
|       "dependencies": { | ||||
|         "@babel/runtime": "^7.9.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/regenerator-runtime": { | ||||
|       "version": "0.13.9", | ||||
|       "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", | ||||
|       "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" | ||||
|     }, | ||||
|     "node_modules/regexp.prototype.flags": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", | ||||
| @ -8767,6 +8867,14 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@babel/runtime": { | ||||
|       "version": "7.17.9", | ||||
|       "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.9.tgz", | ||||
|       "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", | ||||
|       "requires": { | ||||
|         "regenerator-runtime": "^0.13.4" | ||||
|       } | ||||
|     }, | ||||
|     "@discoveryjs/json-ext": { | ||||
|       "version": "0.5.6", | ||||
|       "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", | ||||
| @ -9013,6 +9121,21 @@ | ||||
|         "rimraf": "^3.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "@react-dnd/asap": { | ||||
|       "version": "5.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/asap/-/asap-5.0.2.tgz", | ||||
|       "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" | ||||
|     }, | ||||
|     "@react-dnd/invariant": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/invariant/-/invariant-4.0.2.tgz", | ||||
|       "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" | ||||
|     }, | ||||
|     "@react-dnd/shallowequal": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmmirror.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", | ||||
|       "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" | ||||
|     }, | ||||
|     "@sindresorhus/is": { | ||||
|       "version": "0.14.0", | ||||
|       "resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz", | ||||
| @ -9176,7 +9299,7 @@ | ||||
|       "version": "17.0.21", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", | ||||
|       "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", | ||||
|       "dev": true | ||||
|       "devOptional": true | ||||
|     }, | ||||
|     "@types/normalize-package-data": { | ||||
|       "version": "2.4.1", | ||||
| @ -10488,6 +10611,16 @@ | ||||
|         "path-type": "^4.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "dnd-core": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/dnd-core/-/dnd-core-16.0.1.tgz", | ||||
|       "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", | ||||
|       "requires": { | ||||
|         "@react-dnd/asap": "^5.0.1", | ||||
|         "@react-dnd/invariant": "^4.0.1", | ||||
|         "redux": "^4.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "dns-equal": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", | ||||
| @ -10905,8 +11038,7 @@ | ||||
|     "fast-deep-equal": { | ||||
|       "version": "3.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", | ||||
|       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", | ||||
|       "dev": true | ||||
|       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" | ||||
|     }, | ||||
|     "fast-glob": { | ||||
|       "version": "3.2.11", | ||||
| @ -11384,6 +11516,14 @@ | ||||
|       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "hoist-non-react-statics": { | ||||
|       "version": "3.3.2", | ||||
|       "resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", | ||||
|       "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", | ||||
|       "requires": { | ||||
|         "react-is": "^16.7.0" | ||||
|       } | ||||
|     }, | ||||
|     "hosted-git-info": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", | ||||
| @ -13051,6 +13191,26 @@ | ||||
|         "object-assign": "^4.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "react-dnd": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-dnd/-/react-dnd-16.0.1.tgz", | ||||
|       "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", | ||||
|       "requires": { | ||||
|         "@react-dnd/invariant": "^4.0.1", | ||||
|         "@react-dnd/shallowequal": "^4.0.1", | ||||
|         "dnd-core": "^16.0.1", | ||||
|         "fast-deep-equal": "^3.1.3", | ||||
|         "hoist-non-react-statics": "^3.3.2" | ||||
|       } | ||||
|     }, | ||||
|     "react-dnd-html5-backend": { | ||||
|       "version": "16.0.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", | ||||
|       "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", | ||||
|       "requires": { | ||||
|         "dnd-core": "^16.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "react-dom": { | ||||
|       "version": "17.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", | ||||
| @ -13061,6 +13221,11 @@ | ||||
|         "scheduler": "^0.20.2" | ||||
|       } | ||||
|     }, | ||||
|     "react-is": { | ||||
|       "version": "16.13.1", | ||||
|       "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", | ||||
|       "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" | ||||
|     }, | ||||
|     "read-pkg": { | ||||
|       "version": "5.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", | ||||
| @ -13163,6 +13328,19 @@ | ||||
|         "strip-indent": "^3.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "redux": { | ||||
|       "version": "4.2.0", | ||||
|       "resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.0.tgz", | ||||
|       "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.9.2" | ||||
|       } | ||||
|     }, | ||||
|     "regenerator-runtime": { | ||||
|       "version": "0.13.9", | ||||
|       "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", | ||||
|       "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" | ||||
|     }, | ||||
|     "regexp.prototype.flags": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", | ||||
|  | ||||
| @ -75,6 +75,8 @@ | ||||
|     "express": "^4.17.3", | ||||
|     "gl-matrix": "^3.4.3", | ||||
|     "react": "^17.0.2", | ||||
|     "react-dnd": "^16.0.1", | ||||
|     "react-dnd-html5-backend": "^16.0.1", | ||||
|     "react-dom": "^17.0.2", | ||||
|     "uuid": "^8.3.2" | ||||
|   } | ||||
|  | ||||
| @ -9,6 +9,7 @@ interface IConfirmPopupProps { | ||||
| 	titleI18N?: AllI18nKeys; | ||||
| 	titleI18NOption?: Record<string, string>; | ||||
| 	infoI18n?: AllI18nKeys; | ||||
| 	infoI18nOption?: Record<string, string>; | ||||
| 	yesI18n?: AllI18nKeys; | ||||
| 	noI18n?: AllI18nKeys; | ||||
|     renderInfo?: () => ReactNode; | ||||
| @ -64,8 +65,10 @@ class ConfirmPopup extends Popup<IConfirmPopupProps> { | ||||
|                 this.props.renderInfo ? | ||||
|                     this.props.renderInfo() : | ||||
|                         this.props.infoI18n ? | ||||
|                             <Message i18nKey={this.props.infoI18n}/> : | ||||
|                             null | ||||
|                             <Message | ||||
| 								i18nKey={this.props.infoI18n} | ||||
| 								options={this.props.infoI18nOption} | ||||
| 							/> : null | ||||
|             } | ||||
| 		</ConfirmContent> | ||||
| 	} | ||||
|  | ||||
| @ -1,8 +1,20 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| 
 | ||||
| div.load-file-app-root { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| } | ||||
| 
 | ||||
| div.load-file-layer-root { | ||||
| 	position: fixed; | ||||
| 	z-index: 1000; | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	pointer-events: none; | ||||
| 	box-sizing: border-box; | ||||
| 	padding: 20px; | ||||
| 
 | ||||
| 	div.load-file-layer { | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		display: flex; | ||||
| @ -10,6 +22,7 @@ div.load-file-layer-root { | ||||
| 		justify-content: center; | ||||
| 		align-items: center; | ||||
| 		flex-wrap: wrap; | ||||
| 		border-radius: 3px; | ||||
| 
 | ||||
| 		div { | ||||
| 			user-select: none; | ||||
| @ -27,12 +40,21 @@ div.load-file-layer-root { | ||||
| 			margin-bottom: 5px; | ||||
| 			font-size: 1.5em; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| div.load-file-layer-root.light { | ||||
| 	background-color: rgba($color: #FFFFFF, $alpha: .75); | ||||
| 	background-color: rgba($color: #FFFFFF, $alpha: .6); | ||||
| 
 | ||||
| 	div.load-file-layer { | ||||
| 		border: 2px dashed $lt-font-color-normal-light; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| div.load-file-layer-root.dark { | ||||
| 	background-color: rgba($color: #000000, $alpha: .75); | ||||
| 	background-color: rgba($color: #000000, $alpha: .6); | ||||
| 
 | ||||
| 	div.load-file-layer { | ||||
| 		border: 2px dashed $lt-font-color-normal-dark; | ||||
| 	} | ||||
| } | ||||
| @ -1,16 +1,20 @@ | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { Status, useStatus, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { FunctionComponent } from "react"; | ||||
| import { useDrop } from 'react-dnd' | ||||
| import { NativeTypes } from "react-dnd-html5-backend" | ||||
| import "./LoadFile.scss"; | ||||
| 
 | ||||
| class LoadFile extends Component { | ||||
| const DragFileMask: FunctionComponent = () => { | ||||
| 
 | ||||
| 	private renderMask() { | ||||
| 	return <Theme | ||||
| 		className="load-file-layer-root" | ||||
| 		fontLevel={FontLevel.normal} | ||||
| 	> | ||||
| 		<div className="load-file-layer"> | ||||
| 			<div className="drag-icon"> | ||||
| 				<Icon iconName="KnowledgeArticle"/> | ||||
| 			</div> | ||||
| @ -20,12 +24,119 @@ class LoadFile extends Component { | ||||
| 			<div className="drag-intro"> | ||||
| 				<Localization i18nKey="Info.Hint.Load.File.Intro"/> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</Theme>;  | ||||
| 	} | ||||
| 
 | ||||
| 	public render(): ReactNode { | ||||
| 		return <></>; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| async function fileChecker(status: Status, file?: File) { | ||||
| 
 | ||||
| 	if (!status) return undefined; | ||||
| 
 | ||||
| 	return new Promise((r, j) => { | ||||
| 		 | ||||
| 		// 检查文件存在性
 | ||||
| 		if (!file) { | ||||
| 			status.popup.showPopup(ConfirmPopup, { | ||||
| 				infoI18n: "Popup.Load.Save.Error.Empty", | ||||
| 				titleI18N: "Popup.Load.Save.Title", | ||||
| 				yesI18n: "Popup.Load.Save.confirm" | ||||
| 			}); | ||||
| 			return j(); | ||||
| 		} | ||||
| 
 | ||||
| 		// 检测拓展名
 | ||||
| 		let extendName = (file.name.match(/\.(\w+)$/) ?? [])[1]; | ||||
| 		if (extendName !== "ltss") { | ||||
| 			status.popup.showPopup(ConfirmPopup, { | ||||
| 				infoI18n: "Popup.Load.Save.Error.Type", | ||||
| 				infoI18nOption: { ext: extendName }, | ||||
| 				titleI18N: "Popup.Load.Save.Title", | ||||
| 				yesI18n: "Popup.Load.Save.confirm" | ||||
| 			}); | ||||
| 			return j(); | ||||
| 		} | ||||
| 
 | ||||
| 		// 文件读取
 | ||||
| 		let fileReader = new FileReader(); | ||||
| 		fileReader.readAsText(file); | ||||
| 		fileReader.onload = () => { | ||||
| 
 | ||||
| 			const loadFunc = () => { | ||||
| 
 | ||||
| 				// 进行转换
 | ||||
| 				let errorMessage = status.archive.load(status.model, fileReader.result as string, file.name); | ||||
| 				if (errorMessage) { | ||||
| 					status.popup.showPopup(ConfirmPopup, { | ||||
| 						infoI18n: "Popup.Load.Save.Error.Parse", | ||||
| 						infoI18nOption: { why: errorMessage }, | ||||
| 						titleI18N: "Popup.Load.Save.Title", | ||||
| 						yesI18n: "Popup.Load.Save.confirm" | ||||
| 					}); | ||||
| 					j(); | ||||
| 				}  | ||||
| 
 | ||||
| 				else { | ||||
| 					r(undefined); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// 如果保存进行提示
 | ||||
| 			if (!status.archive.isSaved) { | ||||
| 				status.popup.showPopup(ConfirmPopup, { | ||||
| 					infoI18n: "Popup.Load.Save.Overwrite.Info", | ||||
| 					titleI18N: "Popup.Load.Save.Title", | ||||
| 					yesI18n: "Popup.Load.Save.Overwrite", | ||||
| 					noI18n: "Popup.Action.No", | ||||
| 					red: "yes", | ||||
| 					yes: () => { | ||||
| 						loadFunc(); | ||||
| 					}, | ||||
| 					no: () => { | ||||
| 						j(); | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| 			else { | ||||
| 				loadFunc(); | ||||
| 			}			 | ||||
| 		} | ||||
| 		fileReader.onerror = () => { | ||||
| 			status.popup.showPopup(ConfirmPopup, { | ||||
| 				infoI18n: "Popup.Load.Save.Error.Parse", | ||||
| 				infoI18nOption: { why: "Unknown error" }, | ||||
| 				titleI18N: "Popup.Load.Save.Title", | ||||
| 				yesI18n: "Popup.Load.Save.confirm" | ||||
| 			}); | ||||
| 			j(); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| const LoadFileView: FunctionComponent<IMixinStatusProps> = (props) => { | ||||
| 
 | ||||
| 	const [{ isOver }, drop] = useDrop(() => ({ | ||||
| 		accept: NativeTypes.FILE, | ||||
| 		drop: (item: { files: File[] }) => { | ||||
| 			if (props.status) { | ||||
| 				fileChecker(props.status, item.files[0]).catch((e) => undefined); | ||||
| 			} | ||||
| 		}, | ||||
| 		collect: (monitor) => ({ | ||||
| 			isOver: monitor.isOver() | ||||
| 		}) | ||||
| 	})); | ||||
| 
 | ||||
| 	return <> | ||||
| 		{ | ||||
| 			isOver ? <DragFileMask/> : null | ||||
| 		} | ||||
| 		<div className="load-file-app-root" ref={drop}> | ||||
| 			{props.children} | ||||
| 		</div> | ||||
| 	</> | ||||
| } | ||||
| 
 | ||||
| const LoadFile = useStatus(LoadFileView); | ||||
| 
 | ||||
| export { LoadFile }; | ||||
| @ -161,6 +161,11 @@ class Status extends Emitter<IStatusEvent> { | ||||
|             this.emit("labelChange"); | ||||
|             this.emit("behaviorChange"); | ||||
| 
 | ||||
|             // 清除焦点对象
 | ||||
|             this.setBehaviorObject(); | ||||
|             this.setFocusObject(new Set()); | ||||
|             this.setLabelObject(); | ||||
| 
 | ||||
|             // 映射
 | ||||
|             this.emit("fileLoad"); | ||||
|         }); | ||||
|  | ||||
| @ -65,6 +65,13 @@ const EN_US = { | ||||
|     "Popup.Delete.Behavior.Confirm": "Are you sure you want to delete this behavior? The behavior is deleted and cannot be recalled.", | ||||
|     "Popup.Restore.Behavior.Confirm": "Are you sure you want to reset all parameters of this behavior? This operation cannot be recalled.", | ||||
|     "Popup.Setting.Title": "Preferences setting", | ||||
|     "Popup.Load.Save.Title": "Load save", | ||||
|     "Popup.Load.Save.confirm": "Got it", | ||||
|     "Popup.Load.Save.Overwrite": "Overwrite and continue", | ||||
|     "Popup.Load.Save.Overwrite.Info": "The current workspace will be overwritten after the archive is loaded, and all unsaved progress will be lost. Are you sure you want to continue?", | ||||
|     "Popup.Load.Save.Error.Empty": "File information acquisition error. The file has been lost or moved.", | ||||
|     "Popup.Load.Save.Error.Type": "The file with extension name \"{ext}\" cannot be loaded temporarily", | ||||
|     "Popup.Load.Save.Error.Parse": "Archive parsing error, detailed reason: \n{why}", | ||||
|     "Popup.Add.Behavior.Title": "Add behavior", | ||||
|     "Popup.Add.Behavior.Action.Add": "Add all select behavior", | ||||
|     "Popup.Add.Behavior.Select.Counter": "Selected {count} behavior", | ||||
|  | ||||
| @ -65,6 +65,13 @@ const ZH_CN = { | ||||
|     "Popup.Delete.Behavior.Confirm": "你确定要删除这个行为吗?行为被删除将无法撤回。", | ||||
|     "Popup.Restore.Behavior.Confirm": "你确定要重置此行为的全部参数吗?此操作无法撤回。", | ||||
|     "Popup.Setting.Title": "首选项设置", | ||||
|     "Popup.Load.Save.Title": "加载存档", | ||||
|     "Popup.Load.Save.confirm": "我知道了", | ||||
|     "Popup.Load.Save.Overwrite": "覆盖并继续", | ||||
|     "Popup.Load.Save.Overwrite.Info": "存档加载后将覆盖当前工作区,未保存的进度将全部丢失,确定要继续吗?", | ||||
|     "Popup.Load.Save.Error.Empty": "文件信息获取错误,文件已丢失或已被移动", | ||||
|     "Popup.Load.Save.Error.Type": "暂时无法加载拓展名为 \"{ext}\" 的文件", | ||||
|     "Popup.Load.Save.Error.Parse": "存档解析错误,详细原因: \n{why}", | ||||
|     "Popup.Add.Behavior.Title": "添加行为", | ||||
|     "Popup.Add.Behavior.Action.Add": "添加全部选中行为", | ||||
|     "Popup.Add.Behavior.Select.Counter": "已选择 {count} 个行为", | ||||
|  | ||||
| @ -37,7 +37,7 @@ class Archive extends Emitter<IArchiveEvent> { | ||||
|     /** | ||||
|      * 是否保存 | ||||
|      */ | ||||
|     public isSaved: boolean = false; | ||||
|     public isSaved: boolean = true; | ||||
| 
 | ||||
|     /** | ||||
|      * 文件路径 | ||||
| @ -100,7 +100,7 @@ class Archive extends Emitter<IArchiveEvent> { | ||||
| 
 | ||||
|         // 解析为 JSON 对象
 | ||||
|         const archive: IArchiveObject = JSON.parse(data); | ||||
|         console.log(archive); | ||||
|         // console.log(archive);
 | ||||
| 
 | ||||
|         // 实例化全部对象
 | ||||
|         const objectPool: CtrlObject[] = []; | ||||
| @ -254,7 +254,7 @@ class Archive extends Emitter<IArchiveEvent> { | ||||
|      * 加载文件为模型 | ||||
|      * @return Model | ||||
|      */ | ||||
|     public load(model: Model, data: string): string | undefined { | ||||
|     public load(model: Model, data: string, name: string, url?: string): string | undefined { | ||||
| 
 | ||||
|         try { | ||||
|             this.loadArchiveIntoModel(model, data); | ||||
| @ -262,8 +262,11 @@ class Archive extends Emitter<IArchiveEvent> { | ||||
|             return e as string; | ||||
|         } | ||||
|          | ||||
|         this.isSaved = true; | ||||
|         this.emit("fileLoad", this); | ||||
|         this.fileName = name; | ||||
|         this.isSaved = true; | ||||
|         this.isNewFile = false; | ||||
|         this.emit("fileSave", this); | ||||
|     }; | ||||
| 
 | ||||
|     public constructor() { | ||||
|  | ||||
| @ -1,4 +1,6 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { DndProvider } from 'react-dnd' | ||||
| import { HTML5Backend } from 'react-dnd-html5-backend' | ||||
| import { SettingProvider, Setting, Platform } from "@Context/Setting"; | ||||
| import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme"; | ||||
| import { StatusProvider, Status } from "@Context/Status"; | ||||
| @ -7,12 +9,10 @@ import { initializeIcons } from '@fluentui/font-icons-mdl2'; | ||||
| import { RootContainer } from "@Component/Container/RootContainer"; | ||||
| import { LayoutDirection } from "@Context/Layout"; | ||||
| import { LoadFile } from "@Component/LoadFile/LoadFile"; | ||||
| import { AllBehaviors, getBehaviorById } from "@Behavior/Behavior"; | ||||
| import { CommandBar } from "@Component/CommandBar/CommandBar"; | ||||
| import { HeaderBar } from "@Component/HeaderBar/HeaderBar"; | ||||
| import { Popup } from "@Component/Popup/Popup"; | ||||
| import { Entry } from "../Entry/Entry"; | ||||
| import { Group } from "@Model/Group"; | ||||
| import "./SimulatorWeb.scss"; | ||||
| 
 | ||||
| initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/"); | ||||
| @ -42,118 +42,6 @@ class SimulatorWeb extends Component { | ||||
|         this.status.bindRenderer(classicRender); | ||||
|         this.status.setting = this.setting; | ||||
| 
 | ||||
|         const randomPosition = (group: Group) => { | ||||
|             group.individuals.forEach((individual) => { | ||||
|                 individual.position[0] = (Math.random() - .5) * 2; | ||||
|                 individual.position[1] = (Math.random() - .5) * 2; | ||||
|                 individual.position[2] = (Math.random() - .5) * 2; | ||||
|             }) | ||||
|         }; | ||||
| 
 | ||||
|         // 测试代码
 | ||||
|         if (false) { | ||||
|             let group = this.status.newGroup(); | ||||
|             let range = this.status.newRange(); | ||||
|             range.color = [.1, .5, .9]; | ||||
|             group.new(100); | ||||
|             group.color = [.8, .1, .6]; | ||||
|             randomPosition(group); | ||||
|             this.status.model.update(0); | ||||
|             this.status.newLabel().name = "New Label"; | ||||
|             this.status.newLabel().name = "Test Label 01"; | ||||
|             let template = this.status.model.addBehavior(AllBehaviors[0]); | ||||
|             template.name = "Template"; template.color = [150, 20, 220]; | ||||
|             let dynamic = this.status.model.addBehavior(AllBehaviors[1]); | ||||
|             dynamic.name = "Dynamic"; dynamic.color = [250, 200, 80]; | ||||
|             let brownian = this.status.model.addBehavior(AllBehaviors[2]); | ||||
|             brownian.name = "Brownian"; brownian.color = [200, 80, 250]; | ||||
|             let boundary = this.status.model.addBehavior(AllBehaviors[3]); | ||||
|             boundary.name = "Boundary"; boundary.color = [80, 200, 250]; | ||||
|             boundary.parameter.range.picker = this.status.model.allRangeLabel; | ||||
|             group.addBehavior(template); | ||||
|             group.addBehavior(dynamic); | ||||
|             group.addBehavior(brownian); | ||||
|             group.addBehavior(boundary); | ||||
|         } | ||||
| 
 | ||||
|         // 鱼群模型测试
 | ||||
|         if (false) { | ||||
|             let fish1 = this.status.newGroup(); | ||||
|             let fish2 = this.status.newGroup(); | ||||
|             let shark = this.status.newGroup(); | ||||
|             let range = this.status.newRange(); | ||||
| 
 | ||||
|             range.displayName = "Experimental site"; | ||||
|             range.color = [.8, .1, .6]; | ||||
| 
 | ||||
|             fish1.new(100); | ||||
|             fish1.displayName = "Fish A";             | ||||
|             fish1.color = [.1, .5, .9]; | ||||
|             randomPosition(fish1); | ||||
| 
 | ||||
|             fish2.new(50); | ||||
|             fish2.displayName = "Fish B";             | ||||
|             fish2.color = [.3, .2, .9]; | ||||
|             randomPosition(fish2); | ||||
| 
 | ||||
|             shark.new(3); | ||||
|             shark.displayName = "Shark"; | ||||
|             shark.color = [.8, .2, .3]; | ||||
|             shark.renderParameter.size = 100; | ||||
|             shark.renderParameter.shape = "5"; | ||||
|             randomPosition(shark); | ||||
| 
 | ||||
|             this.status.model.update(0); | ||||
|             let fishLabel = this.status.newLabel(); | ||||
|             fishLabel.name = "Fish"; | ||||
|             fish1.addLabel(fishLabel); | ||||
|             fish2.addLabel(fishLabel); | ||||
| 
 | ||||
|             let template = this.status.model.addBehavior(getBehaviorById("Template")); | ||||
|             template.name = "Template"; template.color = [150, 20, 220]; | ||||
| 
 | ||||
|             let dynamicFish = this.status.model.addBehavior(getBehaviorById("PhysicsDynamics")); | ||||
|             dynamicFish.name = "Dynamic Fish"; dynamicFish.color = [250, 200, 80]; | ||||
| 
 | ||||
|             let dynamicShark = this.status.model.addBehavior(getBehaviorById("PhysicsDynamics")); | ||||
|             dynamicShark.name = "Dynamic Shark"; dynamicShark.color = [250, 200, 80]; | ||||
|             dynamicShark.parameter.maxAcceleration = 8.5; | ||||
|             dynamicShark.parameter.maxVelocity = 15.8; | ||||
|             dynamicShark.parameter.resistance = 3.6; | ||||
| 
 | ||||
|             let brownian = this.status.model.addBehavior(getBehaviorById("Brownian")); | ||||
|             brownian.name = "Brownian"; brownian.color = [200, 80, 250]; | ||||
| 
 | ||||
|             let boundary = this.status.model.addBehavior(getBehaviorById("BoundaryConstraint")); | ||||
|             boundary.name = "Boundary"; boundary.color = [80, 200, 250]; | ||||
|             boundary.parameter.range.picker = this.status.model.allRangeLabel; | ||||
| 
 | ||||
|             let tracking = this.status.model.addBehavior(getBehaviorById("Tracking")); | ||||
|             tracking.name = "Tracking"; tracking.color = [80, 200, 250]; | ||||
|             tracking.parameter.target.picker = fishLabel; | ||||
| 
 | ||||
|             let attacking = this.status.model.addBehavior(getBehaviorById("ContactAttacking")); | ||||
|             attacking.name = "Contact Attacking"; attacking.color = [120, 100, 250]; | ||||
|             attacking.parameter.target.picker = fishLabel; | ||||
| 
 | ||||
|             fish1.addBehavior(dynamicFish); | ||||
|             fish1.addBehavior(brownian); | ||||
|             fish1.addBehavior(boundary); | ||||
| 
 | ||||
|             fish2.addBehavior(dynamicFish); | ||||
|             fish2.addBehavior(brownian); | ||||
|             fish2.addBehavior(boundary); | ||||
| 
 | ||||
|             shark.addBehavior(dynamicShark); | ||||
|             shark.addBehavior(boundary); | ||||
|             shark.addBehavior(tracking); | ||||
|             shark.addBehavior(attacking); | ||||
| 
 | ||||
|             setTimeout(() => { | ||||
|                 this.status.model.updateBehaviorParameter(); | ||||
|             }, 200) | ||||
|         } | ||||
| 
 | ||||
|         (window as any).LT = { | ||||
|             status: this.status, | ||||
|             setting: this.setting | ||||
| @ -193,7 +81,9 @@ class SimulatorWeb extends Component { | ||||
|     public render(): ReactNode { | ||||
|         return <SettingProvider value={this.setting}> | ||||
|             <StatusProvider value={this.status}> | ||||
|                 <DndProvider backend={HTML5Backend}> | ||||
|                     {this.renderContent()} | ||||
|                 </DndProvider> | ||||
|             </StatusProvider> | ||||
|         </SettingProvider> | ||||
|     } | ||||
| @ -204,8 +94,8 @@ class SimulatorWeb extends Component { | ||||
|             backgroundLevel={BackgroundLevel.Level5} | ||||
|             fontLevel={FontLevel.Level3} | ||||
|         > | ||||
|             <LoadFile/> | ||||
|             <Popup/> | ||||
|             <LoadFile> | ||||
|                 <HeaderBar height={45}/> | ||||
|                 <div className="app-root-space" style={{ | ||||
|                     height: `calc( 100% - ${45}px)` | ||||
| @ -213,6 +103,7 @@ class SimulatorWeb extends Component { | ||||
|                     <CommandBar/> | ||||
|                     <RootContainer/> | ||||
|                 </div> | ||||
|             </LoadFile> | ||||
|         </Theme> | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user