fix: Bring UI closer to mockups
This makes many tweaks to get the UI closer to the mockup and using Paragon components as much as possible. Related tickets: * [TNL-8427](https://openedx.atlassian.net/browse/TNL-8427) * [BB-4417](https://tasks.opencraft.com/browse/BB-4417)
This commit is contained in:
committed by
Mehak Nasir
parent
80ad9f1dc2
commit
7138e63cf0
249
package-lock.json
generated
249
package-lock.json
generated
@@ -1425,9 +1425,9 @@
|
||||
}
|
||||
},
|
||||
"@edx/paragon": {
|
||||
"version": "14.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-14.12.5.tgz",
|
||||
"integrity": "sha512-KBJb0e6TQewblFGTlH6OBD/Q82TqK7vtN0y6R1wbjmZz02feNr0Q6CNcM6dtpNMlfNbN7fb9vEE4x6VEUaaQOw==",
|
||||
"version": "16.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-16.7.0.tgz",
|
||||
"integrity": "sha512-WVcbFKv2OzxAQuiJ8BskrIo+ybv8p7QUEC5Ondg+/eWTt3aYtfYVvmDy7000JwPdsktVS3yKtMoDY2VbdgCNug==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.30",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.14.0",
|
||||
@@ -1438,28 +1438,29 @@
|
||||
"classnames": "^2.2.6",
|
||||
"email-prop-type": "^3.0.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"mailto-link": "^1.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-bootstrap": "^1.3.0",
|
||||
"react-focus-on": "^3.5.0",
|
||||
"react-popper": "^2.2.4",
|
||||
"react-proptype-conditional-require": "^1.0.4",
|
||||
"react-responsive": "^6.1.1",
|
||||
"react-responsive": "^8.2.0",
|
||||
"react-table": "^7.6.1",
|
||||
"react-transition-group": "^4.0.0",
|
||||
"sanitize-html": "^1.20.0",
|
||||
"tabbable": "^4.0.0",
|
||||
"uncontrollable": "7.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-responsive": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-6.1.2.tgz",
|
||||
"integrity": "sha512-AXentVC/kN3KED9zhzJv2pu4vZ0i6cSHdTtbCScVV1MT6F5KXaG2qs5D7WLmhdaOvmiMX8UfmS4ZSO+WPwDt4g==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz",
|
||||
"integrity": "sha512-iagCqVrw4QSjhxKp3I/YK6+ODkWY6G+YPElvdYKiUUbywwh9Ds0M7r26Fj2/7dWFFbOpcGnJE6uE7aMck8j5Qg==",
|
||||
"requires": {
|
||||
"hyphenate-style-name": "^1.0.0",
|
||||
"matchmediaquery": "^0.3.0",
|
||||
"prop-types": "^15.6.1"
|
||||
"prop-types": "^15.6.1",
|
||||
"shallow-equal": "^1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2339,12 +2340,11 @@
|
||||
"integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
|
||||
},
|
||||
"@restart/hooks": {
|
||||
"version": "0.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.26.tgz",
|
||||
"integrity": "sha512-7Hwk2ZMYm+JLWcb7R9qIXk1OoUg1Z+saKWqZXlrvFwT3w6UArVNWgxYOzf+PJoK9zZejp8okPAKTctthhXLt5g==",
|
||||
"version": "0.3.27",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.27.tgz",
|
||||
"integrity": "sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.20",
|
||||
"lodash-es": "^4.17.20"
|
||||
"dequal": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
@@ -2594,14 +2594,6 @@
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"@types/classnames": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
|
||||
"integrity": "sha512-zeOWb0JGBoVmlQoznvqXbE0tEC/HONsnoUNH19Hc96NFsTAwTXbTqb8FMYkru1F/iqp7a18Ws3nWJvtA1sHD1A==",
|
||||
"requires": {
|
||||
"classnames": "*"
|
||||
}
|
||||
},
|
||||
"@types/cookie": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
|
||||
@@ -2754,9 +2746,9 @@
|
||||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||
"integrity": "sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ==",
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.2.tgz",
|
||||
"integrity": "sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@@ -3238,6 +3230,7 @@
|
||||
"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"
|
||||
}
|
||||
@@ -4922,6 +4915,7 @@
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
@@ -4932,6 +4926,7 @@
|
||||
"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"
|
||||
}
|
||||
@@ -5237,6 +5232,7 @@
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -5244,7 +5240,8 @@
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.5.5",
|
||||
@@ -6264,6 +6261,11 @@
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"dev": true
|
||||
},
|
||||
"dequal": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
|
||||
"integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug=="
|
||||
},
|
||||
"des.js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
|
||||
@@ -6414,31 +6416,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
|
||||
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain-browser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
|
||||
@@ -6749,7 +6726,8 @@
|
||||
"entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"dev": true
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.8",
|
||||
@@ -6863,7 +6841,8 @@
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"escodegen": {
|
||||
"version": "2.0.0",
|
||||
@@ -8075,9 +8054,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
|
||||
"integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8235,9 +8214,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.18.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
|
||||
"integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
|
||||
"version": "1.18.5",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz",
|
||||
"integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==",
|
||||
"requires": {
|
||||
"call-bind": "^1.0.2",
|
||||
"es-to-primitive": "^1.2.1",
|
||||
@@ -8245,11 +8224,12 @@
|
||||
"get-intrinsic": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.2",
|
||||
"internal-slot": "^1.0.3",
|
||||
"is-callable": "^1.2.3",
|
||||
"is-negative-zero": "^2.0.1",
|
||||
"is-regex": "^1.1.3",
|
||||
"is-string": "^1.0.6",
|
||||
"object-inspect": "^1.10.3",
|
||||
"object-inspect": "^1.11.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.2",
|
||||
"string.prototype.trimend": "^1.0.4",
|
||||
@@ -8270,6 +8250,11 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
|
||||
"integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
|
||||
"integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8556,7 +8541,8 @@
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"has-symbol-support-x": {
|
||||
"version": "1.4.2",
|
||||
@@ -9479,7 +9465,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.1.0",
|
||||
"has": "^1.0.3",
|
||||
@@ -13664,12 +13649,8 @@
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
@@ -13721,6 +13702,11 @@
|
||||
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.uniqby": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz",
|
||||
"integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI="
|
||||
},
|
||||
"logalot": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz",
|
||||
@@ -15323,11 +15309,6 @@
|
||||
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
|
||||
"dev": true
|
||||
},
|
||||
"parse-srcset": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
|
||||
"integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||
@@ -15639,6 +15620,7 @@
|
||||
"version": "7.0.35",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz",
|
||||
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"source-map": "^0.6.1",
|
||||
@@ -16611,34 +16593,33 @@
|
||||
}
|
||||
},
|
||||
"react-bootstrap": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.0.tgz",
|
||||
"integrity": "sha512-PaeOGeRC2+JH9Uf1PukJgXcIpfGlrKKHEBZIArymjenYzSJ/RhO2UdNX+e7nalsCFFZLRRgQ0/FKkscW2LmmRg==",
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.1.tgz",
|
||||
"integrity": "sha512-ojEPQ6OtyIMdLg0Smofk+85PKN6MLKQX3bU0Vwmok/4yNa8DQ2vCGhO2IgHJvT+ERQZ4X+gAQcdn6msAHSwLBg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@babel/runtime": "^7.14.0",
|
||||
"@restart/context": "^2.1.4",
|
||||
"@restart/hooks": "^0.3.26",
|
||||
"@types/classnames": "^2.2.10",
|
||||
"@types/invariant": "^2.2.33",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/react": ">=16.9.35",
|
||||
"@types/react": ">=16.14.8",
|
||||
"@types/react-transition-group": "^4.4.1",
|
||||
"@types/warning": "^3.0.0",
|
||||
"classnames": "^2.2.6",
|
||||
"dom-helpers": "^5.1.2",
|
||||
"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-overlays": "^5.0.0",
|
||||
"react-overlays": "^5.0.1",
|
||||
"react-transition-group": "^4.4.1",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"version": "7.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz",
|
||||
"integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -16665,9 +16646,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"version": "7.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz",
|
||||
"integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -16849,16 +16830,16 @@
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"react-focus-lock": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.5.1.tgz",
|
||||
"integrity": "sha512-gOToRZKVEymGEjFaTRUKgJsdYQrNosoiK7yZnXnnd8bYew4vMzk3Rxb0Q4nyrGwsFuUmgQiSAulQirA0J+v4hA==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.5.2.tgz",
|
||||
"integrity": "sha512-WzpdOnEqjf+/A3EH9opMZWauag7gV0BxFl+EY4ElA4qFqYsUsBLnmo2sELbN5OC30S16GAWMy16B9DLPpdJKAQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"focus-lock": "^0.9.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-clientside-effect": "^1.2.2",
|
||||
"use-callback-ref": "^1.2.1",
|
||||
"use-sidecar": "^1.0.1"
|
||||
"react-clientside-effect": "^1.2.5",
|
||||
"use-callback-ref": "^1.2.5",
|
||||
"use-sidecar": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"react-focus-on": {
|
||||
@@ -16897,9 +16878,9 @@
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-overlays": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.0.1.tgz",
|
||||
"integrity": "sha512-plwUJieTBbLSrgvQ4OkkbTD/deXgxiJdNuKzo6n1RWE3OVnQIU5hffCGS/nvIuu6LpXFs2majbzaXY8rcUVdWA==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.1.1.tgz",
|
||||
"integrity": "sha512-eCN2s2/+GVZzpnId4XVWtvDPYYBD2EtOGP74hE+8yDskPzFy9+pV1H3ZZihxuRdEbQzzacySaaDkR7xE0ydl4Q==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.8.6",
|
||||
@@ -16912,9 +16893,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||
"version": "7.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz",
|
||||
"integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -16964,9 +16945,9 @@
|
||||
}
|
||||
},
|
||||
"react-remove-scroll": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.4.2.tgz",
|
||||
"integrity": "sha512-mMSIZYQF3jS2uRJXeFDRaVGA+BGs/hIryV64YUKsHFtpgwZloOUcdu0oW8K6OU8uLHt/kM5d0lUZbdpIVwgXtQ==",
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.4.3.tgz",
|
||||
"integrity": "sha512-lGWYXfV6jykJwbFpsuPdexKKzp96f3RbvGapDSIdcyGvHb7/eqyn46C7/6h+rUzYar1j5mdU+XECITHXCKBk9Q==",
|
||||
"requires": {
|
||||
"react-remove-scroll-bar": "^2.1.0",
|
||||
"react-style-singleton": "^2.1.0",
|
||||
@@ -17801,63 +17782,6 @@
|
||||
"walker": "~1.0.5"
|
||||
}
|
||||
},
|
||||
"sanitize-html": {
|
||||
"version": "1.27.5",
|
||||
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.5.tgz",
|
||||
"integrity": "sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==",
|
||||
"requires": {
|
||||
"htmlparser2": "^4.1.0",
|
||||
"lodash": "^4.17.15",
|
||||
"parse-srcset": "^1.0.2",
|
||||
"postcss": "^7.0.27"
|
||||
},
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
|
||||
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz",
|
||||
"integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==",
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"domhandler": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
|
||||
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
|
||||
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0",
|
||||
"domutils": "^2.0.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.26.11",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.11.tgz",
|
||||
@@ -18197,7 +18121,6 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
@@ -18441,7 +18364,8 @@
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-loader": {
|
||||
"version": "0.2.4",
|
||||
@@ -19099,6 +19023,7 @@
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"@edx/frontend-component-footer": "10.1.4",
|
||||
"@edx/frontend-component-header": "2.2.5",
|
||||
"@edx/frontend-platform": "1.10.3",
|
||||
"@edx/paragon": "14.12.5",
|
||||
"@edx/paragon": "16.7.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.35",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.3",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.3",
|
||||
|
||||
@@ -31,9 +31,13 @@ function CommentsView({ intl }) {
|
||||
<div className="mb-2">
|
||||
<div className="list-group list-group-flush">
|
||||
<Post post={thread} />
|
||||
{
|
||||
comments.map(reply => <Reply reply={reply} key={reply.id} />)
|
||||
}
|
||||
<div className="list-group">
|
||||
{comments.map(reply => (
|
||||
<div key={reply.id} className="list-group-item list-group-item-action">
|
||||
<Reply reply={reply} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="actions d-flex">
|
||||
|
||||
@@ -1,48 +1,65 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { faFlag, faStar as faEmptyStar } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faEllipsisV, faStar as faSolidStar } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Button, Icon } from '@edx/paragon';
|
||||
import {
|
||||
Flag,
|
||||
StarFilled,
|
||||
StarOutline,
|
||||
} from '@edx/paragon/icons';
|
||||
import LikeButton from '../../posts/post/LikeButton';
|
||||
|
||||
import { Button } from '@edx/paragon';
|
||||
|
||||
function CommentIcons({ abuseFlagged, following }) {
|
||||
function CommentIcons(
|
||||
{
|
||||
abuseFlagged,
|
||||
count,
|
||||
following,
|
||||
onLike,
|
||||
voted,
|
||||
},
|
||||
) {
|
||||
return (
|
||||
<div className="d-flex flex-column icons">
|
||||
<LikeButton
|
||||
count={count}
|
||||
onClick={() => onLike && onLike()}
|
||||
voted={voted}
|
||||
/>
|
||||
{/* Only show the star if the comment has a following attribute, indicating it can be followed */}
|
||||
{ following !== undefined && (
|
||||
following
|
||||
? (
|
||||
<Button variant="link" className="p-0" size="xs">
|
||||
<FontAwesomeIcon icon={faSolidStar} />
|
||||
<Icon src={StarFilled} />
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="link" className="p-0" size="xs">
|
||||
<FontAwesomeIcon icon={faEmptyStar} />
|
||||
<Icon src={StarOutline} />
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
{ abuseFlagged && (
|
||||
{abuseFlagged && (
|
||||
<Button variant="link" className="p-0" size="xs">
|
||||
<FontAwesomeIcon icon={faFlag} />
|
||||
<Icon src={Flag} />
|
||||
</Button>
|
||||
) }
|
||||
<Button variant="link" className="p-0" size="xs">
|
||||
<FontAwesomeIcon icon={faEllipsisV} />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CommentIcons.propTypes = {
|
||||
abuseFlagged: PropTypes.bool,
|
||||
count: PropTypes.number.isRequired,
|
||||
following: PropTypes.bool,
|
||||
onLike: PropTypes.func,
|
||||
voted: PropTypes.bool,
|
||||
};
|
||||
|
||||
CommentIcons.defaultProps = {
|
||||
abuseFlagged: undefined,
|
||||
following: undefined,
|
||||
onLike: undefined,
|
||||
voted: false,
|
||||
};
|
||||
|
||||
export default CommentIcons;
|
||||
|
||||
@@ -24,7 +24,7 @@ const messages = defineMessages({
|
||||
},
|
||||
replyTime: {
|
||||
id: 'discussions.comments.comment.repliedTime',
|
||||
defaultMessage: 'posted {relativeTime}',
|
||||
defaultMessage: 'Posted {relativeTime}',
|
||||
description: 'Message about hwo long ago a reply was posted. Appears as "username posted 7 minutes ago"',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,13 +4,51 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import * as timeago from 'timeago.js';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Avatar, Icon, IconButton } from '@edx/paragon';
|
||||
import { MoreVert } from '@edx/paragon/icons';
|
||||
|
||||
import { commentShape } from '../comment/Comment';
|
||||
import CommentIcons from '../comment-icons/CommentIcons';
|
||||
import { selectCommentResponses } from '../data/selectors';
|
||||
import { fetchCommentResponses } from '../data/thunks';
|
||||
import { editComment, fetchCommentResponses } from '../data/thunks';
|
||||
import messages from '../messages';
|
||||
|
||||
function ReplyHeader({ reply, intl }) {
|
||||
return (
|
||||
<div className="d-flex flex-row justify-content-between">
|
||||
<div className="align-items-center d-flex flex-row">
|
||||
<Avatar className="m-2" alt={reply.author} src={reply.users[reply.author].profile.image.image_url_small} />
|
||||
<div className="status small">
|
||||
<a href="#nowhere">
|
||||
<h1 className="font-weight-normal text-info-300 mr-1 small">
|
||||
{reply.author}
|
||||
</h1>
|
||||
</a>
|
||||
<h2 className="font-weight-normal small text-gray-500" title={reply.createdAt}>
|
||||
{intl.formatMessage(messages.replyTime, {
|
||||
relativeTime: timeago.format(reply.createdAt, intl.locale),
|
||||
})}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<IconButton
|
||||
alt="Options"
|
||||
iconAs={Icon}
|
||||
// TODO: Implement overlay
|
||||
onClick={() => { }}
|
||||
size="sm"
|
||||
src={MoreVert}
|
||||
variant="primary"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReplyHeader.propTypes = {
|
||||
reply: commentShape.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
function Reply({
|
||||
reply,
|
||||
intl,
|
||||
@@ -26,22 +64,18 @@ function Reply({
|
||||
}, [reply.id]);
|
||||
|
||||
return (
|
||||
<div className="discussion-reply d-flex flex-column mt-2">
|
||||
<div className="d-flex flex-row">
|
||||
<div className="d-flex flex-column flex-fill">
|
||||
<div className="status small">
|
||||
<span className="font-weight-bold text-info-300 mr-1">
|
||||
{reply.author}
|
||||
</span>
|
||||
<span title={reply.createdAt}>
|
||||
{intl.formatMessage(messages.replyTime, {
|
||||
relativeTime: timeago.format(reply.createdAt, intl.locale),
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
<div className="reply-body d-flex" dangerouslySetInnerHTML={{ __html: reply.renderedBody }} />
|
||||
</div>
|
||||
<CommentIcons abuseFlagged={reply.abuseFlagged} following={reply.following} />
|
||||
<div className="bt-1 discussion-reply d-flex flex-column my-2">
|
||||
<div>
|
||||
<ReplyHeader reply={reply} intl={intl} />
|
||||
<div className="reply-body d-flex px-2" dangerouslySetInnerHTML={{ __html: reply.renderedBody }} />
|
||||
<CommentIcons
|
||||
abuseFlagged={reply.abuseFlagged}
|
||||
count={reply.voteCount}
|
||||
following={reply.following}
|
||||
// FIXME: this API call fails
|
||||
onLike={() => dispatch(editComment(reply.id, { voted: !reply.voted }))}
|
||||
voted={reply.voted}
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
{/* Pass along intl since the `Reply` component used here is the one before it's injected with `injectIntl` */}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { TopicsView } from '../topics';
|
||||
export default function DiscussionsHome() {
|
||||
return (
|
||||
<main className="container my-4 d-flex flex-row">
|
||||
<div className="d-flex flex-column w-50 mr-1 card">
|
||||
<div className="d-flex flex-column w-50 mr-1">
|
||||
<Route path={Routes.DISCUSSIONS.PATH} component={NavigationBar} />
|
||||
<Route
|
||||
path={[
|
||||
@@ -21,14 +21,16 @@ export default function DiscussionsHome() {
|
||||
]}
|
||||
component={BreadcrumbMenu}
|
||||
/>
|
||||
<Switch>
|
||||
<Route path={Routes.POSTS.MY_POSTS}>
|
||||
<PostsView showOwnPosts />
|
||||
</Route>
|
||||
<Route path={Routes.POSTS.ALL_POSTS} component={PostsView} />
|
||||
<Route path={Routes.POSTS.PATH} component={PostsView} />
|
||||
<Route path={Routes.TOPICS.PATH} component={TopicsView} />
|
||||
</Switch>
|
||||
<div className="card">
|
||||
<Switch>
|
||||
<Route path={Routes.POSTS.MY_POSTS}>
|
||||
<PostsView showOwnPosts />
|
||||
</Route>
|
||||
<Route path={Routes.POSTS.ALL_POSTS} component={PostsView} />
|
||||
<Route path={Routes.POSTS.PATH} component={PostsView} />
|
||||
<Route path={Routes.TOPICS.PATH} component={TopicsView} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex w-50 pl-1 flex-column">
|
||||
<PostActionsBar />
|
||||
|
||||
@@ -28,7 +28,7 @@ function NavigationBar({ intl }) {
|
||||
];
|
||||
|
||||
return (
|
||||
<Nav variant="pills" className="border-bottom py-2">
|
||||
<Nav variant="pills" className="py-2">
|
||||
{navLinks.map(link => (
|
||||
<Nav.Item key={link.label}>
|
||||
<Nav.Link as={NavLink} to={link.url}>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { faSort } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import { ArrowDropUpDown } from '@edx/paragon/icons';
|
||||
|
||||
import { SelectableDropdown } from '../../../components';
|
||||
import {
|
||||
@@ -71,7 +71,7 @@ function PostFilterBar({
|
||||
options={postOrderingOptions}
|
||||
onChange={(sortBy) => dispatch(setSortedBy(sortBy.value))}
|
||||
label={
|
||||
<FontAwesomeIcon icon={faSort} aria-label="Sort" title="Sort" />
|
||||
<Icon src={ArrowDropUpDown} aria-label="Sort" title="Sort" />
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
61
src/discussions/posts/post/LikeButton.jsx
Normal file
61
src/discussions/posts/post/LikeButton.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Icon, IconButton, OverlayTrigger, Tooltip,
|
||||
} from '@edx/paragon';
|
||||
import { ThumbUpFilled, ThumbUpOutline } from '@edx/paragon/icons';
|
||||
import messages from './messages';
|
||||
|
||||
function LikeButton(
|
||||
{
|
||||
count,
|
||||
intl,
|
||||
onClick,
|
||||
voted,
|
||||
},
|
||||
) {
|
||||
const handleClick = (e) => {
|
||||
e.preventDefault();
|
||||
if (onClick) {
|
||||
onClick();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="d-flex align-items-center mx-2.5">
|
||||
<OverlayTrigger
|
||||
overlay={(
|
||||
<Tooltip>
|
||||
{intl.formatMessage(voted ? messages.removeLike : messages.like)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
alt="Like"
|
||||
iconAs={Icon}
|
||||
size="inline"
|
||||
src={voted ? ThumbUpFilled : ThumbUpOutline}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
{count}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
LikeButton.propTypes = {
|
||||
count: PropTypes.number.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
onClick: PropTypes.func,
|
||||
voted: PropTypes.bool,
|
||||
};
|
||||
|
||||
LikeButton.defaultProps = {
|
||||
voted: false,
|
||||
onClick: undefined,
|
||||
};
|
||||
|
||||
export default injectIntl(LikeButton);
|
||||
@@ -1,28 +1,23 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
faQuestionCircle,
|
||||
faStar as faEmptyStar,
|
||||
faThumbsUp as faEmptyThumb,
|
||||
} from '@fortawesome/free-regular-svg-icons';
|
||||
import {
|
||||
faComments,
|
||||
faStar as faSolidStar,
|
||||
faThumbsUp as faSolidThumb,
|
||||
faThumbtack,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import * as timeago from 'timeago.js';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Avatar, IconButton, OverlayTrigger, Tooltip,
|
||||
Avatar, Icon, IconButton, OverlayTrigger, Tooltip,
|
||||
} from '@edx/paragon';
|
||||
import {
|
||||
Pin,
|
||||
QuestionAnswer,
|
||||
StarFilled,
|
||||
StarOutline,
|
||||
} from '@edx/paragon/icons';
|
||||
|
||||
import { updateExistingThread } from '../data/thunks';
|
||||
import messages from './messages';
|
||||
import LikeButton from './LikeButton';
|
||||
|
||||
export const postShape = PropTypes.shape({
|
||||
abuseFlagged: PropTypes.bool,
|
||||
@@ -43,18 +38,11 @@ export const postShape = PropTypes.shape({
|
||||
function PostTypeIcon(props) {
|
||||
return (
|
||||
<div className="m-1">
|
||||
{props.type === 'question' && <FontAwesomeIcon icon={faQuestionCircle} size="lg" />}
|
||||
{props.type === 'discussion' && <FontAwesomeIcon icon={faComments} size="lg" />}
|
||||
{props.type === 'question' && <Icon src={QuestionAnswer} size="lg" />}
|
||||
{props.type === 'discussion' && <Icon src={QuestionAnswer} size="lg" />}
|
||||
{props.pinned && (
|
||||
<FontAwesomeIcon
|
||||
icon={faThumbtack}
|
||||
size="sm"
|
||||
className="position-relative bg-white rounded"
|
||||
style={{
|
||||
left: '-0.25rem',
|
||||
bottom: '-0.75rem',
|
||||
padding: '0.125rem',
|
||||
}}
|
||||
<Icon
|
||||
src={Pin}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -71,27 +59,32 @@ function PostHeader({
|
||||
post,
|
||||
}) {
|
||||
return (
|
||||
<div className="d-flex flex-fill">
|
||||
<Avatar className="my-1" alt={post.author} src={post.authorAvatars.imageUrlSmall} />
|
||||
<div className="d-flex flex-row flex-fill">
|
||||
<PostTypeIcon type={post.type} pinned={post.pinned} />
|
||||
<div className="d-flex flex-fill justify-content-between">
|
||||
<Avatar className="m-2" alt={post.author} src={post.authorAvatars.imageUrlSmall} />
|
||||
<PostTypeIcon type={post.type} pinned={post.pinned} />
|
||||
<div className="align-items-center d-flex flex-row flex-fill">
|
||||
<div className="d-flex flex-column flex-fill">
|
||||
<span className="d-flex font-weight-bold text-gray">
|
||||
<span className="d-flex font-weight-bold">
|
||||
{post.title}
|
||||
</span>
|
||||
<span className="d-flex small text-gray-300">
|
||||
{post.author}{' | '}
|
||||
<span className="d-flex text-gray-500 x-small">
|
||||
<span title={post.createdAt}>
|
||||
{intl.formatMessage(messages.postedOn, { time: timeago.format(post.createdAt, intl.locale) })}
|
||||
{intl.formatMessage(
|
||||
messages.postedOn,
|
||||
{
|
||||
author: post.author,
|
||||
time: timeago.format(post.createdAt, intl.locale),
|
||||
},
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="d-flex align-items-center mr-3">
|
||||
<FontAwesomeIcon icon={faComments} className="mr-2" />
|
||||
<span style={{ minWidth: '2rem' }}>
|
||||
{post.commentCount}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex mr-3">
|
||||
<Icon src={QuestionAnswer} />
|
||||
<span style={{ minWidth: '2rem' }}>
|
||||
{post.commentCount}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -109,35 +102,22 @@ function Post({
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column mt-2">
|
||||
<div className="d-flex flex-column p-2.5 w-100">
|
||||
<PostHeader post={post} intl={intl} />
|
||||
<div className="d-flex mt-2 mb-0 p-0" dangerouslySetInnerHTML={{ __html: post.renderedBody }} />
|
||||
<div className="d-flex align-items-center">
|
||||
<div className="d-flex align-items-center">
|
||||
<OverlayTrigger overlay={(
|
||||
<LikeButton
|
||||
count={post.voteCount}
|
||||
onClick={() => dispatch(updateExistingThread(post.id, { voted: !post.voted }))}
|
||||
voted={post.voted}
|
||||
/>
|
||||
<OverlayTrigger
|
||||
className="mx-2.5"
|
||||
overlay={(
|
||||
<Tooltip>
|
||||
{intl.formatMessage(post.voted ? messages.removeLike : messages.like)}
|
||||
{intl.formatMessage(post.following ? messages.unfollow : messages.follow)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<IconButton
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
dispatch(updateExistingThread(post.id, { voted: !post.voted }));
|
||||
return false;
|
||||
}}
|
||||
alt="Like"
|
||||
size="inline"
|
||||
icon={post.voted ? faSolidThumb : faEmptyThumb}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
{post.voteCount}
|
||||
</div>
|
||||
<OverlayTrigger overlay={(
|
||||
<Tooltip>
|
||||
{intl.formatMessage(post.following ? messages.unfollow : messages.follow)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
@@ -145,8 +125,9 @@ function Post({
|
||||
return true;
|
||||
}}
|
||||
alt="Follow"
|
||||
iconAs={Icon}
|
||||
size="inline"
|
||||
icon={post.following ? faSolidStar : faEmptyStar}
|
||||
src={post.following ? StarFilled : StarOutline}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
import { faCircle, faFlag } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import { Flag, Unread } from '@edx/paragon/icons';
|
||||
|
||||
import { Routes } from '../../../data/constants';
|
||||
import messages from './messages';
|
||||
@@ -24,13 +24,13 @@ function PostLink({
|
||||
}
|
||||
>
|
||||
{post.abuseFlagged && (
|
||||
<div className="bg-gray-100 flex-fill">
|
||||
<FontAwesomeIcon icon={faFlag} className="mx-1" />
|
||||
{intl.formatMessage(messages.contentReported)}
|
||||
<div className="align-items-center bg-danger-100 d-flex flex-fill p-1">
|
||||
<Icon className="text-danger-700" src={Flag} />
|
||||
<span className="text-gray-700 x-small">{intl.formatMessage(messages.contentReported)}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="d-flex flex-row mb-2">
|
||||
<FontAwesomeIcon icon={faCircle} className={`my-1 text-accent-a ${post.read && 'invisible'}`} size="xs" />
|
||||
<div className="d-flex flex-row p-2">
|
||||
{!post.read && <Icon className="text-brand-500" src={Unread} />}
|
||||
<Post post={post} />
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -7,7 +7,7 @@ const messages = defineMessages({
|
||||
},
|
||||
postedOn: {
|
||||
id: 'discussions.post.posted-on',
|
||||
defaultMessage: 'Posted {time}',
|
||||
defaultMessage: 'Posted {time} by {author}',
|
||||
},
|
||||
contentReported: {
|
||||
id: 'discussions.post.content-reported',
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faComments, faFlag } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import { Flag, Help, QuestionAnswer } from '@edx/paragon/icons';
|
||||
import { useParams } from 'react-router';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
@@ -33,16 +32,16 @@ function Topic({
|
||||
</div>
|
||||
<div className="d-flex text-gray-300 h4 mt-1 mb-0">
|
||||
<div className="badge mr-4">
|
||||
<FontAwesomeIcon className="mr-2" icon={faQuestionCircle} />
|
||||
<Icon className="mr-2" src={Help} />
|
||||
{questions}
|
||||
</div>
|
||||
<div className="badge mr-4">
|
||||
<FontAwesomeIcon className="mr-2" icon={faComments} />
|
||||
<Icon className="mr-2" src={QuestionAnswer} />
|
||||
{discussions}
|
||||
</div>
|
||||
{flags !== null && (
|
||||
<div className="badge">
|
||||
<FontAwesomeIcon className="mr-2" icon={faFlag} />
|
||||
<Icon className="mr-2" src={Flag} />
|
||||
{flags}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
import { faSort } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { SearchField } from '@edx/paragon';
|
||||
import { Icon, SearchField } from '@edx/paragon';
|
||||
import { ArrowDropUpDown } from '@edx/paragon/icons';
|
||||
|
||||
import { SelectableDropdown } from '../../../components';
|
||||
import { TopicOrdering } from '../../../data/constants';
|
||||
@@ -27,9 +26,7 @@ function TopicSearchBar({ intl }) {
|
||||
<SelectableDropdown
|
||||
options={topicOrderingOptions}
|
||||
onChange={(option) => dispatch(setSortBy(option.value))}
|
||||
label={
|
||||
<FontAwesomeIcon icon={faSort} />
|
||||
}
|
||||
label={<Icon src={ArrowDropUpDown} />}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user