Basic theming

This commit is contained in:
Alex 2022-02-28 17:59:06 +01:00
parent 8d937ca10e
commit 236caa2616
Signed by: lx
GPG key ID: 0E496D15096376BE
6 changed files with 592 additions and 46 deletions

451
package-lock.json generated
View file

@ -16,8 +16,12 @@
"@types/node": "^16.11.26",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/react-router-bootstrap": "^0.24.5",
"bootstrap": "^5.1.3",
"react": "^17.0.2",
"react-bootstrap": "^2.1.2",
"react-dom": "^17.0.2",
"react-router-bootstrap": "^0.26.0",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"typescript": "^4.5.5",
@ -4052,6 +4056,58 @@
"node": ">= 8"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@react-aria/ssr": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.1.2.tgz",
"integrity": "sha512-amXY11ImpokvkTMeKRHjsSsG7v1yzzs6yeqArCyBIk60J3Yhgxwx9Cah+Uu/804ATFwqzN22AXIo7SdtIaMP+g==",
"dependencies": {
"@babel/runtime": "^7.6.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1"
}
},
"node_modules/@restart/hooks": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.5.tgz",
"integrity": "sha512-tLGtY0aHeIfT7aPwUkvQuhIy3+q3w4iqmUzFLPlOAf/vNUacLaBt1j/S//jv/dQhenRh8jvswyMojCwmLvJw8A==",
"dependencies": {
"dequal": "^2.0.2"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@restart/ui": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.0.1.tgz",
"integrity": "sha512-hLAqltcAjQYtjGuHBHKyPpR3ScTxzdkSYNvniwBfN7rUDbYiHu/UZiI1hvV2idJeUvktRnz29l7W9BnNLHrG6Q==",
"dependencies": {
"@babel/runtime": "^7.13.16",
"@popperjs/core": "^2.10.1",
"@react-aria/ssr": "^3.0.1",
"@restart/hooks": "^0.4.0",
"@types/warning": "^3.0.0",
"dequal": "^2.0.2",
"dom-helpers": "^5.2.0",
"prop-types": "^15.7.2",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -4721,6 +4777,11 @@
"@types/node": "*"
}
},
"node_modules/@types/history": {
"version": "4.7.11",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA=="
},
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@ -4734,6 +4795,11 @@
"@types/node": "*"
}
},
"node_modules/@types/invariant": {
"version": "2.2.35",
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
},
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@ -4832,6 +4898,42 @@
"@types/react": "*"
}
},
"node_modules/@types/react-router": {
"version": "5.1.18",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
"integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==",
"dependencies": {
"@types/history": "^4.7.11",
"@types/react": "*"
}
},
"node_modules/@types/react-router-bootstrap": {
"version": "0.24.5",
"resolved": "https://registry.npmjs.org/@types/react-router-bootstrap/-/react-router-bootstrap-0.24.5.tgz",
"integrity": "sha512-GRx/8xF/skw4/Pmm6d+xbExi8gobCLOe8Eoz9kXPQGbYo7p5Wbi61tjpOF5AbfJ5XMN+fIzweToTi56odj/LOQ==",
"dependencies": {
"@types/react": "*",
"@types/react-router-dom": "*"
}
},
"node_modules/@types/react-router-dom": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
"dependencies": {
"@types/history": "^4.7.11",
"@types/react": "*",
"@types/react-router": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz",
"integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -4893,6 +4995,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"node_modules/@types/warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
"integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI="
},
"node_modules/@types/ws": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.1.tgz",
@ -6235,6 +6342,18 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"node_modules/bootstrap": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
},
"peerDependencies": {
"@popperjs/core": "^2.10.2"
}
},
"node_modules/bowser": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
@ -6558,6 +6677,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
"node_modules/classnames": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
},
"node_modules/clean-css": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz",
@ -7781,6 +7905,14 @@
"node": ">= 0.6"
}
},
"node_modules/dequal": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
"integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==",
"engines": {
"node": ">=6"
}
},
"node_modules/destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
@ -7919,6 +8051,15 @@
"utila": "~0.4"
}
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
@ -10300,6 +10441,14 @@
"node": ">= 0.4"
}
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
@ -15049,6 +15198,23 @@
"react-is": "^16.13.1"
}
},
"node_modules/prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"dependencies": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
},
"peerDependencies": {
"react": ">=0.14.0"
}
},
"node_modules/prop-types-extra/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/prop-types/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -15256,6 +15422,33 @@
"node": ">=14"
}
},
"node_modules/react-bootstrap": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.1.2.tgz",
"integrity": "sha512-E7PR13cVsEW70gw08BWplENwn6PHTshskOsQygZqyc65jQlsnr9MsmuW/lgzAN2OiMBnc0KaNpuZ/FohL7dchw==",
"dependencies": {
"@babel/runtime": "^7.14.0",
"@restart/hooks": "^0.4.5",
"@restart/ui": "^1.0.1",
"@types/invariant": "^2.2.33",
"@types/prop-types": "^15.7.3",
"@types/react": ">=16.14.8",
"@types/react-transition-group": "^4.4.1",
"@types/warning": "^3.0.0",
"classnames": "^2.3.1",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.7.2",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.1",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@ -15396,6 +15589,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -15415,6 +15613,18 @@
"react": ">=16.8"
}
},
"node_modules/react-router-bootstrap": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/react-router-bootstrap/-/react-router-bootstrap-0.26.0.tgz",
"integrity": "sha512-auVpsCOYgI+3CrmtpVjme8ucz76iiMvJhv2BrnWof2HtimrF9NtAHtFzdZrsku5hwp166EPbz7IuSyHJA8kkdA==",
"dependencies": {
"prop-types": "^15.7.2"
},
"peerDependencies": {
"react": ">=16.13.1",
"react-router-dom": ">=6.0.0"
}
},
"node_modules/react-router-dom": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
@ -15500,6 +15710,21 @@
}
}
},
"node_modules/react-transition-group": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
"integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@ -17268,6 +17493,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
"dependencies": {
"@babel/runtime": "^7.6.3",
"@types/react": ">=16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
},
"peerDependencies": {
"react": ">=15.0.0"
}
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@ -17510,6 +17749,14 @@
"makeerror": "1.0.12"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchpack": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
@ -21399,6 +21646,44 @@
}
}
},
"@popperjs/core": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
},
"@react-aria/ssr": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.1.2.tgz",
"integrity": "sha512-amXY11ImpokvkTMeKRHjsSsG7v1yzzs6yeqArCyBIk60J3Yhgxwx9Cah+Uu/804ATFwqzN22AXIo7SdtIaMP+g==",
"requires": {
"@babel/runtime": "^7.6.2"
}
},
"@restart/hooks": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.5.tgz",
"integrity": "sha512-tLGtY0aHeIfT7aPwUkvQuhIy3+q3w4iqmUzFLPlOAf/vNUacLaBt1j/S//jv/dQhenRh8jvswyMojCwmLvJw8A==",
"requires": {
"dequal": "^2.0.2"
}
},
"@restart/ui": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.0.1.tgz",
"integrity": "sha512-hLAqltcAjQYtjGuHBHKyPpR3ScTxzdkSYNvniwBfN7rUDbYiHu/UZiI1hvV2idJeUvktRnz29l7W9BnNLHrG6Q==",
"requires": {
"@babel/runtime": "^7.13.16",
"@popperjs/core": "^2.10.1",
"@react-aria/ssr": "^3.0.1",
"@restart/hooks": "^0.4.0",
"@types/warning": "^3.0.0",
"dequal": "^2.0.2",
"dom-helpers": "^5.2.0",
"prop-types": "^15.7.2",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
}
},
"@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -21875,6 +22160,11 @@
"@types/node": "*"
}
},
"@types/history": {
"version": "4.7.11",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA=="
},
"@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@ -21888,6 +22178,11 @@
"@types/node": "*"
}
},
"@types/invariant": {
"version": "2.2.35",
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
},
"@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@ -21986,6 +22281,42 @@
"@types/react": "*"
}
},
"@types/react-router": {
"version": "5.1.18",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
"integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==",
"requires": {
"@types/history": "^4.7.11",
"@types/react": "*"
}
},
"@types/react-router-bootstrap": {
"version": "0.24.5",
"resolved": "https://registry.npmjs.org/@types/react-router-bootstrap/-/react-router-bootstrap-0.24.5.tgz",
"integrity": "sha512-GRx/8xF/skw4/Pmm6d+xbExi8gobCLOe8Eoz9kXPQGbYo7p5Wbi61tjpOF5AbfJ5XMN+fIzweToTi56odj/LOQ==",
"requires": {
"@types/react": "*",
"@types/react-router-dom": "*"
}
},
"@types/react-router-dom": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
"requires": {
"@types/history": "^4.7.11",
"@types/react": "*",
"@types/react-router": "*"
}
},
"@types/react-transition-group": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz",
"integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==",
"requires": {
"@types/react": "*"
}
},
"@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -22047,6 +22378,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"@types/warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
"integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI="
},
"@types/ws": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.1.tgz",
@ -23055,6 +23391,12 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"bootstrap": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"requires": {}
},
"bowser": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
@ -23284,6 +23626,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
"classnames": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
},
"clean-css": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz",
@ -24200,6 +24547,11 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"dequal": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
"integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug=="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
@ -24315,6 +24667,15 @@
"utila": "~0.4"
}
},
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
@ -26058,6 +26419,14 @@
"side-channel": "^1.0.4"
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
@ -29399,6 +29768,22 @@
}
}
},
"prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"requires": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}
}
},
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -29544,6 +29929,29 @@
"whatwg-fetch": "^3.6.2"
}
},
"react-bootstrap": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.1.2.tgz",
"integrity": "sha512-E7PR13cVsEW70gw08BWplENwn6PHTshskOsQygZqyc65jQlsnr9MsmuW/lgzAN2OiMBnc0KaNpuZ/FohL7dchw==",
"requires": {
"@babel/runtime": "^7.14.0",
"@restart/hooks": "^0.4.5",
"@restart/ui": "^1.0.1",
"@types/invariant": "^2.2.33",
"@types/prop-types": "^15.7.3",
"@types/react": ">=16.14.8",
"@types/react-transition-group": "^4.4.1",
"@types/warning": "^3.0.0",
"classnames": "^2.3.1",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.7.2",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.1",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
}
},
"react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@ -29650,6 +30058,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -29663,6 +30076,14 @@
"history": "^5.2.0"
}
},
"react-router-bootstrap": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/react-router-bootstrap/-/react-router-bootstrap-0.26.0.tgz",
"integrity": "sha512-auVpsCOYgI+3CrmtpVjme8ucz76iiMvJhv2BrnWof2HtimrF9NtAHtFzdZrsku5hwp166EPbz7IuSyHJA8kkdA==",
"requires": {
"prop-types": "^15.7.2"
}
},
"react-router-dom": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
@ -29727,6 +30148,17 @@
"workbox-webpack-plugin": "^6.4.1"
}
},
"react-transition-group": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
"integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@ -31045,6 +31477,17 @@
"which-boxed-primitive": "^1.0.2"
}
},
"uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
"requires": {
"@babel/runtime": "^7.6.3",
"@types/react": ">=16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
}
},
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@ -31245,6 +31688,14 @@
"makeerror": "1.0.12"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watchpack": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",

