mirror of
https://github.com/ansible/awx.git
synced 2026-01-22 06:58:06 -03:30
commit
0fbd0c941a
@ -48,5 +48,7 @@
|
||||
"no-trailing-spaces": ["error"],
|
||||
"react/prefer-stateless-function": "off",
|
||||
"react/prop-types": "off",
|
||||
"jsx-a11y/label-has-for": "off",
|
||||
"jsx-a11y/label-has-associated-control": "off"
|
||||
}
|
||||
}
|
||||
|
||||
230
package-lock.json
generated
230
package-lock.json
generated
@ -14,12 +14,12 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.2.tgz",
|
||||
"integrity": "sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.3.tgz",
|
||||
"integrity": "sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.1.2",
|
||||
"@babel/types": "^7.1.3",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"source-map": "^0.5.0",
|
||||
@ -131,9 +131,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.2.tgz",
|
||||
"integrity": "sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.3.tgz",
|
||||
"integrity": "sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
@ -148,17 +148,17 @@
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz",
|
||||
"integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==",
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.4.tgz",
|
||||
"integrity": "sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/generator": "^7.0.0",
|
||||
"@babel/generator": "^7.1.3",
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-split-export-declaration": "^7.0.0",
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"@babel/parser": "^7.1.3",
|
||||
"@babel/types": "^7.1.3",
|
||||
"debug": "^3.1.0",
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.10"
|
||||
@ -188,9 +188,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.2.tgz",
|
||||
"integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.3.tgz",
|
||||
"integrity": "sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA==",
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.10",
|
||||
@ -259,20 +259,20 @@
|
||||
"integrity": "sha512-I9LGoxDR1ezb3GsS4l9XIDd5yv4jUP4X0FkVOIedRe+XN3OSU2zHSUkwCHdM2zKQRxrZyRCvR9vSzF5yUjG8FA=="
|
||||
},
|
||||
"@patternfly/react-core": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-1.19.1.tgz",
|
||||
"integrity": "sha512-e7DrOF78CF5D/hqGSCbOqC/Txxqu6OD2z8xDhjcl9JlNVIyIPdLKp4ksRMQ0vKj+ctQtAfWgsfTbduRCyo5L2g==",
|
||||
"version": "1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-1.23.0.tgz",
|
||||
"integrity": "sha512-1AAYdNo2EYdjv6oIglPSde9BWwRXOFw8uL8o9owxCOIhynnMybA/8T0ZvPdbO5DysDsGKHyYHiWvETaEpzUlbg==",
|
||||
"requires": {
|
||||
"@patternfly/react-icons": "^2.5.0",
|
||||
"@patternfly/react-styles": "^2.2.0",
|
||||
"@patternfly/react-icons": "^2.5.1",
|
||||
"@patternfly/react-styles": "^2.3.0",
|
||||
"@patternfly/react-tokens": "^1.0.0",
|
||||
"exenv": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"@patternfly/react-icons": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-2.5.0.tgz",
|
||||
"integrity": "sha512-A+2+hZB+WFPlug/UWCTYEB0DRCyUjgf4tXf8jcanlsUON9mHAfcdWy4CvAxCLCUQHozn4efT1QWtGCLY+iW6zA=="
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-2.5.1.tgz",
|
||||
"integrity": "sha512-WCijrkj48gbSAUV7qsf9OiBv1PbO5/Tc8MIHNCPoLVnriAHmzgzH3tNsAKa/ejP4ePYG1Oq8EIFu9OQlwdsjQw=="
|
||||
},
|
||||
"@patternfly/react-styles": {
|
||||
"version": "2.3.0",
|
||||
@ -294,9 +294,9 @@
|
||||
}
|
||||
},
|
||||
"@patternfly/react-tokens": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-1.5.1.tgz",
|
||||
"integrity": "sha512-qu+He+tO3p7akte0K75DDhl+8FiSXdAKyos+UBPeB1tlHUAaOfKfve1k0ehjDI9IpVajxauC23ezg35iA+wwIw==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-1.5.2.tgz",
|
||||
"integrity": "sha512-KpZ9D+x86xUpzznz+Jsa/2H09Dl9UIO9uiNKcWIHwkzNHIO8CA+exKV1R89k9tVkEOScYbDb5JFGVeQin2cmLg==",
|
||||
"optional": true
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
@ -904,9 +904,9 @@
|
||||
}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz",
|
||||
"integrity": "sha1-Bd+nBa2orZ25k/polvItOVsLCgc=",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
|
||||
"integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ast-types-flow": "0.0.7"
|
||||
@ -1902,7 +1902,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
@ -2267,9 +2266,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30000890",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz",
|
||||
"integrity": "sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg=="
|
||||
"version": "1.0.30000892",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz",
|
||||
"integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w=="
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
@ -3209,9 +3208,9 @@
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
|
||||
"integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
|
||||
"integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.0.0",
|
||||
@ -3256,7 +3255,6 @@
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
@ -3269,9 +3267,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.77",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.77.tgz",
|
||||
"integrity": "sha512-XIfQcdU9L4qUte31fFATwptHodMH0Otf53N8y1AKxd1+79vR+2UYpLq+Z1Zbtbuy+w0xd7KwIUrvlnje/htiOg=="
|
||||
"version": "1.3.79",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz",
|
||||
"integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw=="
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.1",
|
||||
@ -3415,9 +3413,9 @@
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.1.tgz",
|
||||
"integrity": "sha512-hgrDtGWz368b7Wqf+v1Z69O3ZebNR0+GA7PtDdbmuz4rInFVUV9uw7whjZEiWyLzCjVb5Rs5WRN1TAS6eo7AYA==",
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz",
|
||||
"integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
@ -3451,12 +3449,12 @@
|
||||
"path-is-inside": "^1.0.2",
|
||||
"pluralize": "^7.0.0",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^2.0.0",
|
||||
"regexpp": "^2.0.1",
|
||||
"require-uncached": "^1.0.3",
|
||||
"semver": "^5.5.1",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"strip-json-comments": "^2.0.1",
|
||||
"table": "^4.0.3",
|
||||
"table": "^5.0.2",
|
||||
"text-table": "^0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -6037,8 +6035,7 @@
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "11.12.0",
|
||||
@ -6924,9 +6921,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"neo-async": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz",
|
||||
"integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==",
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
|
||||
"integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
|
||||
"dev": true
|
||||
},
|
||||
"nice-try": {
|
||||
@ -7062,9 +7059,9 @@
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz",
|
||||
"integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==",
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.4.tgz",
|
||||
"integrity": "sha512-MXyurANsUoE4/6KmfMkwGcBzAnJQ5xJBGW7Ei6ea8KnUKuzHr/SguVBIi3uaUAHtZCPUYkvlJ3Ef5T5VAwVpaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-foreach": "^0.1.3",
|
||||
@ -7082,7 +7079,7 @@
|
||||
"nan": "^2.10.0",
|
||||
"node-gyp": "^3.8.0",
|
||||
"npmlog": "^4.0.0",
|
||||
"request": "2.87.0",
|
||||
"request": "^2.88.0",
|
||||
"sass-graph": "^2.2.4",
|
||||
"stdout-stream": "^1.4.0",
|
||||
"true-case-path": "^1.0.2"
|
||||
@ -7097,65 +7094,6 @@
|
||||
"lru-cache": "^4.0.1",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^5.1.0",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
||||
"dev": true
|
||||
},
|
||||
"request": {
|
||||
"version": "2.87.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
|
||||
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.6.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.5",
|
||||
"extend": "~3.0.1",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.1",
|
||||
"har-validator": "~5.0.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.17",
|
||||
"oauth-sign": "~0.8.2",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.1",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"tough-cookie": "~2.3.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -7807,9 +7745,9 @@
|
||||
}
|
||||
},
|
||||
"postcss-value-parser": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
|
||||
"integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
|
||||
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
|
||||
"dev": true
|
||||
},
|
||||
"prelude-ls": {
|
||||
@ -8159,11 +8097,11 @@
|
||||
}
|
||||
},
|
||||
"redux": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.0.tgz",
|
||||
"integrity": "sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz",
|
||||
"integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"loose-envify": "^1.4.0",
|
||||
"symbol-observable": "^1.2.0"
|
||||
}
|
||||
},
|
||||
@ -9102,9 +9040,9 @@
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
|
||||
"integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
@ -9411,15 +9349,13 @@
|
||||
"integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY="
|
||||
},
|
||||
"table": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz",
|
||||
"integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
|
||||
"integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.0.1",
|
||||
"ajv-keywords": "^3.0.0",
|
||||
"chalk": "^2.1.0",
|
||||
"lodash": "^4.17.4",
|
||||
"ajv": "^6.5.3",
|
||||
"lodash": "^4.17.10",
|
||||
"slice-ansi": "1.0.0",
|
||||
"string-width": "^2.1.1"
|
||||
},
|
||||
@ -9436,26 +9372,6 @@
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
@ -9467,15 +9383,6 @@
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -9694,8 +9601,7 @@
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
|
||||
@ -33,14 +33,14 @@
|
||||
"webpack-dev-server": "^3.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@patternfly/patternfly-next": "^1.0.58",
|
||||
"@patternfly/react-core": "1.23.0",
|
||||
"axios": "^0.18.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"react": "^16.4.1",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"redux": "^4.0.0",
|
||||
"@patternfly/patternfly-next": "^1.0.41",
|
||||
"@patternfly/react-core": "1.19.1"
|
||||
"redux": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
220
src/App.jsx
220
src/App.jsx
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import {
|
||||
HashRouter as Router,
|
||||
@ -7,20 +7,29 @@ import {
|
||||
Redirect,
|
||||
Switch,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import {
|
||||
BackgroundImage,
|
||||
BackgroundImageSrc,
|
||||
Brand,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Nav,
|
||||
NavList,
|
||||
NavGroup,
|
||||
NavItem,
|
||||
Page,
|
||||
PageHeader,
|
||||
PageSection,
|
||||
PageSectionVariants,
|
||||
PageSidebar,
|
||||
Title,
|
||||
TextContent,
|
||||
Text,
|
||||
Toolbar,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
ToolbarItem
|
||||
} from '@patternfly/react-core';
|
||||
import { global_breakpoint_md as breakpointMd } from '@patternfly/react-tokens';
|
||||
import { css } from '@patternfly/react-styles';
|
||||
|
||||
import api from './api';
|
||||
|
||||
@ -47,7 +56,6 @@ import Teams from './pages/Teams';
|
||||
import Templates from './pages/Templates';
|
||||
import Users from './pages/Users';
|
||||
|
||||
|
||||
const AuthenticatedRoute = ({ component: Component, ...rest }) => (
|
||||
<Route {...rest} render={props => (
|
||||
api.isAuthenticated() ? (
|
||||
@ -61,11 +69,28 @@ const AuthenticatedRoute = ({ component: Component, ...rest }) => (
|
||||
)}/>
|
||||
);
|
||||
|
||||
const UnauthenticatedRoute = ({ component: Component, ...rest }) => (
|
||||
<Route {...rest} render={props => (
|
||||
!api.isAuthenticated() ? (
|
||||
<Component {...props}/>
|
||||
) : (
|
||||
<Redirect to={{
|
||||
pathname: '/',
|
||||
state: { from: props.location }
|
||||
}}/>
|
||||
)
|
||||
)}/>
|
||||
);
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = { activeItem: 'dashboard', isNavOpen: true };
|
||||
this.state = {
|
||||
activeItem: 'dashboard',
|
||||
isNavOpen: (typeof window !== 'undefined' &&
|
||||
window.innerWidth >= parseInt(breakpointMd.value, 10)),
|
||||
};
|
||||
}
|
||||
|
||||
onNavToggle = () => {
|
||||
@ -78,93 +103,107 @@ class App extends React.Component {
|
||||
this.setState({ activeItem: itemId });
|
||||
};
|
||||
|
||||
onLogoClick = () => {
|
||||
this.setState({ activeItem: "dashboard" });
|
||||
}
|
||||
|
||||
onDevLogout = () => {
|
||||
api.logout()
|
||||
.then(() => {
|
||||
this.setState({ activeItem: "dashboard" });
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { activeItem, isNavOpen } = this.state;
|
||||
const { logo, loginInfo } = this.props;
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path="/login" component={Login} />
|
||||
<AuthenticatedRoute component={() => (
|
||||
<Page
|
||||
header={(
|
||||
<PageHeader
|
||||
logo={<TowerLogo />}
|
||||
toolbar={(
|
||||
<Toolbar>
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>Item 1</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>Item 2</ToolbarItem>
|
||||
<ToolbarItem>Item 3</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
<Fragment>
|
||||
<BackgroundImage src={{
|
||||
[BackgroundImageSrc.lg]: '/assets/images/pfbg_1200.jpg',
|
||||
[BackgroundImageSrc.md]: '/assets/images/pfbg_992.jpg',
|
||||
[BackgroundImageSrc.md2x]: '/assets/images/pfbg_992@2x.jpg',
|
||||
[BackgroundImageSrc.sm]: '/assets/images/pfbg_768.jpg',
|
||||
[BackgroundImageSrc.sm2x]: '/assets/images/pfbg_768@2x.jpg',
|
||||
[BackgroundImageSrc.xl]: '/assets/images/pfbg_2000.jpg',
|
||||
[BackgroundImageSrc.xs]: '/assets/images/pfbg_576.jpg',
|
||||
[BackgroundImageSrc.xs2x]: '/assets/images/pfbg_576@2x.jpg',
|
||||
[BackgroundImageSrc.filter]: '/assets/images/background-filter.svg'
|
||||
}} />
|
||||
<Switch>
|
||||
<UnauthenticatedRoute path="/login" component={() => <Login logo={logo} loginInfo={loginInfo} />} />
|
||||
<AuthenticatedRoute component={() => (
|
||||
<Page
|
||||
header={(
|
||||
<PageHeader
|
||||
logo={<TowerLogo onClick={this.onLogoClick} />}
|
||||
avatar={<i className="fas fa-user" onClick={this.onDevLogout}></i>}
|
||||
showNavToggle
|
||||
onNavToggle={this.onNavToggle}
|
||||
/>
|
||||
)}
|
||||
avatar="| avatar"
|
||||
showNavToggle
|
||||
onNavToggle={this.onNavToggle}
|
||||
/>
|
||||
)}
|
||||
sidebar={(
|
||||
<PageSidebar
|
||||
isNavOpen={isNavOpen}
|
||||
nav={(
|
||||
<Nav onSelect={this.onNavSelect} aria-label="Primary Navigation">
|
||||
<NavGroup title="Views">
|
||||
<NavItem to="#/home" itemId="dashboard" isActive={activeItem === 'dashboard'}>Dashboard</NavItem>
|
||||
<NavItem to="#/jobs" itemId="jobs" isActive={activeItem === 'jobs'}>Jobs</NavItem>
|
||||
<NavItem to="#/schedules" itemId="schedules" isActive={activeItem === 'schedules'}>Schedules</NavItem>
|
||||
<NavItem to="#/portal" itemId="portal" isActive={activeItem === 'portal'}>My View</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Resources">
|
||||
<NavItem to="#/templates" itemId="templates" isActive={activeItem === 'templates'}>Templates</NavItem>
|
||||
<NavItem to="#/credentials" itemId="credentials" isActive={activeItem === 'credentials'}>Credentials</NavItem>
|
||||
<NavItem to="#/projects" itemId="projects" isActive={activeItem === 'projects'}>Projects</NavItem>
|
||||
<NavItem to="#/inventories" itemId="inventories" isActive={activeItem === 'inventories'}>Inventories</NavItem>
|
||||
<NavItem to="#/inventory_scripts" itemId="inventory_scripts" isActive={activeItem === 'inventory_scripts'}>Inventory Scripts</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Access">
|
||||
<NavItem to="#/organizations" itemId="organizations" isActive={activeItem === 'organizations'}>Organizations</NavItem>
|
||||
<NavItem to="#/users" itemId="users" isActive={activeItem === 'users'}>Users</NavItem>
|
||||
<NavItem to="#/teams" itemId="teams" isActive={activeItem === 'teams'}>Teams</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Administration">
|
||||
<NavItem to="#/credential_types" itemId="credential_types" isActive={activeItem === 'credential_types'}>Credential Types</NavItem>
|
||||
<NavItem to="#/notification_templates" itemId="notification_templates" isActive={activeItem === 'notification_templates'}>Notifications</NavItem>
|
||||
<NavItem to="#/management_jobs" itemId="management_jobs" isActive={activeItem === 'management_jobs'}>Management Jobs</NavItem>
|
||||
<NavItem to="#/instance_groups" itemId="instance_groups" isActive={activeItem === 'instance_groups'}>Instance Groups</NavItem>
|
||||
<NavItem to="#/applications" itemId="applications" isActive={activeItem === 'applications'}>Applications</NavItem>
|
||||
<NavItem to="#/settings" itemId="settings" isActive={activeItem === 'settings'}>Settings</NavItem>
|
||||
</NavGroup>
|
||||
</Nav>
|
||||
)}
|
||||
/>
|
||||
)}>
|
||||
<Switch>
|
||||
<Route exact path="/" component={() => (<Redirect to="/home" />)} />
|
||||
<Route path="/home" component={Dashboard} />
|
||||
<Route path="/jobs" component={Jobs} />
|
||||
<Route path="/schedules" component={Schedules} />
|
||||
<Route path="/portal" component={Portal} />
|
||||
<Route path="/templates" component={Templates} />
|
||||
<Route path="/credentials" component={Credentials} />
|
||||
<Route path="/projects" component={Projects} />
|
||||
<Route path="/inventories" component={Inventories} />
|
||||
<Route path="/inventory_scripts" component={InventoryScripts} />
|
||||
<Route path="/organizations" component={Organizations} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="/teams" component={Teams} />
|
||||
<Route path="/credential_types" component={CredentialTypes} />
|
||||
<Route path="/notification_templates" component={NotificationTemplates} />
|
||||
<Route path="/management_jobs" component={ManagementJobs} />
|
||||
<Route path="/instance_groups" component={InstanceGroups} />
|
||||
<Route path="/applications" component={Applications} />
|
||||
<Route path="/settings" component={Settings} />
|
||||
</Switch>
|
||||
</Page>
|
||||
)} />
|
||||
</Switch>
|
||||
sidebar={(
|
||||
<PageSidebar
|
||||
isNavOpen={isNavOpen}
|
||||
nav={(
|
||||
<Nav onSelect={this.onNavSelect} aria-label="Primary Navigation">
|
||||
<NavGroup title="Views">
|
||||
<NavItem to="#/home" itemId="dashboard" isActive={activeItem === 'dashboard'}>Dashboard</NavItem>
|
||||
<NavItem to="#/jobs" itemId="jobs" isActive={activeItem === 'jobs'}>Jobs</NavItem>
|
||||
<NavItem to="#/schedules" itemId="schedules" isActive={activeItem === 'schedules'}>Schedules</NavItem>
|
||||
<NavItem to="#/portal" itemId="portal" isActive={activeItem === 'portal'}>My View</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Resources">
|
||||
<NavItem to="#/templates" itemId="templates" isActive={activeItem === 'templates'}>Templates</NavItem>
|
||||
<NavItem to="#/credentials" itemId="credentials" isActive={activeItem === 'credentials'}>Credentials</NavItem>
|
||||
<NavItem to="#/projects" itemId="projects" isActive={activeItem === 'projects'}>Projects</NavItem>
|
||||
<NavItem to="#/inventories" itemId="inventories" isActive={activeItem === 'inventories'}>Inventories</NavItem>
|
||||
<NavItem to="#/inventory_scripts" itemId="inventory_scripts" isActive={activeItem === 'inventory_scripts'}>Inventory Scripts</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Access">
|
||||
<NavItem to="#/organizations" itemId="organizations" isActive={activeItem === 'organizations'}>Organizations</NavItem>
|
||||
<NavItem to="#/users" itemId="users" isActive={activeItem === 'users'}>Users</NavItem>
|
||||
<NavItem to="#/teams" itemId="teams" isActive={activeItem === 'teams'}>Teams</NavItem>
|
||||
</NavGroup>
|
||||
<NavGroup title="Administration">
|
||||
<NavItem to="#/credential_types" itemId="credential_types" isActive={activeItem === 'credential_types'}>Credential Types</NavItem>
|
||||
<NavItem to="#/notification_templates" itemId="notification_templates" isActive={activeItem === 'notification_templates'}>Notifications</NavItem>
|
||||
<NavItem to="#/management_jobs" itemId="management_jobs" isActive={activeItem === 'management_jobs'}>Management Jobs</NavItem>
|
||||
<NavItem to="#/instance_groups" itemId="instance_groups" isActive={activeItem === 'instance_groups'}>Instance Groups</NavItem>
|
||||
<NavItem to="#/applications" itemId="applications" isActive={activeItem === 'applications'}>Applications</NavItem>
|
||||
<NavItem to="#/settings" itemId="settings" isActive={activeItem === 'settings'}>Settings</NavItem>
|
||||
</NavGroup>
|
||||
</Nav>
|
||||
)}
|
||||
/>
|
||||
)}>
|
||||
<Switch>
|
||||
<Route exact path="/" component={() => (<Redirect to="/home" />)} />
|
||||
<Route path="/home" component={Dashboard} />
|
||||
<Route path="/jobs" component={Jobs} />
|
||||
<Route path="/schedules" component={Schedules} />
|
||||
<Route path="/portal" component={Portal} />
|
||||
<Route path="/templates" component={Templates} />
|
||||
<Route path="/credentials" component={Credentials} />
|
||||
<Route path="/projects" component={Projects} />
|
||||
<Route path="/inventories" component={Inventories} />
|
||||
<Route path="/inventory_scripts" component={InventoryScripts} />
|
||||
<Route path="/organizations" component={Organizations} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="/teams" component={Teams} />
|
||||
<Route path="/credential_types" component={CredentialTypes} />
|
||||
<Route path="/notification_templates" component={NotificationTemplates} />
|
||||
<Route path="/management_jobs" component={ManagementJobs} />
|
||||
<Route path="/instance_groups" component={InstanceGroups} />
|
||||
<Route path="/applications" component={Applications} />
|
||||
<Route path="/settings" component={Settings} />
|
||||
</Switch>
|
||||
</Page>
|
||||
)} />
|
||||
</Switch>
|
||||
</Fragment>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
@ -172,4 +211,9 @@ class App extends React.Component {
|
||||
|
||||
const el = document.getElementById('app');
|
||||
|
||||
render(<App />, el);
|
||||
api.getRoot()
|
||||
.then(({ data }) => {
|
||||
const { custom_logo, custom_login_info } = data;
|
||||
|
||||
render(<App logo={custom_logo} loginInfo={custom_login_info} />, el);
|
||||
});
|
||||
|
||||
29
src/api.js
29
src/api.js
@ -2,6 +2,7 @@ import axios from 'axios';
|
||||
|
||||
const API_ROOT = '/api/';
|
||||
const API_LOGIN = `${API_ROOT}login/`;
|
||||
const API_LOGOUT = `${API_ROOT}logout/`;
|
||||
const API_V2 = `${API_ROOT}v2/`;
|
||||
const API_CONFIG = `${API_V2}config/`;
|
||||
const API_PROJECTS = `${API_V2}projects/`;
|
||||
@ -12,7 +13,6 @@ const CSRF_HEADER_NAME = 'X-CSRFToken';
|
||||
|
||||
class APIClient {
|
||||
constructor () {
|
||||
this.authenticated = false; // temporary
|
||||
this.http = axios.create({
|
||||
xsrfCookieName: CSRF_COOKIE_NAME,
|
||||
xsrfHeaderName: CSRF_HEADER_NAME,
|
||||
@ -20,7 +20,15 @@ class APIClient {
|
||||
}
|
||||
|
||||
isAuthenticated () {
|
||||
return this.authenticated;
|
||||
let authenticated = false;
|
||||
|
||||
const parsed = (`; ${document.cookie}`).split('; userLoggedIn=');
|
||||
|
||||
if (parsed.length === 2) {
|
||||
authenticated = parsed.pop().split(';').shift() === 'true';
|
||||
}
|
||||
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
login (username, password, redirect = API_CONFIG) {
|
||||
@ -32,16 +40,15 @@ class APIClient {
|
||||
const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
|
||||
|
||||
return this.http.get(API_LOGIN, { headers })
|
||||
.then(() => this.http.post(API_LOGIN, data, { headers }))
|
||||
.then(res => {
|
||||
this.authenticated = true; // temporary
|
||||
|
||||
return res;
|
||||
});
|
||||
.then(() => this.http.post(API_LOGIN, data, { headers }));
|
||||
}
|
||||
|
||||
logout () {
|
||||
return this.http.delete(API_LOGIN);
|
||||
return this.http.get(API_LOGOUT);
|
||||
}
|
||||
|
||||
getConfig () {
|
||||
return this.http.get(API_CONFIG);
|
||||
}
|
||||
|
||||
getProjects () {
|
||||
@ -51,6 +58,10 @@ class APIClient {
|
||||
getOrganizations () {
|
||||
return this.http.get(API_ORGANIZATIONS);
|
||||
}
|
||||
|
||||
getRoot () {
|
||||
return this.http.get(API_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
export default new APIClient();
|
||||
|
||||
101
src/app.scss
101
src/app.scss
@ -1,34 +1,95 @@
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
.pf-l-page__header {
|
||||
--pf-l-page__header--MinHeight: 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
background-color: #030303;
|
||||
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand {
|
||||
--pf-l-page__header-brand--PaddingBottom: 0px;
|
||||
align-self: center;
|
||||
height: 60px;
|
||||
max-width: 190px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.pf-l-page__header-tools {
|
||||
align-self: center;
|
||||
height: 60px;
|
||||
padding-left: 190px;
|
||||
|
||||
.fa-user:hover {
|
||||
// temporary dev logout
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-l-toolbar {
|
||||
align-self: center;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand-link {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand-link img {
|
||||
transform: scale(1.1, 1.1);
|
||||
position: relative;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand-toggle {
|
||||
align-self: center;
|
||||
position: relative;
|
||||
right: 14px;
|
||||
--pf-l-page__header-brand-link--MarginLeft: 0px;
|
||||
--pf-l-page__header-brand-link--MarginLeft: 0px;
|
||||
|
||||
button {
|
||||
--pf-l-page__header-sidebar-toggle--FontSize: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Side Navigation
|
||||
//
|
||||
|
||||
.pf-c-nav {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.pf-c-nav__section {
|
||||
--pf-c-nav__section--MarginTop: 8px;
|
||||
}
|
||||
|
||||
.pf-l-page__sidebar{
|
||||
--pf-l-page__sidebar--Width--lg: 190px;
|
||||
}
|
||||
|
||||
.pf-c-nav__section + .pf-c-nav__section {
|
||||
--pf-c-nav__section--MarginTop: 8px;
|
||||
}
|
||||
|
||||
.pf-c-nav__simple-list .pf-c-nav__link {
|
||||
--pf-c-nav__simple-list-link--PaddingLeft: 24px;
|
||||
--pf-c-nav__simple-list-link--PaddingBottom: 6px;
|
||||
--pf-c-nav__simple-list-link--PaddingTop: 6px;
|
||||
}
|
||||
|
||||
.pf-c-nav__section-title {
|
||||
--pf-c-nav__section-title--PaddingLeft: 24px;
|
||||
}
|
||||
|
||||
//
|
||||
// Page
|
||||
//
|
||||
|
||||
.pf-l-page__main-section {
|
||||
--pf-l-page__main-section--PaddingTop: 11px;
|
||||
--pf-l-page__main-section--PaddingLeft: 11px;
|
||||
}
|
||||
|
||||
.pf-c-nav__section + .pf-c-nav__section {
|
||||
--pf-c-nav__section--MarginTop: 16px;
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand-toggle {
|
||||
padding-bottom: 4px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.pf-l-page__header-brand-link {
|
||||
transform: scale(0.75, 0.75);
|
||||
}
|
||||
|
||||
.pf-l-page__sidebar{
|
||||
--pf-l-page__sidebar--Width--lg: 200px;
|
||||
}
|
||||
|
||||
@ -13,9 +13,13 @@ class TowerLogo extends Component {
|
||||
}
|
||||
|
||||
onClick = () => {
|
||||
if (!this.props.onClick) return;
|
||||
|
||||
const { history } = this.props;
|
||||
|
||||
history.push('/');
|
||||
|
||||
this.props.onClick();
|
||||
};
|
||||
|
||||
onHover = () => {
|
||||
@ -29,7 +33,7 @@ class TowerLogo extends Component {
|
||||
|
||||
let src = TowerLogoHeader;
|
||||
|
||||
if (hover) {
|
||||
if (hover && this.props.onClick) {
|
||||
src = TowerLogoHeaderHover;
|
||||
}
|
||||
|
||||
3
src/components/TowerLogo/index.js
Normal file
3
src/components/TowerLogo/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import TowerLogo from './TowerLogo';
|
||||
|
||||
export default TowerLogo;
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@ -1,69 +1,135 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
Bullseye,
|
||||
Brand,
|
||||
Button,
|
||||
TextInput
|
||||
Level,
|
||||
LevelItem,
|
||||
Login,
|
||||
LoginBox,
|
||||
LoginBoxHeader,
|
||||
LoginBoxBody,
|
||||
LoginFooter,
|
||||
LoginHeaderBrand,
|
||||
TextInput,
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
import TowerLogo from '../components/TowerLogo';
|
||||
import api from '../api';
|
||||
|
||||
class Login extends Component {
|
||||
state = {
|
||||
username: '',
|
||||
password: '',
|
||||
redirect: false,
|
||||
};
|
||||
const LOGIN_ERROR_MESSAGE = 'Invalid username or password. Please try again.';
|
||||
|
||||
handleUsernameChange = value => this.setState({ username: value });
|
||||
class LoginPage extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
handlePasswordChange = value => this.setState({ password: value });
|
||||
this.state = {
|
||||
username: '',
|
||||
password: '',
|
||||
redirect: false,
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this.unmounting = true; // todo: state management
|
||||
}
|
||||
|
||||
safeSetState = obj => !this.unmounting && this.setState(obj);
|
||||
|
||||
handleUsernameChange = value => this.safeSetState({ username: value, error: '' });
|
||||
|
||||
handlePasswordChange = value => this.safeSetState({ password: value, error: '' });
|
||||
|
||||
handleSubmit = event => {
|
||||
const { username, password } = this.state;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
this.safeSetState({ loading: true });
|
||||
|
||||
api.login(username, password)
|
||||
.then(() => this.setState({ redirect: true }));
|
||||
.then(() => this.safeSetState({ redirect: true }))
|
||||
.catch(error => {
|
||||
if (error.response.status === 401) {
|
||||
this.safeSetState({ error: LOGIN_ERROR_MESSAGE });
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.safeSetState({ loading: false });
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const { username, password, redirect } = this.state;
|
||||
const { username, password, redirect, loading, error } = this.state;
|
||||
const { logo, loginInfo } = this.props;
|
||||
|
||||
if (redirect) {
|
||||
return (<Redirect to="/" />);
|
||||
}
|
||||
|
||||
return (
|
||||
<Bullseye>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<TextInput
|
||||
aria-label="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
onChange={this.handleUsernameChange}
|
||||
value={username}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<TextInput
|
||||
aria-label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
onChange={this.handlePasswordChange}
|
||||
value={password}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit">
|
||||
Login
|
||||
</Button>
|
||||
</form>
|
||||
</Bullseye>
|
||||
<Login
|
||||
header={(
|
||||
<LoginHeaderBrand>
|
||||
{logo ? <Brand src={`data:image/jpeg;${logo}`} alt="logo brand" /> : <TowerLogo />}
|
||||
</LoginHeaderBrand>
|
||||
)}
|
||||
footer={<LoginFooter>{ loginInfo }</LoginFooter>}
|
||||
>
|
||||
<LoginBox>
|
||||
<LoginBoxHeader>
|
||||
Welcome to Ansible Tower! Please Sign In.
|
||||
</LoginBoxHeader>
|
||||
<LoginBoxBody>
|
||||
<form className="pf-c-form" onSubmit={this.handleSubmit}>
|
||||
<div className="pf-c-form__group" id="username">
|
||||
<label className="pf-c-form__label" htmlFor="username">
|
||||
Username
|
||||
<span className="pf-c-form__label__required" aria-hidden="true">*</span>
|
||||
</label>
|
||||
<TextInput
|
||||
autoComplete="off"
|
||||
aria-label="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
isDisabled={loading}
|
||||
value={username}
|
||||
onChange={this.handleUsernameChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="pf-c-form__group">
|
||||
<label className="pf-c-form__label" htmlFor="pw">
|
||||
Password
|
||||
<span className="pf-c-form__label__required" aria-hidden="true">*</span>
|
||||
</label>
|
||||
<TextInput
|
||||
aria-label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
isDisabled={loading}
|
||||
value={password}
|
||||
onChange={this.handlePasswordChange}
|
||||
/>
|
||||
</div>
|
||||
<Level>
|
||||
<LevelItem>
|
||||
<p className="pf-c-form__helper-text pf-m-error" aria-live="polite">
|
||||
{ error }
|
||||
</p>
|
||||
</LevelItem>
|
||||
<LevelItem>
|
||||
<Button type="submit" isDisabled={loading}>
|
||||
Sign In
|
||||
</Button>
|
||||
</LevelItem>
|
||||
</Level>
|
||||
</form>
|
||||
</LoginBoxBody>
|
||||
</LoginBox>
|
||||
</Login>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Login;
|
||||
export default LoginPage;
|
||||
|
||||
@ -16,26 +16,34 @@ module.exports = {
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader' },
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
includePaths: [
|
||||
'node_modules/patternfly/dist/sass',
|
||||
'node_modules/patternfly/node_modules/bootstrap-sass/assets/stylesheet',
|
||||
'node_modules/patternfly/node_modules/font-awesome-sass/assets/stylesheets'
|
||||
]
|
||||
}
|
||||
}
|
||||
{ loader: 'sass-loader' },
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(woff(2)?|ttf|jpg|png|eot|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
||||
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
|
||||
use: [{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'fonts/',
|
||||
publicPatH: '../'
|
||||
outputPath: 'assets/fonts/',
|
||||
publicPatH: '../',
|
||||
includePaths: [
|
||||
'node_modules/@patternfly/patternfly-next/assets/fonts',
|
||||
]
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
test: /\.(jpg|png|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
||||
use: [{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'assets/images/',
|
||||
publicPatH: '../',
|
||||
includePaths: [
|
||||
'node_modules/@patternfly/patternfly-next/assets/images',
|
||||
]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user