View file

@ -11,8 +11,12 @@
"@types/node": "^16.11.26",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/react-router-bootstrap": "^0.24.5",
"bootstrap": "^5.1.3",
"react": "^17.0.2",
"react-bootstrap": "^2.1.2",
"react-dom": "^17.0.2",
"react-router-bootstrap": "^0.26.0",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"typescript": "^4.5.5",

View file

@ -11,6 +11,10 @@ import BucketList from './BucketList';
import { ObjectList1, ObjectList2 } from './ObjectList';
import './App.css';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
type AppProps = {};
type AppState = {
@ -30,11 +34,11 @@ class App extends React.Component<AppProps, AppState> {
super(props);
}
handleChangeAccessKeyId = (e: React.FormEvent<HTMLInputElement>): void => {
handleChangeAccessKeyId = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({accessKeyId: e.currentTarget.value});
}
handleChangeSecreteAccessKey = (e: React.FormEvent<HTMLInputElement>): void => {
handleChangeSecreteAccessKey = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({secretAccessKey: e.currentTarget.value});
}
@ -67,21 +71,42 @@ class App extends React.Component<AppProps, AppState> {
render() {
if (this.state.client) {
return (
<HashRouter>
<Routes>
<Route path="/:bucket/*" element={ <ObjectList2 client={this.state.client} /> } />
<Route path="/:bucket" element={ <ObjectList1 client={this.state.client} /> } />
<Route path="/" element={<BucketList client={this.state.client} />} />
</Routes>
</HashRouter>
<Container className="p-3">
<HashRouter>
<Routes>
<Route path="/:bucket/*" element={ <ObjectList2 client={this.state.client} /> } />
<Route path="/:bucket" element={ <ObjectList1 client={this.state.client} /> } />
<Route path="/" element={<BucketList client={this.state.client} />} />
</Routes>
</HashRouter>
</Container>
);
} else {
return (
<form onSubmit={this.login} >
<p>Access key id: <input type="text" value={ this.state.accessKeyId } onChange={this.handleChangeAccessKeyId} /></p>
<p>Secret access key: <input type="text" value={ this.state.secretAccessKey } onChange={this.handleChangeSecreteAccessKey} /></p>
<p><input type="submit" value="Log in" /></p>
</form>
<Container className="p-3">
<Form onSubmit={this.login} >
<Form.Group className="mb-3" controlId="formAccessKeyId">
<Form.Label>Access key ID</Form.Label>
<Form.Control type="text" placeholder="Access key id" value={ this.state.accessKeyId } onChange={this.handleChangeAccessKeyId} />
<Form.Text className="text-muted">
Hello!
</Form.Text>
</Form.Group>
<Form.Group className="mb-3" controlId="formSecretAccessKey">
<Form.Label>Secret access key</Form.Label>
<Form.Control type="text" placeholder="Secret access key" value={ this.state.secretAccessKey } onChange={this.handleChangeSecreteAccessKey} />
<Form.Text className="text-muted">
world!
</Form.Text>
</Form.Group>
<Button variant="primary" type="submit" onClick={this.login}>
Log in
</Button>
</Form>
</Container>
);
}
}

View file

@ -2,6 +2,12 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';
import Breadcrumb from 'react-bootstrap/Breadcrumb';
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';
import { LinkContainer } from 'react-router-bootstrap'
type Props = {
client: S3Client;
};
@ -21,6 +27,7 @@ class BucketList extends React.Component<Props, State> {
const data = await this.props.client.send(command);
console.log("ok", data);
const buckets = (data.Buckets || []).map((b) => (b.Name || 'aza'));
buckets.sort();
this.setState({buckets: buckets});
} catch(error) {
console.log("err", error);
@ -29,11 +36,20 @@ class BucketList extends React.Component<Props, State> {
render() {
return (
<ul>
{ this.state.buckets.map((b) =>
<li key={ b }><Link to={ "/" + b }>{ b }</Link></li>
)}
</ul>
<>
<Breadcrumb>
<Breadcrumb.Item active>my buckets</Breadcrumb.Item>
</Breadcrumb>
<ListGroup>
{ this.state.buckets.map((b) =>
<LinkContainer to={ "/" + b }>
<ListGroup.Item key={ b } action>
{ b }
</ListGroup.Item>
</LinkContainer>
)}
</ListGroup>
</>
);
}

View file

@ -2,6 +2,12 @@ import React from 'react';
import { Link, useParams } from 'react-router-dom';
import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3';
import Alert from 'react-bootstrap/Alert';
import Breadcrumb from 'react-bootstrap/Breadcrumb';
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';
import { LinkContainer } from 'react-router-bootstrap'
type Props = {
client: S3Client;
bucket: string;
@ -14,6 +20,8 @@ type State = {
files: string[];
};
var cache: { [path: string]: State; } = {};
class ObjectList extends React.Component<Props, State> {
state = {
loaded: false,
@ -28,6 +36,10 @@ class ObjectList extends React.Component<Props, State> {
async componentDidMount() {
console.log(this.props);
if (cache[this.path()]) {
this.setState(cache[this.path()]);
}
let command = new ListObjectsV2Command({
Bucket: this.props.bucket,
Prefix: this.props.prefix,
@ -38,54 +50,90 @@ class ObjectList extends React.Component<Props, State> {
const data = await this.props.client.send(command);
console.log("ok", data);
const folders = (data.CommonPrefixes || []).map((cp) => cp.Prefix!.substring(pxlen));
const files = (data.Contents || []).map((obj) => obj.Key!.substring(pxlen));
folders.sort();
files.sort();
this.setState({
loaded: true,
folders: (data.CommonPrefixes || []).map((cp) => cp.Prefix!.substring(pxlen)),
files: (data.Contents || []).map((obj) => obj.Key!.substring(pxlen)),
folders: folders,
files: files,
});
cache[this.path()] = this.state;
} catch(error) {
console.log("err", error);
}
}
parentTag() {
path() {
return this.props.bucket + "/" + this.props.prefix;
}
renderBreadcrumbs() {
let spl = this.props.prefix.split("/");
while (spl.pop() == "");
spl.push("");
let pp = spl.join("/");
let items = [];
for (var i = 0; i < spl.length - 1; i++) {
if (i < spl.length - 2) {
items.push(
<LinkContainer to={ "/" + this.props.bucket + "/" + spl.slice(0, i+1).join("/") + "/" }>
<Breadcrumb.Item>{ spl[i] }</Breadcrumb.Item>
</LinkContainer>
);
} else {
items.push(
<Breadcrumb.Item active>{ spl[i] }</Breadcrumb.Item>
);
}
}
return (
<li key="PARENT">
<Link to={ "/" + this.props.bucket + "/" + pp }>..</Link>
</li>
<Breadcrumb>
<LinkContainer to="/">
<Breadcrumb.Item>my buckets</Breadcrumb.Item>
</LinkContainer>
{ this.props.prefix == "" ?
<Breadcrumb.Item active>{ this.props.bucket }</Breadcrumb.Item>
:
<LinkContainer to={ "/" + this.props.bucket + "/" }>
<Breadcrumb.Item>{ this.props.bucket }</Breadcrumb.Item>
</LinkContainer>
}
{ items }
</Breadcrumb>
);
}
render() {
let par = (this.props.prefix.length > 0 ?
this.parentTag()
: <></>);
if (!this.state.loaded) {
return (
<ul>
{ par }
<li>Loading...</li>
</ul>
<>
{ this.renderBreadcrumbs() }
<Alert variant="secondary">Loading...</Alert>
</>
);
}
return (
<ul>
{ par }
{ this.state.folders.map((f) =>
<li key={f + "/" }>
<Link to={ "/" + this.props.bucket + "/" + this.props.prefix + f }>{ f }</Link>
</li>
)}
{ this.state.files.map((f) =>
<li key={f}>{ f }</li>
)}
</ul>
<>
{ this.renderBreadcrumbs() }
<ListGroup>
{ this.state.folders.map((f) =>
<LinkContainer to={ "/" + this.props.bucket + "/" + this.props.prefix + f }>
<ListGroup.Item key={f + "/"} action>
{ f }
</ListGroup.Item>
</LinkContainer>
)}
{ this.state.files.map((f) =>
<ListGroup.Item key={f}>
{ f }
</ListGroup.Item>
)}
</ListGroup>
</>
);
}
}

View file

@ -4,6 +4,8 @@ import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<React.StrictMode>
<App />