Compare commits
47 Commits
open-relea
...
ahtisham/I
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2db3a5b68e | ||
|
|
202fd3315a | ||
|
|
fe8ffbd345 | ||
|
|
2913de47ac | ||
|
|
9a26173b7f | ||
|
|
ad3346ea09 | ||
|
|
545b69376f | ||
|
|
af029b43a2 | ||
|
|
b7aff94513 | ||
|
|
c26c7d34e6 | ||
|
|
2eee6c3ca2 | ||
|
|
e7a41b2391 | ||
|
|
ad42959e56 | ||
|
|
67b0b33a81 | ||
|
|
da108a2054 | ||
|
|
1005752bf1 | ||
|
|
31a66f6832 | ||
|
|
37053e9bd3 | ||
|
|
9f84230c17 | ||
|
|
d60f1afa6b | ||
|
|
df6a0d4293 | ||
|
|
e8bd91b418 | ||
|
|
bdaa13a7ad | ||
|
|
5ab324c9ca | ||
|
|
00ab8283e2 | ||
|
|
1719315681 | ||
|
|
8e19eed468 | ||
|
|
11460a3d26 | ||
|
|
a3d0273de6 | ||
|
|
f1d2de6694 | ||
|
|
1169de04f6 | ||
|
|
aa7a5a8cc1 | ||
|
|
9d9377bb8c | ||
|
|
f45f47f2e0 | ||
|
|
bea247f6e5 | ||
|
|
9e878fc916 | ||
|
|
21176131a7 | ||
|
|
b23846b1e4 | ||
|
|
7912d70388 | ||
|
|
42f1efd0a0 | ||
|
|
8e449acde7 | ||
|
|
5f477cb93f | ||
|
|
cf8f08172f | ||
|
|
b72dbae4f0 | ||
|
|
f805f73447 | ||
|
|
27c4d7e3d6 | ||
|
|
b976e812dc |
755
package-lock.json
generated
755
package-lock.json
generated
@@ -10,9 +10,9 @@
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
||||
"@edx/frontend-component-footer": "12.0.0",
|
||||
"@edx/frontend-component-header": "4.0.0",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/frontend-component-footer": "11.2.0",
|
||||
"@edx/frontend-component-header": "3.2.0",
|
||||
"@edx/frontend-platform": "2.6.1",
|
||||
"@edx/paragon": "20.15.0",
|
||||
"@reduxjs/toolkit": "1.8.0",
|
||||
"@tinymce/tinymce-react": "3.13.1",
|
||||
@@ -3395,42 +3395,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-footer": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-12.0.0.tgz",
|
||||
"integrity": "sha512-m8Rx6ZPWzIN5XLrz6Ft3aTuFo0rty0jECd79CBYWdm0D9KD1WxoYEG+fElluyOQp/t42T5jLImHTSWjFURx5kw==",
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-11.2.0.tgz",
|
||||
"integrity": "sha512-prN6SeoWenbNq6jCqlpmYx57OhNbVGw1wjQFVH+aA5JMjjLUf6PmjPG87fuD9udQyFteb2lvbCyongPEZOozrg==",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/react-fontawesome": "0.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@edx/frontend-platform": "^4.0.0",
|
||||
"@edx/frontend-platform": "^2.3.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.9.0 || ^17.0.0",
|
||||
"react-dom": "^16.9.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz",
|
||||
"integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"react": "^16.9.0",
|
||||
"react-dom": "^16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-footer/node_modules/@fortawesome/react-fontawesome": {
|
||||
@@ -3446,110 +3425,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-4.0.0.tgz",
|
||||
"integrity": "sha512-r/L3p2ZSI1DitjxVKAor18GmgJllafYslrdpzGI0vcX/gTemH13jf2Xr9iQqrT921DP2nzZ5GOwGJNptTSjiaA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-3.2.0.tgz",
|
||||
"integrity": "sha512-ep9yOwe9CG03lSf/QBsBOZO3S/Ksrttgi4MkjpUe/6Sm/KdAnMCOhx2Gbj9jBcFrHqCkpeef26zGjjhpHGDwkQ==",
|
||||
"dependencies": {
|
||||
"@edx/paragon": "20.30.1",
|
||||
"@fortawesome/fontawesome-svg-core": "6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-transition-group": "4.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@edx/frontend-platform": "^4.0.0",
|
||||
"@edx/frontend-platform": "^2.0.0",
|
||||
"@edx/paragon": ">= 7.0.0 < 21.0.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.9.0 || ^17.0.0",
|
||||
"react-dom": "^16.9.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@edx/paragon": {
|
||||
"version": "20.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.30.1.tgz",
|
||||
"integrity": "sha512-v3Ek8deZWqVKi3IWP08Mj4egrvbmbqQEyRA6+qazHZdgHJA4qOP1SST42UKd9XxPeRbLWUgaJWd0iBAOAna/gw==",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||
"@popperjs/core": "^2.11.4",
|
||||
"bootstrap": "^4.6.2",
|
||||
"classnames": "^2.3.1",
|
||||
"email-prop-type": "^3.0.0",
|
||||
"file-selector": "^0.6.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"glob": "^8.0.3",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"mailto-link": "^2.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-bootstrap": "^1.6.5",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dropzone": "^14.2.1",
|
||||
"react-focus-on": "^3.5.4",
|
||||
"react-loading-skeleton": "^3.1.0",
|
||||
"react-popper": "^2.2.5",
|
||||
"react-proptype-conditional-require": "^1.0.4",
|
||||
"react-responsive": "^8.2.0",
|
||||
"react-table": "^7.7.0",
|
||||
"react-transition-group": "^4.4.2",
|
||||
"tabbable": "^5.3.3",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.6 || ^17.0.0",
|
||||
"react-dom": "^16.8.6 || ^17.0.0",
|
||||
"react-intl": "^5.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@edx/paragon/node_modules/@fortawesome/react-fontawesome": {
|
||||
"version": "0.1.19",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz",
|
||||
"integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
|
||||
"react": ">=16.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-xI0c+a8xnKItAXCN8rZgCNCJQiVAd2Y7p9e2ND6zN3J3ekneu96qrePieJ7yA7073C1JxxoM3vH1RU7rYsaj8w==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-regular-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-cZnwiVHZ51SVzWHOaNCIA+u9wevZjCuAGSvSYpNlm6A4H4Vhwh8481Bf/5rwheIC3fFKlgXxLKaw8Xeroz8Ntg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-solid-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-x5tMwzF2lTH8pyv8yeZRodItP2IVlzzmBuD1M7BjawWgg9XAvktqJJ91Qjgoaf8qJpHQ8FEU9VxRfOkLhh86QA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"react": "^16.9.0",
|
||||
"react-dom": "^16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/react-fontawesome": {
|
||||
@@ -3564,63 +3458,18 @@
|
||||
"react": ">=16.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-component-header/node_modules/uuid": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-platform": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-4.2.0.tgz",
|
||||
"integrity": "sha512-iDoFeccENQKBjqUgdjl5KSwBrjNEj8YW6Ual+6twcHHJUBg3yRoBEphwHIoRREcMgQjhdKVAdWj8eleh4JsEKA==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-2.6.1.tgz",
|
||||
"integrity": "sha512-5ZcHBvwmJRYPPKEqv+H4DbsfW9atr5V2+uY/zX58F/Tqh0T5X8MmgppVjplWFbmon5QV4aNw5C1ViQnirNqUiA==",
|
||||
"dependencies": {
|
||||
"@cospired/i18n-iso-languages": "2.2.0",
|
||||
"@formatjs/intl-pluralrules": "4.3.3",
|
||||
"@formatjs/intl-relativetimeformat": "10.0.1",
|
||||
"axios": "0.27.2",
|
||||
"axios-cache-interceptor": "0.10.7",
|
||||
"axios": "0.26.1",
|
||||
"axios-cache-adapter": "2.7.3",
|
||||
"form-urlencoded": "4.1.4",
|
||||
"glob": "7.2.3",
|
||||
"glob": "7.2.0",
|
||||
"history": "4.10.1",
|
||||
"i18n-iso-countries": "4.3.1",
|
||||
"jwt-decode": "3.1.2",
|
||||
@@ -3635,58 +3484,24 @@
|
||||
"universal-cookie": "4.0.4"
|
||||
},
|
||||
"bin": {
|
||||
"intl-imports.js": "i18n/scripts/intl-imports.js",
|
||||
"transifex-utils.js": "i18n/scripts/transifex-utils.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@edx/paragon": ">= 10.0.0 < 21.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.9.0 || ^17.0.0",
|
||||
"react-dom": "^16.9.0 || ^17.0.0",
|
||||
"react": "^16.9.0",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-redux": "^7.1.1",
|
||||
"react-router-dom": "^5.0.1",
|
||||
"redux": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-platform/node_modules/axios": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-platform/node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-platform/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
"follow-redirects": "^1.14.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/new-relic-source-map-webpack-plugin": {
|
||||
@@ -3733,6 +3548,27 @@
|
||||
"react-intl": "^5.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/paragon/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
|
||||
"integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/paragon/node_modules/@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz",
|
||||
"integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/paragon/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
@@ -4056,89 +3892,62 @@
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.3.0.tgz",
|
||||
"integrity": "sha512-4BC1NMoacEBzSXRwKjZ/X/gmnbp/HU5Qqat7E8xqorUtBFZS+bwfGH5/wqOC2K6GV0rgEobp3OjGRMa5fK9pFg==",
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.3.0.tgz",
|
||||
"integrity": "sha512-uz9YifyKlixV6AcKlOX8WNdtF7l6nakGyLYxYaCa823bEBqyj/U2ssqtctO38itNEwXb8/lMzjdoJ+aaJuOdrw==",
|
||||
"version": "1.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
|
||||
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/react-fontawesome": {
|
||||
"version": "0.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz",
|
||||
@@ -7677,7 +7486,8 @@
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/at-least-node": {
|
||||
"version": "1.0.0",
|
||||
@@ -7739,22 +7549,20 @@
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios-cache-interceptor": {
|
||||
"version": "0.10.7",
|
||||
"resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-0.10.7.tgz",
|
||||
"integrity": "sha512-UjpxChG5DpF6Kf1IPGMLOzRDNL8ZNS6TOn1jTaVvCE7cWFU904jJwi0T1s+IbijpnLEjK2iq5uLIuR8Sj+RsFQ==",
|
||||
"node_modules/axios-cache-adapter": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/axios-cache-adapter/-/axios-cache-adapter-2.7.3.tgz",
|
||||
"integrity": "sha512-A+ZKJ9lhpjthOEp4Z3QR/a9xC4du1ALaAsejgRGrH9ef6kSDxdFrhRpulqsh9khsEnwXxGfgpUuDp1YXMNMEiQ==",
|
||||
"dependencies": {
|
||||
"cache-parser": "^1.2.4",
|
||||
"fast-defer": "^1.1.7",
|
||||
"object-code": "^1.2.4"
|
||||
"cache-control-esm": "1.0.0",
|
||||
"md5": "^2.2.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/ArthurFiorette/axios-cache-interceptor?sponsor=1"
|
||||
"peerDependencies": {
|
||||
"axios": "~0.21.1"
|
||||
}
|
||||
},
|
||||
"node_modules/axios-mock-adapter": {
|
||||
@@ -8910,10 +8718,10 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cache-parser": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-O0KwuHuJnbHUrghHi2kGp0SxnWSIBXTYt7M8WVhW0kbPRUNUKoE/Of6e1rRD6AAxmfxFunKnt90yEK09D+sc5g=="
|
||||
"node_modules/cache-control-esm": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cache-control-esm/-/cache-control-esm-1.0.0.tgz",
|
||||
"integrity": "sha512-Fa3UV4+eIk4EOih8FTV6EEsVKO0W5XWtNs6FC3InTfVz+EjurjPfDXY5wZDo/lxjDxg5RjNcurLyxEJBcEUx9g=="
|
||||
},
|
||||
"node_modules/cacheable-request": {
|
||||
"version": "2.1.4",
|
||||
@@ -9146,6 +8954,14 @@
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/charenc": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
|
||||
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/check-types": {
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
|
||||
@@ -9588,6 +9404,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
@@ -9886,6 +9703,14 @@
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/crypt": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
|
||||
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
@@ -10681,6 +10506,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
@@ -12523,11 +12349,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fast-defer": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.7.tgz",
|
||||
"integrity": "sha512-tJ01ulDWT2WhqxMKS20nXX6wyX2iInBYpbN3GO7yjKwXMY4qvkdBRxak9IFwBLlFDESox+SwSvqMCZDfe1tqeg=="
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
|
||||
@@ -13596,7 +13417,6 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@@ -19883,6 +19703,21 @@
|
||||
"css-mediaquery": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/md5": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
|
||||
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||
"dependencies": {
|
||||
"charenc": "0.0.2",
|
||||
"crypt": "0.0.2",
|
||||
"is-buffer": "~1.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/md5/node_modules/is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
@@ -20460,11 +20295,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-code": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/object-code/-/object-code-1.2.4.tgz",
|
||||
"integrity": "sha512-uGq4ETUuWe+GA586NXEriiaozNuff+YNFXlpD8cVrM1GoiuTZpCABP+bZCWDrvQDoCiSTyiWAFHD/HF/iwhb2w=="
|
||||
},
|
||||
"node_modules/object-copy": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
|
||||
@@ -22455,15 +22285,6 @@
|
||||
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-colorful": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
|
||||
"integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.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",
|
||||
@@ -30201,30 +30022,17 @@
|
||||
}
|
||||
},
|
||||
"@edx/frontend-component-footer": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-12.0.0.tgz",
|
||||
"integrity": "sha512-m8Rx6ZPWzIN5XLrz6Ft3aTuFo0rty0jECd79CBYWdm0D9KD1WxoYEG+fElluyOQp/t42T5jLImHTSWjFURx5kw==",
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-11.2.0.tgz",
|
||||
"integrity": "sha512-prN6SeoWenbNq6jCqlpmYx57OhNbVGw1wjQFVH+aA5JMjjLUf6PmjPG87fuD9udQyFteb2lvbCyongPEZOozrg==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/react-fontawesome": "0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ=="
|
||||
},
|
||||
"@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz",
|
||||
"integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/react-fontawesome": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
|
||||
@@ -30236,87 +30044,20 @@
|
||||
}
|
||||
},
|
||||
"@edx/frontend-component-header": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-4.0.0.tgz",
|
||||
"integrity": "sha512-r/L3p2ZSI1DitjxVKAor18GmgJllafYslrdpzGI0vcX/gTemH13jf2Xr9iQqrT921DP2nzZ5GOwGJNptTSjiaA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-3.2.0.tgz",
|
||||
"integrity": "sha512-ep9yOwe9CG03lSf/QBsBOZO3S/Ksrttgi4MkjpUe/6Sm/KdAnMCOhx2Gbj9jBcFrHqCkpeef26zGjjhpHGDwkQ==",
|
||||
"requires": {
|
||||
"@edx/paragon": "20.30.1",
|
||||
"@fortawesome/fontawesome-svg-core": "6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-transition-group": "4.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@edx/paragon": {
|
||||
"version": "20.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.30.1.tgz",
|
||||
"integrity": "sha512-v3Ek8deZWqVKi3IWP08Mj4egrvbmbqQEyRA6+qazHZdgHJA4qOP1SST42UKd9XxPeRbLWUgaJWd0iBAOAna/gw==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||
"@popperjs/core": "^2.11.4",
|
||||
"bootstrap": "^4.6.2",
|
||||
"classnames": "^2.3.1",
|
||||
"email-prop-type": "^3.0.0",
|
||||
"file-selector": "^0.6.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"glob": "^8.0.3",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"mailto-link": "^2.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-bootstrap": "^1.6.5",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dropzone": "^14.2.1",
|
||||
"react-focus-on": "^3.5.4",
|
||||
"react-loading-skeleton": "^3.1.0",
|
||||
"react-popper": "^2.2.5",
|
||||
"react-proptype-conditional-require": "^1.0.4",
|
||||
"react-responsive": "^8.2.0",
|
||||
"react-table": "^7.7.0",
|
||||
"react-transition-group": "^4.4.2",
|
||||
"tabbable": "^5.3.3",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/react-fontawesome": {
|
||||
"version": "0.1.19",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz",
|
||||
"integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-xI0c+a8xnKItAXCN8rZgCNCJQiVAd2Y7p9e2ND6zN3J3ekneu96qrePieJ7yA7073C1JxxoM3vH1RU7rYsaj8w==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-regular-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-cZnwiVHZ51SVzWHOaNCIA+u9wevZjCuAGSvSYpNlm6A4H4Vhwh8481Bf/5rwheIC3fFKlgXxLKaw8Xeroz8Ntg==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-solid-svg-icons": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.3.0.tgz",
|
||||
"integrity": "sha512-x5tMwzF2lTH8pyv8yeZRodItP2IVlzzmBuD1M7BjawWgg9XAvktqJJ91Qjgoaf8qJpHQ8FEU9VxRfOkLhh86QA==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/react-fontawesome": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
|
||||
@@ -30324,54 +30065,21 @@
|
||||
"requires": {
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@edx/frontend-platform": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-4.2.0.tgz",
|
||||
"integrity": "sha512-iDoFeccENQKBjqUgdjl5KSwBrjNEj8YW6Ual+6twcHHJUBg3yRoBEphwHIoRREcMgQjhdKVAdWj8eleh4JsEKA==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-2.6.1.tgz",
|
||||
"integrity": "sha512-5ZcHBvwmJRYPPKEqv+H4DbsfW9atr5V2+uY/zX58F/Tqh0T5X8MmgppVjplWFbmon5QV4aNw5C1ViQnirNqUiA==",
|
||||
"requires": {
|
||||
"@cospired/i18n-iso-languages": "2.2.0",
|
||||
"@formatjs/intl-pluralrules": "4.3.3",
|
||||
"@formatjs/intl-relativetimeformat": "10.0.1",
|
||||
"axios": "0.27.2",
|
||||
"axios-cache-interceptor": "0.10.7",
|
||||
"axios": "0.26.1",
|
||||
"axios-cache-adapter": "2.7.3",
|
||||
"form-urlencoded": "4.1.4",
|
||||
"glob": "7.2.3",
|
||||
"glob": "7.2.0",
|
||||
"history": "4.10.1",
|
||||
"i18n-iso-countries": "4.3.1",
|
||||
"jwt-decode": "3.1.2",
|
||||
@@ -30387,35 +30095,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
"follow-redirects": "^1.14.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30459,6 +30143,19 @@
|
||||
"uncontrollable": "^7.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
|
||||
"integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg=="
|
||||
},
|
||||
"@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz",
|
||||
"integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.2.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
@@ -30782,61 +30479,40 @@
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.3.0.tgz",
|
||||
"integrity": "sha512-4BC1NMoacEBzSXRwKjZ/X/gmnbp/HU5Qqat7E8xqorUtBFZS+bwfGH5/wqOC2K6GV0rgEobp3OjGRMa5fK9pFg=="
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg=="
|
||||
},
|
||||
"@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.3.0.tgz",
|
||||
"integrity": "sha512-uz9YifyKlixV6AcKlOX8WNdtF7l6nakGyLYxYaCa823bEBqyj/U2ssqtctO38itNEwXb8/lMzjdoJ+aaJuOdrw==",
|
||||
"version": "1.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
|
||||
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.3.0"
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ=="
|
||||
}
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-regular-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ=="
|
||||
}
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-solid-svg-icons": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz",
|
||||
"integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==",
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz",
|
||||
"integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ=="
|
||||
}
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/react-fontawesome": {
|
||||
@@ -33583,7 +33259,8 @@
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
@@ -33620,19 +33297,17 @@
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
},
|
||||
"axios-cache-interceptor": {
|
||||
"version": "0.10.7",
|
||||
"resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-0.10.7.tgz",
|
||||
"integrity": "sha512-UjpxChG5DpF6Kf1IPGMLOzRDNL8ZNS6TOn1jTaVvCE7cWFU904jJwi0T1s+IbijpnLEjK2iq5uLIuR8Sj+RsFQ==",
|
||||
"axios-cache-adapter": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/axios-cache-adapter/-/axios-cache-adapter-2.7.3.tgz",
|
||||
"integrity": "sha512-A+ZKJ9lhpjthOEp4Z3QR/a9xC4du1ALaAsejgRGrH9ef6kSDxdFrhRpulqsh9khsEnwXxGfgpUuDp1YXMNMEiQ==",
|
||||
"requires": {
|
||||
"cache-parser": "^1.2.4",
|
||||
"fast-defer": "^1.1.7",
|
||||
"object-code": "^1.2.4"
|
||||
"cache-control-esm": "1.0.0",
|
||||
"md5": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"axios-mock-adapter": {
|
||||
@@ -34552,10 +34227,10 @@
|
||||
"unset-value": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"cache-parser": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-O0KwuHuJnbHUrghHi2kGp0SxnWSIBXTYt7M8WVhW0kbPRUNUKoE/Of6e1rRD6AAxmfxFunKnt90yEK09D+sc5g=="
|
||||
"cache-control-esm": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cache-control-esm/-/cache-control-esm-1.0.0.tgz",
|
||||
"integrity": "sha512-Fa3UV4+eIk4EOih8FTV6EEsVKO0W5XWtNs6FC3InTfVz+EjurjPfDXY5wZDo/lxjDxg5RjNcurLyxEJBcEUx9g=="
|
||||
},
|
||||
"cacheable-request": {
|
||||
"version": "2.1.4",
|
||||
@@ -34740,6 +34415,11 @@
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||
"dev": true
|
||||
},
|
||||
"charenc": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
|
||||
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="
|
||||
},
|
||||
"check-types": {
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
|
||||
@@ -35098,6 +34778,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@@ -35331,6 +35012,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypt": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
|
||||
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="
|
||||
},
|
||||
"css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
@@ -35934,7 +35620,8 @@
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
@@ -37400,11 +37087,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fast-defer": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.7.tgz",
|
||||
"integrity": "sha512-tJ01ulDWT2WhqxMKS20nXX6wyX2iInBYpbN3GO7yjKwXMY4qvkdBRxak9IFwBLlFDESox+SwSvqMCZDfe1tqeg=="
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
|
||||
@@ -38188,7 +37870,6 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@@ -42978,6 +42659,23 @@
|
||||
"css-mediaquery": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"md5": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
|
||||
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||
"requires": {
|
||||
"charenc": "0.0.2",
|
||||
"crypt": "0.0.2",
|
||||
"is-buffer": "~1.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
@@ -43425,11 +43123,6 @@
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
},
|
||||
"object-code": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/object-code/-/object-code-1.2.4.tgz",
|
||||
"integrity": "sha512-uGq4ETUuWe+GA586NXEriiaozNuff+YNFXlpD8cVrM1GoiuTZpCABP+bZCWDrvQDoCiSTyiWAFHD/HF/iwhb2w=="
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
|
||||
@@ -44842,12 +44535,6 @@
|
||||
"@babel/runtime": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"react-colorful": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
|
||||
"integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
||||
"@edx/frontend-component-footer": "12.0.0",
|
||||
"@edx/frontend-component-header": "4.0.0",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/frontend-component-footer": "11.2.0",
|
||||
"@edx/frontend-component-header": "3.2.0",
|
||||
"@edx/frontend-platform": "2.6.1",
|
||||
"@edx/paragon": "20.15.0",
|
||||
"@reduxjs/toolkit": "1.8.0",
|
||||
"@tinymce/tinymce-react": "3.13.1",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { camelCaseObject } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
import { getApiBaseUrl } from '../../../data/constants';
|
||||
import { API_BASE_URL } from '../../../data/constants';
|
||||
|
||||
function normalizeCourseHomeCourseMetadata(metadata, rootSlug) {
|
||||
const data = camelCaseObject(metadata);
|
||||
@@ -21,7 +21,7 @@ function normalizeCourseHomeCourseMetadata(metadata, rootSlug) {
|
||||
}
|
||||
|
||||
export async function getCourseHomeCourseMetadata(courseId, rootSlug) {
|
||||
const url = `${getApiBaseUrl()}/api/course_home/course_metadata/${courseId}`;
|
||||
const url = `${API_BASE_URL}/api/course_home/course_metadata/${courseId}`;
|
||||
// don't know the context of adding timezone in url. hence omitting it
|
||||
// url = appendBrowserTimezoneToUrl(url);
|
||||
const { data } = await getAuthenticatedHttpClient().get(url);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
@@ -14,7 +14,6 @@ import postsMessages from '../discussions/posts/post-actions-bar/messages';
|
||||
import { setFilter as setTopicFilter } from '../discussions/topics/data/slices';
|
||||
|
||||
function Search({ intl }) {
|
||||
const [previousSearchValue, setPreviousSearchValue] = useState('');
|
||||
const dispatch = useDispatch();
|
||||
const { page } = useContext(DiscussionContext);
|
||||
const postSearch = useSelector(({ threads }) => threads.filters.search);
|
||||
@@ -36,7 +35,6 @@ function Search({ intl }) {
|
||||
dispatch(setSearchQuery(''));
|
||||
dispatch(setTopicFilter(''));
|
||||
dispatch(setUsernameSearch(''));
|
||||
setPreviousSearchValue('');
|
||||
};
|
||||
|
||||
const onChange = (query) => {
|
||||
@@ -44,7 +42,7 @@ function Search({ intl }) {
|
||||
};
|
||||
|
||||
const onSubmit = (query) => {
|
||||
if (query === '' || query === previousSearchValue) {
|
||||
if (query === '') {
|
||||
return;
|
||||
}
|
||||
if (isPostSearch) {
|
||||
@@ -54,7 +52,6 @@ function Search({ intl }) {
|
||||
} else if (page === 'learners') {
|
||||
dispatch(setUsernameSearch(query));
|
||||
}
|
||||
setPreviousSearchValue(query);
|
||||
};
|
||||
|
||||
useEffect(() => onClear(), [page]);
|
||||
|
||||
@@ -32,6 +32,7 @@ import 'tinymce/plugins/lists';
|
||||
import 'tinymce/plugins/emoticons';
|
||||
import 'tinymce/plugins/emoticons/js/emojis';
|
||||
import 'tinymce/plugins/charmap';
|
||||
import 'tinymce/plugins/paste';
|
||||
/* eslint import/no-webpack-loader-syntax: off */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import edxBrandCss from '!!raw-loader!sass-loader!../index.scss';
|
||||
@@ -100,12 +101,13 @@ export default function TinyMCEEditor(props) {
|
||||
skin: false,
|
||||
menubar: false,
|
||||
branding: false,
|
||||
paste_data_images: false,
|
||||
contextmenu: false,
|
||||
browser_spellcheck: true,
|
||||
a11y_advanced_options: true,
|
||||
autosave_interval: '1s',
|
||||
autosave_restore_when_empty: false,
|
||||
plugins: 'autoresize autosave codesample link lists image imagetools code emoticons charmap',
|
||||
plugins: 'autoresize autosave codesample link lists image imagetools code emoticons charmap paste',
|
||||
toolbar: 'undo redo'
|
||||
+ ' | formatselect | bold italic underline'
|
||||
+ ' | link blockquote openedx_code image'
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
import { getApiBaseUrl } from './constants';
|
||||
import { API_BASE_URL } from './constants';
|
||||
|
||||
export const getBlocksAPIURL = () => `${getApiBaseUrl()}/api/courses/v1/blocks/`;
|
||||
export const blocksAPIURL = `${API_BASE_URL}/api/courses/v1/blocks/`;
|
||||
export async function getCourseBlocks(courseId, username) {
|
||||
const params = {
|
||||
course_id: courseId,
|
||||
@@ -14,6 +14,6 @@ export async function getCourseBlocks(courseId, username) {
|
||||
student_view_data: 'discussion',
|
||||
};
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(getBlocksAPIURL(), { params });
|
||||
.get(blocksAPIURL, { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
export const getApiBaseUrl = () => getConfig().LMS_BASE_URL;
|
||||
export const API_BASE_URL = getConfig().LMS_BASE_URL;
|
||||
|
||||
/**
|
||||
* Enum for thread types.
|
||||
|
||||
@@ -7,11 +7,10 @@ import { initializeMockApp } from '@edx/frontend-platform/testing';
|
||||
import { initializeStore } from '../store';
|
||||
import { executeThunk } from '../test-utils';
|
||||
import { getBlocksAPIResponse } from './__factories__';
|
||||
import { getBlocksAPIURL } from './api';
|
||||
import { blocksAPIURL } from './api';
|
||||
import { RequestStatus } from './constants';
|
||||
import { fetchCourseBlocks } from './thunks';
|
||||
|
||||
const blocksAPIURL = getBlocksAPIURL();
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
|
||||
let axiosMock;
|
||||
|
||||
@@ -6,7 +6,9 @@ ensureConfig([
|
||||
'LMS_BASE_URL',
|
||||
], 'Comments API service');
|
||||
|
||||
export const getCohortsApiUrl = courseId => `${getConfig().LMS_BASE_URL}/api/cohorts/v1/courses/${courseId}/cohorts/`;
|
||||
const apiBaseUrl = getConfig().LMS_BASE_URL;
|
||||
|
||||
export const getCohortsApiUrl = courseId => `${apiBaseUrl}/api/cohorts/v1/courses/${courseId}/cohorts/`;
|
||||
|
||||
export async function getCourseCohorts(courseId) {
|
||||
const params = snakeCaseObject({ courseId });
|
||||
|
||||
@@ -13,19 +13,16 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { getCourseConfigApiUrl } from '../data/api';
|
||||
import { courseConfigApiUrl } from '../data/api';
|
||||
import { fetchCourseConfig } from '../data/thunks';
|
||||
import DiscussionContent from '../discussions-home/DiscussionContent';
|
||||
import { getThreadsApiUrl } from '../posts/data/api';
|
||||
import { threadsApiUrl } from '../posts/data/api';
|
||||
import { fetchThreads } from '../posts/data/thunks';
|
||||
import { getCommentsApiUrl } from './data/api';
|
||||
import { commentsApiUrl } from './data/api';
|
||||
|
||||
import '../posts/data/__factories__';
|
||||
import './data/__factories__';
|
||||
|
||||
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
const commentsApiUrl = getCommentsApiUrl();
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
const discussionPostId = 'thread-1';
|
||||
const questionPostId = 'thread-2';
|
||||
const closedPostId = 'thread-2';
|
||||
@@ -384,6 +381,7 @@ describe('CommentsView', () => {
|
||||
});
|
||||
expect(testLocation.pathname).toBe(`/${courseId}/posts/${discussionPostId}/edit`);
|
||||
});
|
||||
|
||||
it('should allow pinning the post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
@@ -397,6 +395,7 @@ describe('CommentsView', () => {
|
||||
});
|
||||
assertLastUpdateData({ pinned: false });
|
||||
});
|
||||
|
||||
it('should allow reporting the post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
@@ -408,6 +407,11 @@ describe('CommentsView', () => {
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /report/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
|
||||
assertLastUpdateData({ abuse_flagged: true });
|
||||
});
|
||||
|
||||
@@ -426,12 +430,8 @@ describe('CommentsView', () => {
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
|
||||
});
|
||||
|
||||
it.each([
|
||||
['endorsing comments', 'Endorse', { endorsed: true }],
|
||||
['reporting comments', 'Report', { abuse_flagged: true }],
|
||||
])('handles %s', async (label, buttonLabel, patchData) => {
|
||||
it('handles endorsing comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// Wait for the content to load
|
||||
await screen.findByText('comment number 7', { exact: false });
|
||||
|
||||
@@ -441,11 +441,36 @@ describe('CommentsView', () => {
|
||||
await act(async () => {
|
||||
fireEvent.click(actionButtons[1]);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: buttonLabel }));
|
||||
fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
|
||||
});
|
||||
expect(axiosMock.history.patch).toHaveLength(2);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject(patchData);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
|
||||
});
|
||||
|
||||
it('handles reporting comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
// Wait for the content to load
|
||||
await screen.findByText('comment number 7', { exact: false });
|
||||
|
||||
// There should be three buttons, one for the post, the second for the
|
||||
// comment and the third for a response to that comment
|
||||
const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
|
||||
await act(async () => {
|
||||
fireEvent.click(actionButtons[1]);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /Report/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
|
||||
expect(axiosMock.history.patch).toHaveLength(2);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -627,12 +652,8 @@ describe('CommentsView', () => {
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
|
||||
});
|
||||
|
||||
it.each([
|
||||
['endorsing comments', 'Endorse', { endorsed: true }],
|
||||
['reporting comments', 'Report', { abuse_flagged: true }],
|
||||
])('handles %s', async (label, buttonLabel, patchData) => {
|
||||
it('handles endorsing comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// Wait for the content to load
|
||||
await screen.findByText('comment number 7', { exact: false });
|
||||
|
||||
@@ -642,11 +663,36 @@ describe('CommentsView', () => {
|
||||
await act(async () => {
|
||||
fireEvent.click(actionButtons[1]);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: buttonLabel }));
|
||||
fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
|
||||
});
|
||||
expect(axiosMock.history.patch).toHaveLength(2);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject(patchData);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
|
||||
});
|
||||
|
||||
it('handles reporting comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
// Wait for the content to load
|
||||
await screen.findByText('comment number 7', { exact: false });
|
||||
|
||||
// There should be three buttons, one for the post, the second for the
|
||||
// comment and the third for a response to that comment
|
||||
const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
|
||||
await act(async () => {
|
||||
fireEvent.click(actionButtons[1]);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /Report/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
|
||||
expect(axiosMock.history.patch).toHaveLength(2);
|
||||
expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,11 +9,10 @@ import { Button, useToggle } from '@edx/paragon';
|
||||
|
||||
import HTMLLoader from '../../../components/HTMLLoader';
|
||||
import { ContentActions } from '../../../data/constants';
|
||||
import { AlertBanner, DeleteConfirmation, EndorsedAlertBanner } from '../../common';
|
||||
import { AlertBanner, Confirmation, EndorsedAlertBanner } from '../../common';
|
||||
import { DiscussionContext } from '../../common/context';
|
||||
import { selectBlackoutDate } from '../../data/selectors';
|
||||
import { useUserCanAddThreadInBlackoutDate } from '../../data/hooks';
|
||||
import { fetchThread } from '../../posts/data/thunks';
|
||||
import { inBlackoutDateRange } from '../../utils';
|
||||
import CommentIcons from '../comment-icons/CommentIcons';
|
||||
import { selectCommentCurrentPage, selectCommentHasMorePages, selectCommentResponses } from '../data/selectors';
|
||||
import { editComment, fetchCommentResponses, removeComment } from '../data/thunks';
|
||||
@@ -36,10 +35,11 @@ function Comment({
|
||||
const inlineReplies = useSelector(selectCommentResponses(comment.id));
|
||||
const [isEditing, setEditing] = useState(false);
|
||||
const [isDeleting, showDeleteConfirmation, hideDeleteConfirmation] = useToggle(false);
|
||||
const [isReporting, showReportConfirmation, hideReportConfirmation] = useToggle(false);
|
||||
const [isReplying, setReplying] = useState(false);
|
||||
const hasMorePages = useSelector(selectCommentHasMorePages(comment.id));
|
||||
const currentPage = useSelector(selectCommentCurrentPage(comment.id));
|
||||
const blackoutDateRange = useSelector(selectBlackoutDate);
|
||||
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
|
||||
const {
|
||||
courseId,
|
||||
} = useContext(DiscussionContext);
|
||||
@@ -50,6 +50,24 @@ function Comment({
|
||||
}
|
||||
}, [comment.id]);
|
||||
|
||||
const handleAbusedFlag = () => {
|
||||
if (comment.abuseFlagged) {
|
||||
dispatch(editComment(comment.id, { flagged: !comment.abuseFlagged }));
|
||||
} else {
|
||||
showReportConfirmation();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteConfirmation = () => {
|
||||
dispatch(removeComment(comment.id));
|
||||
hideDeleteConfirmation();
|
||||
};
|
||||
|
||||
const handleReportConfirmation = () => {
|
||||
dispatch(editComment(comment.id, { flagged: !comment.abuseFlagged }));
|
||||
hideReportConfirmation();
|
||||
};
|
||||
|
||||
const actionHandlers = {
|
||||
[ContentActions.EDIT_CONTENT]: () => setEditing(true),
|
||||
[ContentActions.ENDORSE]: async () => {
|
||||
@@ -57,7 +75,7 @@ function Comment({
|
||||
await dispatch(fetchThread(comment.threadId, courseId));
|
||||
},
|
||||
[ContentActions.DELETE]: showDeleteConfirmation,
|
||||
[ContentActions.REPORT]: () => dispatch(editComment(comment.id, { flagged: !comment.abuseFlagged })),
|
||||
[ContentActions.REPORT]: () => handleAbusedFlag(),
|
||||
};
|
||||
|
||||
const handleLoadMoreComments = () => (
|
||||
@@ -67,16 +85,25 @@ function Comment({
|
||||
return (
|
||||
<div className={classNames({ 'py-2 my-3': showFullThread })}>
|
||||
<div className="d-flex flex-column card" data-testid={`comment-${comment.id}`} role="listitem">
|
||||
<DeleteConfirmation
|
||||
<Confirmation
|
||||
isOpen={isDeleting}
|
||||
title={intl.formatMessage(messages.deleteResponseTitle)}
|
||||
description={intl.formatMessage(messages.deleteResponseDescription)}
|
||||
onClose={hideDeleteConfirmation}
|
||||
onDelete={() => {
|
||||
dispatch(removeComment(comment.id));
|
||||
hideDeleteConfirmation();
|
||||
}}
|
||||
comfirmAction={handleDeleteConfirmation}
|
||||
closeButtonVaraint="tertiary"
|
||||
confirmButtonText={intl.formatMessage(messages.deleteConfirmationDelete)}
|
||||
/>
|
||||
{!comment.abuseFlagged && (
|
||||
<Confirmation
|
||||
isOpen={isReporting}
|
||||
title={intl.formatMessage(messages.reportResponseTitle)}
|
||||
description={intl.formatMessage(messages.reportResponseDescription)}
|
||||
onClose={hideReportConfirmation}
|
||||
comfirmAction={handleReportConfirmation}
|
||||
confirmButtonVariant="danger"
|
||||
/>
|
||||
)}
|
||||
<EndorsedAlertBanner postType={postType} content={comment} />
|
||||
<div className="d-flex flex-column p-4.5">
|
||||
<AlertBanner content={comment} />
|
||||
@@ -130,18 +157,18 @@ function Comment({
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{(!isClosedPost && !inBlackoutDateRange(blackoutDateRange))
|
||||
{!isClosedPost && userCanAddThreadInBlackoutDate
|
||||
&& (
|
||||
<Button
|
||||
className="d-flex flex-grow mt-3 py-2 font-size-14"
|
||||
variant="outline-primary"
|
||||
style={{
|
||||
lineHeight: '20px',
|
||||
}}
|
||||
onClick={() => setReplying(true)}
|
||||
>
|
||||
{intl.formatMessage(messages.addComment)}
|
||||
</Button>
|
||||
<Button
|
||||
className="d-flex flex-grow mt-3 py-2 font-size-14"
|
||||
variant="outline-primary"
|
||||
style={{
|
||||
lineHeight: '20px',
|
||||
}}
|
||||
onClick={() => setReplying(true)}
|
||||
>
|
||||
{intl.formatMessage(messages.addComment)}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
||||
|
||||
@@ -55,9 +55,7 @@ function CommentEditor({
|
||||
|
||||
const initialValues = {
|
||||
comment: comment.rawBody,
|
||||
editReasonCode: comment?.lastEdit?.reasonCode || (
|
||||
userIsStaff && canDisplayEditReason ? 'violates-guidelines' : undefined
|
||||
),
|
||||
editReasonCode: comment?.lastEdit?.reasonCode || (userIsStaff ? 'violates-guidelines' : ''),
|
||||
};
|
||||
|
||||
const handleCloseEditor = (resetForm) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Avatar, useToggle } from '@edx/paragon';
|
||||
import HTMLLoader from '../../../components/HTMLLoader';
|
||||
import { AvatarOutlineAndLabelColors, ContentActions } from '../../../data/constants';
|
||||
import {
|
||||
ActionsDropdown, AlertBanner, AuthorLabel, DeleteConfirmation,
|
||||
ActionsDropdown, AlertBanner, AuthorLabel, Confirmation,
|
||||
} from '../../common';
|
||||
import timeLocale from '../../common/time-locale';
|
||||
import { useAlertBannerVisible } from '../../data/hooks';
|
||||
@@ -29,6 +29,26 @@ function Reply({
|
||||
const dispatch = useDispatch();
|
||||
const [isEditing, setEditing] = useState(false);
|
||||
const [isDeleting, showDeleteConfirmation, hideDeleteConfirmation] = useToggle(false);
|
||||
const [isReporting, showReportConfirmation, hideReportConfirmation] = useToggle(false);
|
||||
|
||||
const handleAbusedFlag = () => {
|
||||
if (reply.abuseFlagged) {
|
||||
dispatch(editComment(reply.id, { flagged: !reply.abuseFlagged }));
|
||||
} else {
|
||||
showReportConfirmation();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteConfirmation = () => {
|
||||
dispatch(removeComment(reply.id));
|
||||
hideDeleteConfirmation();
|
||||
};
|
||||
|
||||
const handleReportConfirmation = () => {
|
||||
dispatch(editComment(reply.id, { flagged: !reply.abuseFlagged }));
|
||||
hideReportConfirmation();
|
||||
};
|
||||
|
||||
const actionHandlers = {
|
||||
[ContentActions.EDIT_CONTENT]: () => setEditing(true),
|
||||
[ContentActions.ENDORSE]: () => dispatch(editComment(
|
||||
@@ -37,7 +57,7 @@ function Reply({
|
||||
ContentActions.ENDORSE,
|
||||
)),
|
||||
[ContentActions.DELETE]: showDeleteConfirmation,
|
||||
[ContentActions.REPORT]: () => dispatch(editComment(reply.id, { flagged: !reply.abuseFlagged })),
|
||||
[ContentActions.REPORT]: () => handleAbusedFlag(),
|
||||
};
|
||||
const authorAvatars = useSelector(selectAuthorAvatars(reply.author));
|
||||
const colorClass = AvatarOutlineAndLabelColors[reply.authorLabel];
|
||||
@@ -45,17 +65,25 @@ function Reply({
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column mt-4.5" data-testid={`reply-${reply.id}`} role="listitem">
|
||||
<DeleteConfirmation
|
||||
<Confirmation
|
||||
isOpen={isDeleting}
|
||||
title={intl.formatMessage(messages.deleteCommentTitle)}
|
||||
description={intl.formatMessage(messages.deleteCommentDescription)}
|
||||
onClose={hideDeleteConfirmation}
|
||||
onDelete={() => {
|
||||
dispatch(removeComment(reply.id));
|
||||
hideDeleteConfirmation();
|
||||
}}
|
||||
comfirmAction={handleDeleteConfirmation}
|
||||
closeButtonVaraint="tertiary"
|
||||
confirmButtonText={intl.formatMessage(messages.deleteConfirmationDelete)}
|
||||
/>
|
||||
|
||||
{!reply.abuseFlagged && (
|
||||
<Confirmation
|
||||
isOpen={isReporting}
|
||||
title={intl.formatMessage(messages.reportCommentTitle)}
|
||||
description={intl.formatMessage(messages.reportCommentDescription)}
|
||||
onClose={hideReportConfirmation}
|
||||
comfirmAction={handleReportConfirmation}
|
||||
confirmButtonVariant="danger"
|
||||
/>
|
||||
)}
|
||||
{hasAnyAlert && (
|
||||
<div className="d-flex">
|
||||
<div className="d-flex invisible">
|
||||
|
||||
@@ -2,14 +2,12 @@ import React, { useContext, useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Button } from '@edx/paragon';
|
||||
|
||||
import { DiscussionContext } from '../../common/context';
|
||||
import { selectBlackoutDate } from '../../data/selectors';
|
||||
import { inBlackoutDateRange } from '../../utils';
|
||||
import { useUserCanAddThreadInBlackoutDate } from '../../data/hooks';
|
||||
import messages from '../messages';
|
||||
import CommentEditor from './CommentEditor';
|
||||
|
||||
@@ -20,13 +18,12 @@ function ResponseEditor({
|
||||
}) {
|
||||
const { inContext } = useContext(DiscussionContext);
|
||||
const [addingResponse, setAddingResponse] = useState(false);
|
||||
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
|
||||
|
||||
useEffect(() => {
|
||||
setAddingResponse(false);
|
||||
}, [postId]);
|
||||
|
||||
const blackoutDateRange = useSelector(selectBlackoutDate);
|
||||
|
||||
return addingResponse
|
||||
? (
|
||||
<div className={classNames({ 'bg-white p-4 mb-4 rounded': addWrappingDiv })}>
|
||||
@@ -37,7 +34,7 @@ function ResponseEditor({
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
: !inBlackoutDateRange(blackoutDateRange) && (
|
||||
: userCanAddThreadInBlackoutDate && (
|
||||
<div className={classNames({ 'mb-4': addWrappingDiv }, 'actions d-flex')}>
|
||||
<Button
|
||||
variant="primary"
|
||||
|
||||
@@ -8,7 +8,9 @@ ensureConfig([
|
||||
'LMS_BASE_URL',
|
||||
], 'Comments API service');
|
||||
|
||||
export const getCommentsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/comments/`;
|
||||
const apiBaseUrl = getConfig().LMS_BASE_URL;
|
||||
|
||||
export const commentsApiUrl = `${apiBaseUrl}/api/discussion/v1/comments/`;
|
||||
|
||||
/**
|
||||
* Returns all the comments for the specified thread.
|
||||
@@ -34,7 +36,7 @@ export async function getThreadComments(
|
||||
});
|
||||
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(getCommentsApiUrl(), { params });
|
||||
.get(commentsApiUrl, { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -51,7 +53,7 @@ export async function getCommentResponses(
|
||||
pageSize,
|
||||
} = {},
|
||||
) {
|
||||
const url = `${getCommentsApiUrl()}${commentId}/`;
|
||||
const url = `${commentsApiUrl}${commentId}/`;
|
||||
const params = snakeCaseObject({
|
||||
page,
|
||||
pageSize,
|
||||
@@ -71,7 +73,7 @@ export async function getCommentResponses(
|
||||
*/
|
||||
export async function postComment(comment, threadId, parentId = null) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.post(getCommentsApiUrl(), snakeCaseObject({ threadId, raw_body: comment, parentId }));
|
||||
.post(commentsApiUrl, snakeCaseObject({ threadId, raw_body: comment, parentId }));
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ export async function updateComment(commentId, {
|
||||
endorsed,
|
||||
editReasonCode,
|
||||
}) {
|
||||
const url = `${getCommentsApiUrl()}${commentId}/`;
|
||||
const url = `${commentsApiUrl}${commentId}/`;
|
||||
const postData = snakeCaseObject({
|
||||
raw_body: comment,
|
||||
voted,
|
||||
@@ -111,7 +113,7 @@ export async function updateComment(commentId, {
|
||||
* @param {string} commentId ID of comment to delete
|
||||
*/
|
||||
export async function deleteComment(commentId) {
|
||||
const url = `${getCommentsApiUrl()}${commentId}/`;
|
||||
const url = `${commentsApiUrl}${commentId}/`;
|
||||
await getAuthenticatedHttpClient()
|
||||
.delete(url);
|
||||
}
|
||||
|
||||
@@ -7,14 +7,13 @@ import { initializeMockApp } from '@edx/frontend-platform/testing';
|
||||
import { EndorsementStatus } from '../../../data/constants';
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
import { getCommentsApiUrl } from './api';
|
||||
import { commentsApiUrl } from './api';
|
||||
import {
|
||||
addComment, editComment, fetchCommentResponses, fetchThreadComments, removeComment,
|
||||
} from './thunks';
|
||||
|
||||
import './__factories__';
|
||||
|
||||
const commentsApiUrl = getCommentsApiUrl();
|
||||
let axiosMock;
|
||||
let store;
|
||||
|
||||
|
||||
@@ -148,6 +148,31 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Are you sure you want to permanently delete this comment?',
|
||||
description: 'Text displayed in confirmation dialog when deleting a comment',
|
||||
},
|
||||
deleteConfirmationDelete: {
|
||||
id: 'discussions.delete.confirmation.button.delete',
|
||||
defaultMessage: 'Delete',
|
||||
description: 'Delete button shown on delete confirmation dialog',
|
||||
},
|
||||
reportResponseTitle: {
|
||||
id: 'discussions.editor.response.response.title',
|
||||
defaultMessage: 'Report inappropriate content?',
|
||||
description: 'Title of confirmation dialog shown when reporting a response',
|
||||
},
|
||||
reportResponseDescription: {
|
||||
id: 'discussions.editor.response.description',
|
||||
defaultMessage: 'The discussion moderation team will review this content and take appropriate action.',
|
||||
description: 'Text displayed in confirmation dialog when deleting a response',
|
||||
},
|
||||
reportCommentTitle: {
|
||||
id: 'discussions.editor.report.comment.title',
|
||||
defaultMessage: 'Report inappropriate content?',
|
||||
description: 'Title of confirmation dialog shown when reporting a comment',
|
||||
},
|
||||
reportCommentDescription: {
|
||||
id: 'discussions.editor.report.comment.description',
|
||||
defaultMessage: 'The discussion moderation team will review this content and take appropriate action.',
|
||||
description: 'Text displayed in confirmation dialog when deleting a response',
|
||||
},
|
||||
editReasonCode: {
|
||||
id: 'discussions.editor.comments.editReasonCode',
|
||||
defaultMessage: 'Reason for editing',
|
||||
|
||||
@@ -52,37 +52,39 @@ function ActionsDropdown({
|
||||
size="sm"
|
||||
ref={setTarget}
|
||||
/>
|
||||
<ModalPopup
|
||||
onClose={close}
|
||||
positionRef={target}
|
||||
isOpen={isOpen}
|
||||
placement={inContext ? 'left' : 'auto-start'}
|
||||
>
|
||||
<div
|
||||
className="bg-white p-1 shadow d-flex flex-column"
|
||||
data-testid="actions-dropdown-modal-popup"
|
||||
<div className="actions-dropdown">
|
||||
<ModalPopup
|
||||
onClose={close}
|
||||
positionRef={target}
|
||||
isOpen={isOpen}
|
||||
placement={inContext ? 'left' : 'auto-start'}
|
||||
>
|
||||
{actions.map(action => (
|
||||
<React.Fragment key={action.id}>
|
||||
{action.action === ContentActions.DELETE
|
||||
<div
|
||||
className="bg-white p-1 shadow d-flex flex-column"
|
||||
data-testid="actions-dropdown-modal-popup"
|
||||
>
|
||||
{actions.map(action => (
|
||||
<React.Fragment key={action.id}>
|
||||
{(action.action === ContentActions.DELETE)
|
||||
&& <Dropdown.Divider />}
|
||||
|
||||
<Dropdown.Item
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
size="inline"
|
||||
onClick={() => {
|
||||
close();
|
||||
handleActions(action.action);
|
||||
}}
|
||||
className="d-flex justify-content-start py-1.5 mr-4"
|
||||
>
|
||||
<Icon src={action.icon} className="mr-1" /> {intl.formatMessage(action.label)}
|
||||
</Dropdown.Item>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</ModalPopup>
|
||||
<Dropdown.Item
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
size="inline"
|
||||
onClick={() => {
|
||||
close();
|
||||
handleActions(action.action);
|
||||
}}
|
||||
className="d-flex justify-content-start py-1.5 mr-4"
|
||||
>
|
||||
<Icon src={action.icon} className="mr-1" /> {intl.formatMessage(action.label)}
|
||||
</Dropdown.Item>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</ModalPopup>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useSelector } from 'react-redux';
|
||||
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Alert } from '@edx/paragon';
|
||||
import { Error } from '@edx/paragon/icons';
|
||||
import { Report } from '@edx/paragon/icons';
|
||||
|
||||
import { commentShape } from '../comments/comment/proptypes';
|
||||
import messages from '../comments/messages';
|
||||
@@ -28,7 +28,7 @@ function AlertBanner({
|
||||
return (
|
||||
<>
|
||||
{canSeeReportedBanner && (
|
||||
<Alert icon={Error} variant="danger" className="px-3 mb-2 py-10px shadow-none flex-fill">
|
||||
<Alert icon={Report} variant="danger" className="px-3 mb-2 py-10px shadow-none flex-fill">
|
||||
{intl.formatMessage(messages.abuseFlaggedMessage)}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
@@ -10,13 +10,12 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { getCourseConfigApiUrl } from '../data/api';
|
||||
import { courseConfigApiUrl } from '../data/api';
|
||||
import { fetchCourseConfig } from '../data/thunks';
|
||||
import AuthorLabel from './AuthorLabel';
|
||||
import { DiscussionContext } from './context';
|
||||
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
let store;
|
||||
let axiosMock;
|
||||
let container;
|
||||
|
||||
@@ -6,13 +6,16 @@ import { ActionRow, Button, ModalDialog } from '@edx/paragon';
|
||||
|
||||
import messages from '../messages';
|
||||
|
||||
function DeleteConfirmation({
|
||||
function Confirmation({
|
||||
intl,
|
||||
isOpen,
|
||||
title,
|
||||
description,
|
||||
onClose,
|
||||
onDelete,
|
||||
comfirmAction,
|
||||
closeButtonVaraint,
|
||||
confirmButtonVariant,
|
||||
confirmButtonText,
|
||||
}) {
|
||||
return (
|
||||
<ModalDialog title={title} isOpen={isOpen} hasCloseButton={false} onClose={onClose} zIndex={5000}>
|
||||
@@ -26,11 +29,11 @@ function DeleteConfirmation({
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<ActionRow>
|
||||
<ModalDialog.CloseButton variant="tertiary">
|
||||
{intl.formatMessage(messages.deleteConfirmationCancel)}
|
||||
<ModalDialog.CloseButton variant={closeButtonVaraint}>
|
||||
{intl.formatMessage(messages.confirmationCancel)}
|
||||
</ModalDialog.CloseButton>
|
||||
<Button variant="primary" onClick={onDelete}>
|
||||
{intl.formatMessage(messages.deleteConfirmationDelete)}
|
||||
<Button variant={confirmButtonVariant} onClick={comfirmAction}>
|
||||
{ confirmButtonText || intl.formatMessage(messages.confirmationConfirm)}
|
||||
</Button>
|
||||
</ActionRow>
|
||||
</ModalDialog.Footer>
|
||||
@@ -38,13 +41,22 @@ function DeleteConfirmation({
|
||||
);
|
||||
}
|
||||
|
||||
DeleteConfirmation.propTypes = {
|
||||
Confirmation.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
comfirmAction: PropTypes.func.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
closeButtonVaraint: PropTypes.string,
|
||||
confirmButtonVariant: PropTypes.string,
|
||||
confirmButtonText: PropTypes.string,
|
||||
};
|
||||
|
||||
export default injectIntl(DeleteConfirmation);
|
||||
Confirmation.defaultProps = {
|
||||
closeButtonVaraint: 'default',
|
||||
confirmButtonVariant: 'primary',
|
||||
confirmButtonText: '',
|
||||
};
|
||||
|
||||
export default injectIntl(Confirmation);
|
||||
@@ -1,5 +1,5 @@
|
||||
export { default as ActionsDropdown } from './ActionsDropdown';
|
||||
export { default as AlertBanner } from './AlertBanner';
|
||||
export { default as AuthorLabel } from './AuthorLabel';
|
||||
export { default as DeleteConfirmation } from './DeleteConfirmation';
|
||||
export { default as Confirmation } from './Confirmation';
|
||||
export { default as EndorsedAlertBanner } from './EndorsedAlertBanner';
|
||||
|
||||
@@ -7,14 +7,16 @@ ensureConfig([
|
||||
'LMS_BASE_URL',
|
||||
], 'Posts API service');
|
||||
|
||||
export const getCourseConfigApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`;
|
||||
const apiBaseUrl = getConfig().LMS_BASE_URL;
|
||||
|
||||
export const courseConfigApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`;
|
||||
|
||||
/**
|
||||
* Get discussions course config
|
||||
* @param {string} courseId
|
||||
*/
|
||||
export async function getDiscussionsConfig(courseId) {
|
||||
const url = `${getCourseConfigApiUrl()}${courseId}/`;
|
||||
const url = `${courseConfigApiUrl}${courseId}/`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url);
|
||||
return data;
|
||||
}
|
||||
@@ -24,7 +26,7 @@ export async function getDiscussionsConfig(courseId) {
|
||||
* @param {string} courseId
|
||||
*/
|
||||
export async function getDiscussionsSettings(courseId) {
|
||||
const url = `${getCourseConfigApiUrl()}${courseId}/settings`;
|
||||
const url = `${courseConfigApiUrl}${courseId}/settings`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -10,20 +10,26 @@ import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
import { breakpoints, useWindowSize } from '@edx/paragon';
|
||||
|
||||
import { Routes } from '../../data/constants';
|
||||
import { RequestStatus, Routes } from '../../data/constants';
|
||||
import { selectTopicsUnderCategory } from '../../data/selectors';
|
||||
import { fetchCourseBlocks } from '../../data/thunks';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { clearRedirect } from '../posts/data';
|
||||
import { selectTopics } from '../topics/data/selectors';
|
||||
import { threadsLoadingStatus } from '../posts/data/selectors';
|
||||
import { selectTopics, topicsLoadingStatus } from '../topics/data/selectors';
|
||||
import { fetchCourseTopics } from '../topics/data/thunks';
|
||||
import { discussionsPath } from '../utils';
|
||||
import { discussionsPath, inBlackoutDateRange } from '../utils';
|
||||
import {
|
||||
selectAreThreadsFiltered, selectLearnersTabEnabled,
|
||||
selectAreThreadsFiltered,
|
||||
selectBlackoutDate,
|
||||
selectIsCourseAdmin,
|
||||
selectIsCourseStaff,
|
||||
selectLearnersTabEnabled,
|
||||
selectModerationSettings,
|
||||
selectPostThreadCount,
|
||||
selectUserHasModerationPrivileges,
|
||||
selectUserIsGroupTa,
|
||||
selectUserIsStaff,
|
||||
} from './selectors';
|
||||
import { fetchCourseConfig } from './thunks';
|
||||
|
||||
@@ -43,14 +49,27 @@ export function useTotalTopicThreadCount() {
|
||||
export const useSidebarVisible = () => {
|
||||
const isFiltered = useSelector(selectAreThreadsFiltered);
|
||||
const totalThreads = useSelector(selectPostThreadCount);
|
||||
const isViewingTopics = useRouteMatch(Routes.TOPICS.PATH);
|
||||
const threadsCallStatus = useSelector(threadsLoadingStatus);
|
||||
const isViewingSpecificTopic = useRouteMatch(Routes.TOPICS.TOPIC);
|
||||
const isViewingTopics = useRouteMatch(Routes.TOPICS.ALL);
|
||||
const isViewingLearners = useRouteMatch(Routes.LEARNERS.PATH);
|
||||
const topicsLoading = useSelector(topicsLoadingStatus);
|
||||
|
||||
if (
|
||||
isViewingSpecificTopic
|
||||
&& isViewingSpecificTopic.isExact
|
||||
&& totalThreads > 0
|
||||
&& topicsLoading === RequestStatus.SUCCESSFUL
|
||||
&& threadsCallStatus === RequestStatus.SUCCESSFUL
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFiltered) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isViewingTopics || isViewingLearners) {
|
||||
if ((isViewingTopics && isViewingTopics.isExact) || isViewingLearners) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,7 +116,7 @@ export function useRedirectToThread(courseId, inContext) {
|
||||
|
||||
export function useIsOnDesktop() {
|
||||
const windowSize = useWindowSize();
|
||||
return windowSize.width >= breakpoints.large.minWidth;
|
||||
return windowSize.width >= breakpoints.medium.minWidth;
|
||||
}
|
||||
|
||||
export function useIsOnXLDesktop() {
|
||||
@@ -174,3 +193,16 @@ export const useCurrentDiscussionTopic = () => {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const useUserCanAddThreadInBlackoutDate = () => {
|
||||
const blackoutDateRange = useSelector(selectBlackoutDate);
|
||||
const isUserAdmin = useSelector(selectUserIsStaff);
|
||||
const userHasModerationPrivilages = useSelector(selectUserHasModerationPrivileges);
|
||||
const isUserGroupTA = useSelector(selectUserIsGroupTa);
|
||||
const isCourseAdmin = useSelector(selectIsCourseAdmin);
|
||||
const isCourseStaff = useSelector(selectIsCourseStaff);
|
||||
const isInBlackoutDateRange = inBlackoutDateRange(blackoutDateRange);
|
||||
|
||||
return (!(isInBlackoutDateRange)
|
||||
|| (isUserAdmin || userHasModerationPrivilages || isUserGroupTA || isCourseAdmin || isCourseStaff));
|
||||
};
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Factory } from 'rosie';
|
||||
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { useCurrentDiscussionTopic } from './hooks';
|
||||
import { courseConfigApiUrl } from './api';
|
||||
import { useCurrentDiscussionTopic, useUserCanAddThreadInBlackoutDate } from './hooks';
|
||||
import { fetchCourseConfig } from './thunks';
|
||||
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
let store;
|
||||
initializeMockApp();
|
||||
let axiosMock;
|
||||
|
||||
const generateApiResponse = (blackouts = [], isCourseAdmin = false) => ({
|
||||
blackouts,
|
||||
hasModerationPrivileges: false,
|
||||
isGroupTa: false,
|
||||
isCourseAdmin,
|
||||
isCourseStaff: false,
|
||||
isUserAdmin: false,
|
||||
});
|
||||
|
||||
describe('Hooks', () => {
|
||||
describe('useCurrentDiscussionTopic', () => {
|
||||
function ComponentWithHook() {
|
||||
@@ -39,6 +56,7 @@ describe('Hooks', () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
initializeMockApp();
|
||||
store = initializeStore({
|
||||
blocks: {
|
||||
blocks: {
|
||||
@@ -82,4 +100,75 @@ describe('Hooks', () => {
|
||||
expect(queryByText('null')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('useUserCanAddThreadInBlackoutDate', () => {
|
||||
function ComponentWithHook() {
|
||||
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
|
||||
return (
|
||||
<div>
|
||||
{String(userCanAddThreadInBlackoutDate)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderComponent() {
|
||||
return render(
|
||||
<IntlProvider locale="en">
|
||||
<AppProvider store={store}>
|
||||
<ComponentWithHook />
|
||||
</AppProvider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
}
|
||||
describe('User can add Thread in blackoutdates ', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
Factory.resetAll();
|
||||
store = initializeStore();
|
||||
});
|
||||
|
||||
test('when blackoutdates are not active and Role is Learner return true', async () => {
|
||||
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`)
|
||||
.reply(200, generateApiResponse([], false));
|
||||
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
|
||||
const { queryByText } = renderComponent();
|
||||
expect(queryByText('true')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('when blackoutdates are not active and Role is not Learner return true', async () => {
|
||||
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`)
|
||||
.reply(200, generateApiResponse([], true));
|
||||
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
|
||||
const { queryByText } = renderComponent();
|
||||
expect(queryByText('true')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('when blackoutdates are active and Role is Learner return false', async () => {
|
||||
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`)
|
||||
.reply(200, generateApiResponse([{
|
||||
start: '2022-11-25T00:00:00Z',
|
||||
end: '2050-11-25T23:59:00Z',
|
||||
}], false));
|
||||
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
|
||||
const { queryByText } = renderComponent();
|
||||
expect(queryByText('false')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('when blackoutdates are active and Role is not Learner return true', async () => {
|
||||
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`)
|
||||
.reply(200, generateApiResponse([
|
||||
{ start: '2022-11-25T00:00:00Z', end: '2050-11-25T23:59:00Z' }], true));
|
||||
const { queryByText } = renderComponent();
|
||||
expect(queryByText('true')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,6 +24,10 @@ export const selectBlackoutDate = state => state.config.blackouts;
|
||||
|
||||
export const selectGroupAtSubsection = state => state.config.groupAtSubsection;
|
||||
|
||||
export const selectIsCourseAdmin = state => state.config.isCourseAdmin;
|
||||
|
||||
export const selectIsCourseStaff = state => state.config.isCourseStaff;
|
||||
|
||||
export const selectModerationSettings = state => ({
|
||||
postCloseReasons: state.config.postCloseReasons,
|
||||
editReasons: state.config.editReasons,
|
||||
|
||||
@@ -14,6 +14,8 @@ const configSlice = createSlice({
|
||||
groupAtSubsection: false,
|
||||
hasModerationPrivileges: false,
|
||||
isGroupTa: false,
|
||||
isCourseAdmin: false,
|
||||
isCourseStaff: false,
|
||||
isUserAdmin: false,
|
||||
learnersTabEnabled: false,
|
||||
settings: {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../store';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { fetchConfigSuccess } from '../data/slices';
|
||||
import { getThreadsApiUrl } from '../posts/data/api';
|
||||
import { threadsApiUrl } from '../posts/data/api';
|
||||
import DiscussionSidebar from './DiscussionSidebar';
|
||||
|
||||
import '../posts/data/__factories__';
|
||||
@@ -21,7 +21,6 @@ import '../posts/data/__factories__';
|
||||
let store;
|
||||
let container;
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
let axiosMock;
|
||||
|
||||
function renderComponent(displaySidebar = true, location = `/${courseId}/`) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import messages from '../messages';
|
||||
import { getThreadsApiUrl } from '../posts/data/api';
|
||||
import { threadsApiUrl } from '../posts/data/api';
|
||||
import { fetchThreads } from '../posts/data/thunks';
|
||||
import EmptyPosts from './EmptyPosts';
|
||||
|
||||
@@ -20,7 +20,6 @@ import '../posts/data/__factories__';
|
||||
|
||||
let store;
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
|
||||
function renderComponent(location = `/${courseId}/`) {
|
||||
return render(
|
||||
|
||||
@@ -9,7 +9,7 @@ import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getApiBaseUrl } from '../../data/constants';
|
||||
import { API_BASE_URL } from '../../data/constants';
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import messages from '../messages';
|
||||
@@ -20,7 +20,7 @@ import '../topics/data/__factories__';
|
||||
|
||||
let store;
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
|
||||
|
||||
function renderComponent(location = `/${courseId}/topics/`) {
|
||||
return render(
|
||||
|
||||
@@ -14,17 +14,15 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { getCourseConfigApiUrl } from '../data/api';
|
||||
import { courseConfigApiUrl } from '../data/api';
|
||||
import { fetchCourseConfig } from '../data/thunks';
|
||||
import { getCoursesApiUrl } from './data/api';
|
||||
import { coursesApiUrl } from './data/api';
|
||||
import LearnerPostsView from './LearnerPostsView';
|
||||
|
||||
import './data/__factories__';
|
||||
|
||||
let store;
|
||||
let axiosMock;
|
||||
const coursesApiUrl = getCoursesApiUrl();
|
||||
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
const username = 'abc123';
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { getCourseConfigApiUrl } from '../data/api';
|
||||
import { courseConfigApiUrl } from '../data/api';
|
||||
import { fetchCourseConfig } from '../data/thunks';
|
||||
import { getCoursesApiUrl, getUserProfileApiUrl } from './data/api';
|
||||
import { coursesApiUrl, userProfileApiUrl } from './data/api';
|
||||
import { fetchLearners } from './data/thunks';
|
||||
import LearnersView from './LearnersView';
|
||||
|
||||
@@ -23,9 +23,6 @@ import './data/__factories__';
|
||||
|
||||
let store;
|
||||
let axiosMock;
|
||||
const coursesApiUrl = getCoursesApiUrl();
|
||||
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
const userProfileApiUrl = getUserProfileApiUrl();
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
|
||||
function renderComponent() {
|
||||
|
||||
@@ -8,8 +8,10 @@ ensureConfig([
|
||||
'LMS_BASE_URL',
|
||||
], 'Posts API service');
|
||||
|
||||
export const getCoursesApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`;
|
||||
export const getUserProfileApiUrl = () => `${getConfig().LMS_BASE_URL}/api/user/v1/accounts`;
|
||||
const apiBaseUrl = getConfig().LMS_BASE_URL;
|
||||
|
||||
export const coursesApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`;
|
||||
export const userProfileApiUrl = `${apiBaseUrl}/api/user/v1/accounts`;
|
||||
|
||||
/**
|
||||
* Fetches all the learners in the given course.
|
||||
@@ -18,7 +20,7 @@ export const getUserProfileApiUrl = () => `${getConfig().LMS_BASE_URL}/api/user/
|
||||
* @returns {Promise<{}>}
|
||||
*/
|
||||
export async function getLearners(courseId, params) {
|
||||
const url = `${getCoursesApiUrl()}${courseId}/activity_stats/`;
|
||||
const url = `${coursesApiUrl}${courseId}/activity_stats/`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url, { params });
|
||||
return data;
|
||||
}
|
||||
@@ -28,7 +30,7 @@ export async function getLearners(courseId, params) {
|
||||
* @param {string} usernames
|
||||
*/
|
||||
export async function getUserProfiles(usernames) {
|
||||
const url = `${getUserProfileApiUrl()}?username=${usernames.join()}`;
|
||||
const url = `${userProfileApiUrl}?username=${usernames.join()}`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url);
|
||||
return data;
|
||||
}
|
||||
@@ -65,7 +67,7 @@ export async function getUserPosts(courseId, {
|
||||
countFlagged,
|
||||
cohort,
|
||||
} = {}) {
|
||||
const learnerPostsApiUrl = `${getCoursesApiUrl()}${courseId}/learner/`;
|
||||
const learnerPostsApiUrl = `${coursesApiUrl}${courseId}/learner/`;
|
||||
|
||||
const params = snakeCaseObject({
|
||||
page,
|
||||
|
||||
@@ -4,6 +4,8 @@ import { isEmpty } from 'lodash';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
|
||||
import FilterBar from '../../../components/FilterBar';
|
||||
import { selectCourseCohorts } from '../../cohorts/data/selectors';
|
||||
import { fetchCourseCohorts } from '../../cohorts/data/thunks';
|
||||
@@ -39,12 +41,20 @@ function LearnerPostFilterBar() {
|
||||
|
||||
const handleFilterChange = (event) => {
|
||||
const { name, value } = event.currentTarget;
|
||||
const filterContentEventProperties = {
|
||||
statusFilter: postFilter.status,
|
||||
threadTypeFilter: postFilter.postType,
|
||||
sortFilter: postFilter.orderBy,
|
||||
cohortFilter: postFilter.cohort,
|
||||
triggeredBy: name,
|
||||
};
|
||||
if (name === 'postType') {
|
||||
if (postFilter.postType !== value) {
|
||||
dispatch(setPostFilter({
|
||||
...postFilter,
|
||||
postType: value,
|
||||
}));
|
||||
filterContentEventProperties.threadTypeFilter = value;
|
||||
}
|
||||
} else if (name === 'status') {
|
||||
if (postFilter.status !== value) {
|
||||
@@ -52,6 +62,7 @@ function LearnerPostFilterBar() {
|
||||
...postFilter,
|
||||
status: value,
|
||||
}));
|
||||
filterContentEventProperties.statusFilter = value;
|
||||
}
|
||||
} else if (name === 'orderBy') {
|
||||
if (postFilter.orderBy !== value) {
|
||||
@@ -59,6 +70,7 @@ function LearnerPostFilterBar() {
|
||||
...postFilter,
|
||||
orderBy: value,
|
||||
}));
|
||||
filterContentEventProperties.sortFilter = value;
|
||||
}
|
||||
} else if (name === 'cohort') {
|
||||
if (postFilter.cohort !== value) {
|
||||
@@ -66,8 +78,10 @@ function LearnerPostFilterBar() {
|
||||
...postFilter,
|
||||
cohort: value,
|
||||
}));
|
||||
filterContentEventProperties.cohortFilter = value;
|
||||
}
|
||||
}
|
||||
sendTrackEvent('edx.forum.filter.content', filterContentEventProperties);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Collapsible, Form, Icon } from '@edx/paragon';
|
||||
import { Check, Tune } from '@edx/paragon/icons';
|
||||
@@ -58,6 +59,12 @@ function LearnerFilterBar({
|
||||
|
||||
if (name === 'sort') {
|
||||
dispatch(setSortedBy(value));
|
||||
sendTrackEvent(
|
||||
'edx.forum.sort.user',
|
||||
{
|
||||
sort: value,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Delete',
|
||||
description: 'Action to delete a post or comment',
|
||||
},
|
||||
confirmationConfirm: {
|
||||
id: 'discussions.confirmation.button.confirm',
|
||||
defaultMessage: 'Confirm',
|
||||
description: 'Confirm button shown on confirmation dialog',
|
||||
},
|
||||
closeAction: {
|
||||
id: 'discussions.actions.close',
|
||||
defaultMessage: 'Close',
|
||||
@@ -71,16 +76,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Unmark as answered',
|
||||
description: 'Action to unmark a comment as answering a post',
|
||||
},
|
||||
deleteConfirmationCancel: {
|
||||
id: 'discussions.delete.confirmation.button.cancel',
|
||||
confirmationCancel: {
|
||||
id: 'discussions.modal.confirmation.button.cancel',
|
||||
defaultMessage: 'Cancel',
|
||||
description: 'Cancel button shown on delete confirmation dialog',
|
||||
},
|
||||
deleteConfirmationDelete: {
|
||||
id: 'discussions.delete.confirmation.button.delete',
|
||||
defaultMessage: 'Delete',
|
||||
description: 'Delete button shown on delete confirmation dialog',
|
||||
},
|
||||
emptyAllTopics: {
|
||||
id: 'discussions.empty.allTopics',
|
||||
defaultMessage:
|
||||
|
||||
@@ -13,8 +13,8 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getBlocksAPIResponse } from '../../../data/__factories__';
|
||||
import { getBlocksAPIURL } from '../../../data/api';
|
||||
import { getApiBaseUrl, Routes } from '../../../data/constants';
|
||||
import { blocksAPIURL } from '../../../data/api';
|
||||
import { API_BASE_URL, Routes } from '../../../data/constants';
|
||||
import { fetchCourseBlocks } from '../../../data/thunks';
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
@@ -25,7 +25,7 @@ import { BreadcrumbMenu } from '../index';
|
||||
import '../../topics/data/__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`;
|
||||
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`;
|
||||
let store;
|
||||
let axiosMock;
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('BreadcrumbMenu', () => {
|
||||
Factory.resetAll();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
blocksAPIResponse = getBlocksAPIResponse();
|
||||
axiosMock.onGet(getBlocksAPIURL())
|
||||
axiosMock.onGet(blocksAPIURL)
|
||||
.reply(200, blocksAPIResponse);
|
||||
await executeThunk(fetchCourseBlocks(courseId, 'test-user'), store.dispatch, store.getState);
|
||||
const data = [
|
||||
|
||||
@@ -12,7 +12,7 @@ import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getApiBaseUrl, Routes } from '../../../data/constants';
|
||||
import { API_BASE_URL, Routes } from '../../../data/constants';
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
import { fetchCourseTopics } from '../../topics/data/thunks';
|
||||
@@ -21,7 +21,7 @@ import { LegacyBreadcrumbMenu } from '../index';
|
||||
import '../../topics/data/__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
|
||||
let store;
|
||||
let axiosMock;
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ import { fetchThreads } from './data/thunks';
|
||||
import NoResults from './NoResults';
|
||||
import { PostLink } from './post';
|
||||
|
||||
function PostsList({ posts, topics, intl }) {
|
||||
function PostsList({
|
||||
posts, topics, intl, isTopicTab,
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
courseId,
|
||||
@@ -38,7 +40,7 @@ function PostsList({ posts, topics, intl }) {
|
||||
const userIsStaff = useSelector(selectUserIsStaff);
|
||||
const configStatus = useSelector(selectconfigLoadingStatus);
|
||||
|
||||
const loadThreads = (topicIds, pageNum = undefined) => {
|
||||
const loadThreads = (topicIds, pageNum = undefined, isFilterChanged = false) => {
|
||||
const params = {
|
||||
orderBy,
|
||||
filters,
|
||||
@@ -46,9 +48,10 @@ function PostsList({ posts, topics, intl }) {
|
||||
author: showOwnPosts ? authenticatedUser.username : null,
|
||||
countFlagged: (userHasModerationPrivileges || userIsStaff) || undefined,
|
||||
topicIds,
|
||||
isFilterChanged,
|
||||
};
|
||||
|
||||
if (showOwnPosts && filters.search === '') {
|
||||
if (showOwnPosts) {
|
||||
dispatch(fetchUserPosts(courseId, params));
|
||||
} else {
|
||||
dispatch(fetchThreads(courseId, params));
|
||||
@@ -59,7 +62,11 @@ function PostsList({ posts, topics, intl }) {
|
||||
if (topics !== undefined && configStatus === RequestStatus.SUCCESSFUL) {
|
||||
loadThreads(topics);
|
||||
}
|
||||
}, [courseId, orderBy, filters, page, JSON.stringify(topics), configStatus]);
|
||||
}, [courseId, filters, orderBy, page, JSON.stringify(topics), configStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTopicTab) { loadThreads(topics, 1, true); }
|
||||
}, [filters]);
|
||||
|
||||
const checkIsSelected = (id) => window.location.pathname.includes(id);
|
||||
const pinnedPosts = useMemo(() => filterPosts(posts, 'pinned'), [posts]);
|
||||
@@ -103,12 +110,14 @@ PostsList.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
})),
|
||||
topics: PropTypes.arrayOf(PropTypes.string),
|
||||
isTopicTab: PropTypes.bool,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
PostsList.defaultProps = {
|
||||
posts: [],
|
||||
topics: undefined,
|
||||
isTopicTab: false,
|
||||
};
|
||||
|
||||
export default injectIntl(PostsList);
|
||||
|
||||
@@ -21,7 +21,7 @@ function AllPostsList() {
|
||||
|
||||
function TopicPostsList({ topicId }) {
|
||||
const posts = useSelector(selectTopicThreads([topicId]));
|
||||
return <PostsList posts={posts} topics={[topicId]} />;
|
||||
return <PostsList posts={posts} topics={[topicId]} isTopicTab />;
|
||||
}
|
||||
|
||||
TopicPostsList.propTypes = {
|
||||
|
||||
@@ -18,16 +18,14 @@ import { initializeStore } from '../../store';
|
||||
import { getCohortsApiUrl } from '../cohorts/data/api';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { fetchConfigSuccess } from '../data/slices';
|
||||
import { getCoursesApiUrl } from '../learners/data/api';
|
||||
import { getThreadsApiUrl } from './data/api';
|
||||
import { coursesApiUrl } from '../learners/data/api';
|
||||
import { threadsApiUrl } from './data/api';
|
||||
import { PostsView } from './index';
|
||||
|
||||
import './data/__factories__';
|
||||
import '../cohorts/data/__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
const coursesApiUrl = getCoursesApiUrl();
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
let store;
|
||||
let axiosMock;
|
||||
const username = 'abc123';
|
||||
@@ -114,7 +112,6 @@ describe('PostsView', () => {
|
||||
config: { hasModerationPrivileges: true },
|
||||
...data,
|
||||
};
|
||||
// console.log(storeData);
|
||||
store = initializeStore(storeData);
|
||||
store.dispatch(fetchConfigSuccess({}));
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@ ensureConfig([
|
||||
'LMS_BASE_URL',
|
||||
], 'Posts API service');
|
||||
|
||||
export const getThreadsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/threads/`;
|
||||
export const getCoursesApiUrl = () => `${getConfig().LMS_BASE_URL}/api/discussion/v1/courses/`;
|
||||
const apiBaseUrl = getConfig().LMS_BASE_URL;
|
||||
|
||||
export const threadsApiUrl = `${apiBaseUrl}/api/discussion/v1/threads/`;
|
||||
export const coursesApiUrl = `${apiBaseUrl}/api/discussion/v1/courses/`;
|
||||
|
||||
/**
|
||||
* Fetches all the threads in the given course and topic.
|
||||
@@ -60,7 +62,7 @@ export async function getThreads(
|
||||
countFlagged,
|
||||
groupId: cohort,
|
||||
});
|
||||
const { data } = await getAuthenticatedHttpClient().get(getThreadsApiUrl(), { params });
|
||||
const { data } = await getAuthenticatedHttpClient().get(threadsApiUrl, { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -71,7 +73,7 @@ export async function getThreads(
|
||||
*/
|
||||
export async function getThread(threadId, courseId) {
|
||||
const params = { requested_fields: 'profile_image', course_id: courseId };
|
||||
const url = `${getThreadsApiUrl()}${threadId}/`;
|
||||
const url = `${threadsApiUrl}${threadId}/`;
|
||||
const { data } = await getAuthenticatedHttpClient().get(url, { params });
|
||||
return data;
|
||||
}
|
||||
@@ -115,7 +117,7 @@ export async function postThread(
|
||||
});
|
||||
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.post(getThreadsApiUrl(), postData);
|
||||
.post(threadsApiUrl, postData);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ export async function updateThread(threadId, {
|
||||
editReasonCode,
|
||||
closeReasonCode,
|
||||
} = {}) {
|
||||
const url = `${getThreadsApiUrl()}${threadId}/`;
|
||||
const url = `${threadsApiUrl}${threadId}/`;
|
||||
const patchData = snakeCaseObject({
|
||||
topicId,
|
||||
abuse_flagged: flagged,
|
||||
@@ -175,7 +177,7 @@ export async function updateThread(threadId, {
|
||||
* @param {string} threadId
|
||||
*/
|
||||
export async function deleteThread(threadId) {
|
||||
const url = `${getThreadsApiUrl()}${threadId}/`;
|
||||
const url = `${threadsApiUrl}${threadId}/`;
|
||||
await getAuthenticatedHttpClient()
|
||||
.delete(url);
|
||||
}
|
||||
@@ -189,7 +191,7 @@ export async function deleteThread(threadId) {
|
||||
* @returns {Promise<{ location: string }>}
|
||||
*/
|
||||
export async function uploadFile(blob, filename, courseId, threadKey) {
|
||||
const uploadUrl = `${getCoursesApiUrl()}${courseId}/upload`;
|
||||
const uploadUrl = `${coursesApiUrl}${courseId}/upload`;
|
||||
const formData = new FormData();
|
||||
formData.append('thread_key', threadKey);
|
||||
formData.append('uploaded_file', blob, filename);
|
||||
|
||||
@@ -3,10 +3,9 @@ import MockAdapter from 'axios-mock-adapter';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { initializeMockApp } from '@edx/frontend-platform/testing';
|
||||
|
||||
import { getCoursesApiUrl, uploadFile } from './api';
|
||||
import { coursesApiUrl, uploadFile } from './api';
|
||||
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
const coursesApiUrl = getCoursesApiUrl();
|
||||
|
||||
let axiosMock = null;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { initializeMockApp } from '@edx/frontend-platform/testing';
|
||||
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
import { getThreadsApiUrl } from './api';
|
||||
import { threadsApiUrl } from './api';
|
||||
import {
|
||||
createNewThread, fetchThread, fetchThreads, removeThread, updateExistingThread,
|
||||
} from './thunks';
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
import './__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
|
||||
let axiosMock;
|
||||
let store;
|
||||
|
||||
@@ -79,7 +79,13 @@ const threadsSlice = createSlice({
|
||||
}
|
||||
state.status = RequestStatus.SUCCESSFUL;
|
||||
state.threadsById = { ...state.threadsById, ...payload.threadsById };
|
||||
state.threadsInTopic = mergeThreadsInTopics(state.threadsInTopic, payload.threadsInTopic);
|
||||
// filter
|
||||
if (payload.isFilterChanged) {
|
||||
state.threadsInTopic = { ...payload.threadsInTopic };
|
||||
} else {
|
||||
state.threadsInTopic = mergeThreadsInTopics(state.threadsInTopic, payload.threadsInTopic);
|
||||
}
|
||||
|
||||
state.avatars = { ...state.avatars, ...payload.avatars };
|
||||
state.nextPage = (payload.page < payload.pagination.numPages) ? payload.page + 1 : null;
|
||||
state.totalPages = payload.pagination.numPages;
|
||||
|
||||
@@ -102,6 +102,7 @@ export function fetchThreads(courseId, {
|
||||
author = null,
|
||||
filters = {},
|
||||
page = 1,
|
||||
isFilterChanged,
|
||||
countFlagged,
|
||||
} = {}) {
|
||||
const options = {
|
||||
@@ -141,7 +142,7 @@ export function fetchThreads(courseId, {
|
||||
const data = await getThreads(courseId, options);
|
||||
const normalisedData = normaliseThreads(camelCaseObject(data), topicIds);
|
||||
dispatch(fetchThreadsSuccess({
|
||||
...normalisedData, page, author, textSearchRewrite: data.text_search_rewrite,
|
||||
...normalisedData, page, author, textSearchRewrite: data.text_search_rewrite, isFilterChanged,
|
||||
}));
|
||||
} catch (error) {
|
||||
if (getHttpErrorStatus(error) === 403) {
|
||||
|
||||
@@ -12,8 +12,9 @@ import { Close } from '@edx/paragon/icons';
|
||||
|
||||
import Search from '../../../components/Search';
|
||||
import { RequestStatus } from '../../../data/constants';
|
||||
import { selectBlackoutDate, selectconfigLoadingStatus } from '../../data/selectors';
|
||||
import { inBlackoutDateRange, postMessageToParent } from '../../utils';
|
||||
import { useUserCanAddThreadInBlackoutDate } from '../../data/hooks';
|
||||
import { selectconfigLoadingStatus } from '../../data/selectors';
|
||||
import { postMessageToParent } from '../../utils';
|
||||
import { showPostEditor } from '../data';
|
||||
import messages from './messages';
|
||||
|
||||
@@ -25,7 +26,7 @@ function PostActionsBar({
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
const loadingStatus = useSelector(selectconfigLoadingStatus);
|
||||
const blackoutDateRange = useSelector(selectBlackoutDate);
|
||||
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
|
||||
|
||||
const handleCloseInContext = () => {
|
||||
postMessageToParent('learning.events.sidebar.close');
|
||||
@@ -39,7 +40,8 @@ function PostActionsBar({
|
||||
{intl.formatMessage(messages.title)}
|
||||
</h4>
|
||||
)}
|
||||
{(!inBlackoutDateRange(blackoutDateRange) && loadingStatus === RequestStatus.SUCCESSFUL) && (
|
||||
{loadingStatus === RequestStatus.SUCCESSFUL && userCanAddThreadInBlackoutDate
|
||||
&& (
|
||||
<>
|
||||
{!inContext && <div className="border-right border-light-400 mx-3" />}
|
||||
<Button
|
||||
|
||||
@@ -138,9 +138,7 @@ function PostEditor({
|
||||
follow: isEmpty(post?.following) ? true : post?.following,
|
||||
anonymous: allowAnonymous ? false : undefined,
|
||||
anonymousToPeers: allowAnonymousToPeers ? false : undefined,
|
||||
editReasonCode: post?.lastEdit?.reasonCode || (
|
||||
userIsStaff && canDisplayEditReason ? 'violates-guidelines' : undefined
|
||||
),
|
||||
editReasonCode: post?.lastEdit?.reasonCode || (userIsStaff ? 'violates-guidelines' : ''),
|
||||
cohort: post?.cohort || 'default',
|
||||
};
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getApiBaseUrl, Routes } from '../../../data/constants';
|
||||
import { API_BASE_URL, Routes } from '../../../data/constants';
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
import { getCohortsApiUrl } from '../../cohorts/data/api';
|
||||
import { DiscussionContext } from '../../common/context';
|
||||
import { fetchCourseTopics } from '../../topics/data/thunks';
|
||||
import { getThreadsApiUrl } from '../data/api';
|
||||
import { threadsApiUrl } from '../data/api';
|
||||
import { fetchThread } from '../data/thunks';
|
||||
import { PostEditor } from '../index';
|
||||
|
||||
@@ -28,8 +28,7 @@ import '../../topics/data/__factories__';
|
||||
import '../data/__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
|
||||
let store;
|
||||
let axiosMock;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { capitalize, isEmpty, toString } from 'lodash';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Collapsible, Form, Icon, Spinner,
|
||||
@@ -84,6 +85,13 @@ function PostFilterBar({
|
||||
name,
|
||||
value,
|
||||
} = event.currentTarget;
|
||||
const filterContentEventProperties = {
|
||||
statusFilter: currentStatus,
|
||||
threadTypeFilter: currentType,
|
||||
sortFilter: currentSorting,
|
||||
cohortFilter: selectedCohort,
|
||||
triggeredBy: name,
|
||||
};
|
||||
if (name === 'type') {
|
||||
dispatch(setPostsTypeFilter(value));
|
||||
if (
|
||||
@@ -92,6 +100,7 @@ function PostFilterBar({
|
||||
// You can't filter discussions by unanswered
|
||||
dispatch(setStatusFilter(PostsStatusFilter.ALL));
|
||||
}
|
||||
filterContentEventProperties.threadTypeFilter = value;
|
||||
}
|
||||
if (name === 'status') {
|
||||
dispatch(setStatusFilter(value));
|
||||
@@ -103,13 +112,17 @@ function PostFilterBar({
|
||||
// You can't filter questions by not responded so switch type to discussion
|
||||
dispatch(setPostsTypeFilter(ThreadType.DISCUSSION));
|
||||
}
|
||||
filterContentEventProperties.statusFilter = value;
|
||||
}
|
||||
if (name === 'sort') {
|
||||
dispatch(setSortedBy(value));
|
||||
filterContentEventProperties.sortFilter = value;
|
||||
}
|
||||
if (name === 'cohort') {
|
||||
dispatch(setCohortFilter(value));
|
||||
filterContentEventProperties.cohortFilter = value;
|
||||
}
|
||||
sendTrackEvent('edx.forum.filter.content', filterContentEventProperties);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import React from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Hyperlink, useToggle } from '@edx/paragon';
|
||||
|
||||
import HTMLLoader from '../../../components/HTMLLoader';
|
||||
import { ContentActions } from '../../../data/constants';
|
||||
import { selectorForUnitSubsection, selectTopicContext } from '../../../data/selectors';
|
||||
import { AlertBanner, DeleteConfirmation } from '../../common';
|
||||
import { AlertBanner, Confirmation } from '../../common';
|
||||
import { DiscussionContext } from '../../common/context';
|
||||
import { selectModerationSettings } from '../../data/selectors';
|
||||
import { selectTopic } from '../../topics/data/selectors';
|
||||
import { removeThread, updateExistingThread } from '../data/thunks';
|
||||
@@ -35,10 +36,29 @@ function Post({
|
||||
const topicContext = useSelector(selectTopicContext(post.topicId));
|
||||
const { reasonCodesEnabled } = useSelector(selectModerationSettings);
|
||||
const [isDeleting, showDeleteConfirmation, hideDeleteConfirmation] = useToggle(false);
|
||||
const [isReporting, showReportConfirmation, hideReportConfirmation] = useToggle(false);
|
||||
const [isClosing, showClosePostModal, hideClosePostModal] = useToggle(false);
|
||||
|
||||
const postURL = new URL(`${getConfig().PUBLIC_PATH}${courseId}/posts/${post.id}`, window.location.origin);
|
||||
const handleAbusedFlag = () => {
|
||||
if (post.abuseFlagged) {
|
||||
dispatch(updateExistingThread(post.id, { flagged: !post.abuseFlagged }));
|
||||
} else {
|
||||
showReportConfirmation();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteConfirmation = () => {
|
||||
dispatch(removeThread(post.id));
|
||||
history.push('.');
|
||||
hideDeleteConfirmation();
|
||||
};
|
||||
|
||||
const handleReportConfirmation = () => {
|
||||
dispatch(updateExistingThread(post.id, { flagged: !post.abuseFlagged }));
|
||||
hideReportConfirmation();
|
||||
};
|
||||
|
||||
const { inContext } = useContext(DiscussionContext);
|
||||
const actionHandlers = {
|
||||
[ContentActions.EDIT_CONTENT]: () => history.push({
|
||||
...location,
|
||||
@@ -54,9 +74,9 @@ function Post({
|
||||
dispatch(updateExistingThread(post.id, { closed: true }));
|
||||
}
|
||||
},
|
||||
[ContentActions.COPY_LINK]: () => { navigator.clipboard.writeText(postURL.href); },
|
||||
[ContentActions.COPY_LINK]: () => { navigator.clipboard.writeText(`${window.location.origin}/${courseId}/posts/${post.id}`); },
|
||||
[ContentActions.PIN]: () => dispatch(updateExistingThread(post.id, { pinned: !post.pinned })),
|
||||
[ContentActions.REPORT]: () => dispatch(updateExistingThread(post.id, { flagged: !post.abuseFlagged })),
|
||||
[ContentActions.REPORT]: () => handleAbusedFlag(),
|
||||
};
|
||||
|
||||
const getTopicCategoryName = topicData => (
|
||||
@@ -65,30 +85,50 @@ function Post({
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column w-100 mw-100" data-testid={`post-${post.id}`}>
|
||||
<DeleteConfirmation
|
||||
<Confirmation
|
||||
isOpen={isDeleting}
|
||||
title={intl.formatMessage(messages.deletePostTitle)}
|
||||
description={intl.formatMessage(messages.deletePostDescription)}
|
||||
onClose={hideDeleteConfirmation}
|
||||
onDelete={() => {
|
||||
dispatch(removeThread(post.id));
|
||||
history.push('.');
|
||||
hideDeleteConfirmation();
|
||||
}}
|
||||
comfirmAction={handleDeleteConfirmation}
|
||||
closeButtonVaraint="tertiary"
|
||||
confirmButtonText={intl.formatMessage(messages.deleteConfirmationDelete)}
|
||||
/>
|
||||
{!post.abuseFlagged && (
|
||||
<Confirmation
|
||||
isOpen={isReporting}
|
||||
title={intl.formatMessage(messages.reportPostTitle)}
|
||||
description={intl.formatMessage(messages.reportPostDescription)}
|
||||
onClose={hideReportConfirmation}
|
||||
comfirmAction={handleReportConfirmation}
|
||||
confirmButtonVariant="danger"
|
||||
/>
|
||||
)}
|
||||
<AlertBanner content={post} />
|
||||
<PostHeader post={post} actionHandlers={actionHandlers} />
|
||||
<div className="d-flex mt-4 mb-2 text-break font-style-normal text-primary-500">
|
||||
<HTMLLoader htmlNode={post.renderedBody} id="post" />
|
||||
</div>
|
||||
{topicContext && topic && (
|
||||
<div className="border px-3 rounded mb-4 border-light-400 align-self-start py-2.5">
|
||||
<div className={classNames('border px-3 rounded mb-4 border-light-400 align-self-start py-2.5',
|
||||
{ 'w-100': inContext })}
|
||||
>
|
||||
<span className="text-gray-500">{intl.formatMessage(messages.relatedTo)}{' '}</span>
|
||||
<Hyperlink
|
||||
destination={topicContext.unitLink}
|
||||
target="_top"
|
||||
>
|
||||
{`${getTopicCategoryName(topic)} / ${topic.name}`}
|
||||
{inContext
|
||||
? (
|
||||
<>
|
||||
<span className="w-auto">{topicContext.chapterName}</span>
|
||||
<span className="mx-1">/</span>
|
||||
<span className="w-auto">{topicContext.verticalName}</span>
|
||||
<span className="mx-1">/</span>
|
||||
<span className="w-auto">{topicContext.unitName}</span>
|
||||
</>
|
||||
)
|
||||
: `${getTopicCategoryName(topic)} / ${topic.name}`}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -11,12 +11,11 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../../store';
|
||||
import { executeThunk } from '../../../test-utils';
|
||||
import { DiscussionContext } from '../../common/context';
|
||||
import { getCourseConfigApiUrl } from '../../data/api';
|
||||
import { courseConfigApiUrl } from '../../data/api';
|
||||
import { fetchCourseConfig } from '../../data/thunks';
|
||||
import PostLink from './PostLink';
|
||||
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
let store;
|
||||
let axiosMock;
|
||||
|
||||
|
||||
@@ -71,6 +71,21 @@ const messages = defineMessages({
|
||||
id: 'discussions.editor.delete.post.description',
|
||||
defaultMessage: 'Are you sure you want to permanently delete this post?',
|
||||
},
|
||||
deleteConfirmationDelete: {
|
||||
id: 'discussions.post.delete.confirmation.button.delete',
|
||||
defaultMessage: 'Delete',
|
||||
description: 'Delete button shown on delete confirmation dialog',
|
||||
},
|
||||
reportPostTitle: {
|
||||
id: 'discussions.editor.report.post.title',
|
||||
defaultMessage: 'Report inappropriate content?',
|
||||
description: 'Title of confirmation dialog shown when reporting a post',
|
||||
},
|
||||
reportPostDescription: {
|
||||
id: 'discussions.editor.report.post.description',
|
||||
defaultMessage: 'The discussion moderation team will review this content and take appropriate action.',
|
||||
description: 'Text displayed in confirmation dialog when deleting a post',
|
||||
},
|
||||
closePostModalTitle: {
|
||||
id: 'discussions.post.closePostModal.title',
|
||||
defaultMessage: 'Close post',
|
||||
|
||||
@@ -11,8 +11,8 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getBlocksAPIResponse } from '../../data/__factories__';
|
||||
import { getBlocksAPIURL } from '../../data/api';
|
||||
import { DiscussionProvider, getApiBaseUrl } from '../../data/constants';
|
||||
import { blocksAPIURL } from '../../data/api';
|
||||
import { API_BASE_URL, DiscussionProvider } from '../../data/constants';
|
||||
import { selectSequences } from '../../data/selectors';
|
||||
import { fetchCourseBlocks } from '../../data/thunks';
|
||||
import { initializeStore } from '../../store';
|
||||
@@ -26,8 +26,8 @@ import './data/__factories__';
|
||||
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
|
||||
const topicsApiUrl = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const topicsv2ApiUrl = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`;
|
||||
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const topicsv2ApiUrl = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`;
|
||||
let store;
|
||||
let axiosMock;
|
||||
let lastLocation;
|
||||
@@ -113,7 +113,7 @@ describe('TopicsView', () => {
|
||||
axiosMock
|
||||
.onGet(topicsv2ApiUrl)
|
||||
.reply(200, data);
|
||||
axiosMock.onGet(getBlocksAPIURL())
|
||||
axiosMock.onGet(blocksAPIURL)
|
||||
.reply(200, getBlocksAPIResponse(true));
|
||||
axiosMock.onAny().networkError();
|
||||
await executeThunk(fetchCourseBlocks(courseId, 'abc123'), store.dispatch, store.getState);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
import { getApiBaseUrl } from '../../../data/constants';
|
||||
import { API_BASE_URL } from '../../../data/constants';
|
||||
|
||||
export async function getCourseTopics(courseId, topicIds) {
|
||||
const url = `${getApiBaseUrl()}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const url = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
|
||||
const params = {};
|
||||
if (topicIds) {
|
||||
params.topic_id = topicIds.join(',');
|
||||
@@ -15,7 +15,7 @@ export async function getCourseTopics(courseId, topicIds) {
|
||||
}
|
||||
|
||||
export async function getCourseTopicsV2(courseId, topicIds) {
|
||||
const url = `${getApiBaseUrl()}/api/discussion/v2/course_topics/${courseId}`;
|
||||
const url = `${API_BASE_URL}/api/discussion/v2/course_topics/${courseId}`;
|
||||
const params = {};
|
||||
if (topicIds) {
|
||||
params.topic_id = topicIds.join(',');
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Are you sure you want to permanently delete this response?",
|
||||
"discussions.editor.delete.comment.title": "Delete comment",
|
||||
"discussions.editor.delete.comment.description": "Are you sure you want to permanently delete this comment?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Select reason for editing",
|
||||
"discussions.comment.comments.editedBy": "Edited by",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post closed by",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} reported",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Last active {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Actions menu",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Reopen",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Unmark as answered",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "All discussion activity for these topics will show up here.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Delete post",
|
||||
"discussions.editor.delete.post.description": "Are you sure you want to permanently delete this post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Are you sure you want to permanently delete this response?",
|
||||
"discussions.editor.delete.comment.title": "Delete comment",
|
||||
"discussions.editor.delete.comment.description": "Are you sure you want to permanently delete this comment?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Select reason for editing",
|
||||
"discussions.comment.comments.editedBy": "Edited by",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post closed by",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} reported",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Last active {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Actions menu",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Reopen",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Unmark as answered",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "All discussion activity for these topics will show up here.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Delete post",
|
||||
"discussions.editor.delete.post.description": "Are you sure you want to permanently delete this post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "¿Está seguro de que desea eliminar esta respuesta de forma permanente?",
|
||||
"discussions.editor.delete.comment.title": "Eliminar comentario",
|
||||
"discussions.editor.delete.comment.description": "¿Estás seguro de que quieres eliminar este comentario de forma permanente?",
|
||||
"discussions.delete.confirmation.button.delete": "Borrar",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Razón de la edición",
|
||||
"discussions.editor.posts.editReasonCode.error": "Seleccione el motivo de la edición",
|
||||
"discussions.comment.comments.editedBy": "Editado por",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Publicación cerrada por",
|
||||
"discussion.comment.repliesHeading": "{count} respuestas para la respuesta añadida",
|
||||
"discussion.comment.time": "hace {time}",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} informado",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} informado anteriormente",
|
||||
"discussions.learner.lastLogin": "Último activo {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Menú de acciones",
|
||||
"discussions.actions.copylink": "Copiar link",
|
||||
"discussions.actions.unpin": "Desmarcar",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Cerrar",
|
||||
"discussions.actions.reopen": "Reabrir",
|
||||
"discussions.actions.report": "Informar",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Invalidar",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Desmarcar como respondida",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancelar",
|
||||
"discussions.delete.confirmation.button.delete": "Borrar",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "Toda la actividad de debate de estos temas se mostrará aquí.",
|
||||
"discussions.empty.allPosts": "Toda la actividad de debate de su curso se mostrará aquí.",
|
||||
"discussions.empty.myPosts": "Las publicaciones con las que has interactuado se mostrarán aquí.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Eliminar mensaje",
|
||||
"discussions.editor.delete.post.description": "¿Seguro que quieres eliminar esta publicación de forma permanente?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Cerrar publicación",
|
||||
"discussions.post.closePostModal.text": "Escribe un motivo para cerrar esta publicación. Esto solo se mostrará a otros moderadores.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Motivo",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Are you sure you want to permanently delete this response?",
|
||||
"discussions.editor.delete.comment.title": "Delete comment",
|
||||
"discussions.editor.delete.comment.description": "Are you sure you want to permanently delete this comment?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Select reason for editing",
|
||||
"discussions.comment.comments.editedBy": "Édité par",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Message fermé par",
|
||||
"discussion.comment.repliesHeading": "{count} réponses pour la réponse ajoutée",
|
||||
"discussion.comment.time": "il y a {time}",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} signalé",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Last active {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Actions menu",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Reopen",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Unmark as answered",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "All discussion activity for these topics will show up here.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Delete post",
|
||||
"discussions.editor.delete.post.description": "Are you sure you want to permanently delete this post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Êtes-vous sûr de vouloir supprimer définitivement cette réponse ?",
|
||||
"discussions.editor.delete.comment.title": "Supprimer le commentaire",
|
||||
"discussions.editor.delete.comment.description": "Êtes-vous sûr de vouloir supprimer définitivement ce commentaire ?",
|
||||
"discussions.delete.confirmation.button.delete": "Supprimer",
|
||||
"discussions.editor.response.response.title": "Signaler un contenu inapproprié ?",
|
||||
"discussions.editor.response.description": "L'équipe de modération de la discussion examinera ce contenu et prendra les mesures appropriées.",
|
||||
"discussions.editor.report.comment.title": "Signaler un contenu inapproprié ?",
|
||||
"discussions.editor.report.comment.description": "L'équipe de modération de la discussion examinera ce contenu et prendra les mesures appropriées.",
|
||||
"discussions.editor.comments.editReasonCode": "Raison de la modification",
|
||||
"discussions.editor.posts.editReasonCode.error": "Sélectionnez la raison de la modification",
|
||||
"discussions.comment.comments.editedBy": "Édité par",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Message fermé par",
|
||||
"discussion.comment.repliesHeading": "{count} réponses pour la réponse ajoutée",
|
||||
"discussion.comment.time": "il y a {time}",
|
||||
"discussion.thread.notFound": "Sujet introuvable",
|
||||
"discussions.learner.reported": "{reported} signalé",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} signalé précédemment",
|
||||
"discussions.learner.lastLogin": "Dernier actif {lastActiveTime}",
|
||||
@@ -44,22 +50,22 @@
|
||||
"discussions.learner.mostActivity": "La plupart des activités",
|
||||
"discussions.learner.reportedActivity": "Activité signalée",
|
||||
"discussions.learner.recentActivity": "Activité récente",
|
||||
"discussions.learner.sortFilterStatus": "All learners sorted by {sort, select,\n flagged {reported activity}\n activity {most activity}\n other {{sort}}\n }",
|
||||
"discussions.learner.sortFilterStatus": "Tous les apprenants triés pas {sort, select,\n flagged {reported activity}\n activity {most activity}\n other {{sort}}\n }",
|
||||
"discussion.learner.allActivity": "Toutes les activités",
|
||||
"discussion.learner.posts": "Posts",
|
||||
"discussions.actions.button.alt": "Menu Actions",
|
||||
"discussions.actions.copylink": "Copier le lien",
|
||||
"discussions.actions.unpin": "Détacher",
|
||||
"discussions.confirmation.button.confirm": "Confirmer",
|
||||
"discussions.actions.close": "Fermer",
|
||||
"discussions.actions.reopen": "Rouvrir",
|
||||
"discussions.actions.report": "Signaler",
|
||||
"discussions.actions.unreport": "Ne pas signaler",
|
||||
"discussions.actions.endorse": "Approuver",
|
||||
"discussions.actions.unendorse": "Ne plus approuver",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.markAnswered": "Marquer comme répondu",
|
||||
"discussions.actions.unMarkAnswered": "Décocher comme répondu",
|
||||
"discussions.delete.confirmation.button.cancel": "Annuler",
|
||||
"discussions.delete.confirmation.button.delete": "Supprimer",
|
||||
"discussions.modal.confirmation.button.cancel": "Annuler",
|
||||
"discussions.empty.allTopics": "Toutes les activités de discussion pour ces sujets apparaîtront ici.",
|
||||
"discussions.empty.allPosts": "Toutes les activités de discussion pour votre cours s'afficheront ici.",
|
||||
"discussions.empty.myPosts": "Les publications avec lesquelles vous avez interagi s'afficheront ici.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Relative à",
|
||||
"discussions.editor.delete.post.title": "Supprimer le message",
|
||||
"discussions.editor.delete.post.description": "Êtes-vous sûr de vouloir supprimer définitivement ce message ?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Supprimer",
|
||||
"discussions.editor.report.post.title": "Signaler un contenu inapproprié ?",
|
||||
"discussions.editor.report.post.description": "L'équipe de modération de la discussion examinera ce contenu et prendra les mesures appropriées.",
|
||||
"discussions.post.closePostModal.title": "Fermer le message",
|
||||
"discussions.post.closePostModal.text": "Entrez une raison pour fermer ce message. Cela ne sera affiché qu'aux autres modérateurs.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Raison",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Are you sure you want to permanently delete this response?",
|
||||
"discussions.editor.delete.comment.title": "Delete comment",
|
||||
"discussions.editor.delete.comment.description": "Are you sure you want to permanently delete this comment?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Select reason for editing",
|
||||
"discussions.comment.comments.editedBy": "Edited by",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post closed by",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} reported",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Last active {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Actions menu",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Reopen",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Unmark as answered",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "All discussion activity for these topics will show up here.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Delete post",
|
||||
"discussions.editor.delete.post.description": "Are you sure you want to permanently delete this post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Sei sicuro di voler eliminare definitivamente questa risposta?",
|
||||
"discussions.editor.delete.comment.title": "Elimina commento",
|
||||
"discussions.editor.delete.comment.description": "Sei sicuro di voler eliminare definitivamente questo commento?",
|
||||
"discussions.delete.confirmation.button.delete": "Cancella",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Motivo della modifica",
|
||||
"discussions.editor.posts.editReasonCode.error": "Seleziona il motivo per la modifica",
|
||||
"discussions.comment.comments.editedBy": "A cura di",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post chiuso da",
|
||||
"discussion.comment.repliesHeading": "{count} risposte per la risposta aggiunta",
|
||||
"discussion.comment.time": "{time} fa",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} segnalato",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} segnalato in precedenza",
|
||||
"discussions.learner.lastLogin": "Ultimo attivo {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Menù Azioni",
|
||||
"discussions.actions.copylink": "Copia link",
|
||||
"discussions.actions.unpin": "Sblocca ",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Chiudi",
|
||||
"discussions.actions.reopen": "Riaprire",
|
||||
"discussions.actions.report": "Segnala",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Annulla promozione ",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Deseleziona come risposta",
|
||||
"discussions.delete.confirmation.button.cancel": "Annulla",
|
||||
"discussions.delete.confirmation.button.delete": "Cancella",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "Tutte le attività di discussione per questi argomenti verranno visualizzate qui.",
|
||||
"discussions.empty.allPosts": "Tutte le attività di discussione per il tuo corso verranno visualizzate qui.",
|
||||
"discussions.empty.myPosts": "I post con cui hai interagito verranno visualizzati qui.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Elimina messaggio",
|
||||
"discussions.editor.delete.post.description": "Sei sicuro di voler eliminare definitivamente questo post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Chiudi messaggio",
|
||||
"discussions.post.closePostModal.text": "Inserisci un motivo per chiudere questo post. Questo verrà mostrato solo agli altri moderatori.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Motivo ",
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Czy na pewno chcesz trwale usunąć tę odpowiedź?",
|
||||
"discussions.editor.delete.comment.title": "Usuń komentarz",
|
||||
"discussions.editor.delete.comment.description": "Czy na pewno chcesz trwale usunąć ten komentarz?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Wybierz powód edycji",
|
||||
"discussions.comment.comments.editedBy": "Edytowany przez",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post zamknięty przez",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} zgłoszone",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Ostatnia aktywność {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Menu czynności",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Otwórz ponownie",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Nie oznaczaj jako odpowiedziane",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "Wszystkie dyskusje dotyczące tych tematów pojawią się tutaj.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Usuń post",
|
||||
"discussions.editor.delete.post.description": "Czy na pewno chcesz trwale usunąć ten wpis?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
"discussions.comments.comment.addResponse": "Bir cevap ekle",
|
||||
"discussions.comments.comment.addComment": "Bir yorum ekle",
|
||||
"discussions.comments.comment.abuseFlaggedMessage": "Personelin incelemesi için bildirilen içerik",
|
||||
"discussions.actions.back.alt": "Back to list",
|
||||
"discussions.actions.back.alt": "Listeye dön",
|
||||
"discussions.comments.comment.responseCount": "{num, plural,\n =0 {No responses}\n one {Showing # response}\n other {Showing # responses}\n }",
|
||||
"discussions.comments.comment.endorsedResponseCount": "{num, plural,\n =0 {No endorsed responses}\n one {Showing # endorsed response}\n other {Showing # endorsed responses}\n }",
|
||||
"discussions.comments.comment.loadMoreComments": "Daha fazla yorum yükle",
|
||||
"discussions.comments.comment.loadMoreResponses": "Daha fazla yanıt yükle",
|
||||
"discussions.comments.comment.visibility": "This post is visible to {group, select,\n null {Everyone}\n other {{group}}\n }.",
|
||||
"discussions.comments.comment.postedTime": "{postType, select,\n discussion {Discussion}\n question {Question}\n other {{postType}}\n } posted {relativeTime} by",
|
||||
"discussions.comments.comment.commentTime": "Posted {relativeTime}",
|
||||
"discussions.comments.comment.commentTime": "{relativeTime} önce gönderildi",
|
||||
"discussions.comments.comment.answer": "Cevap",
|
||||
"discussions.comments.comment.answeredlabel": "Marked as answered by",
|
||||
"discussions.comments.comment.endorsed": "Endorsed",
|
||||
"discussions.comments.comment.endorsedlabel": "Endorsed by",
|
||||
"discussions.comments.comment.endorsed": "Doğrulandı",
|
||||
"discussions.comments.comment.endorsedlabel": "Doğrulayan",
|
||||
"discussions.actions.label": "Eylemler menüsü",
|
||||
"discussions.actions.edit": "Düzenle",
|
||||
"discussions.actions.pin": "İşaretle",
|
||||
@@ -28,13 +28,19 @@
|
||||
"discussions.editor.delete.response.description": "Bu yanıtı kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"discussions.editor.delete.comment.title": "Yorumu sil",
|
||||
"discussions.editor.delete.comment.description": "Bu yorumu kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"discussions.delete.confirmation.button.delete": "Sil",
|
||||
"discussions.editor.response.response.title": "Uygunsuz içerik mi raporlayacaksınız?",
|
||||
"discussions.editor.response.description": "Tartışma yöneticileri bu içeriği inceleyecek ve uygun işlemi yapacaktır.",
|
||||
"discussions.editor.report.comment.title": "Uygunsuz içerik mi raporlayacaksınız?",
|
||||
"discussions.editor.report.comment.description": "Tartışma yöneticileri bu içeriği inceleyecek ve uygun işlemi yapacaktır.",
|
||||
"discussions.editor.comments.editReasonCode": "Düzenleme nedeni",
|
||||
"discussions.editor.posts.editReasonCode.error": "Düzenleme nedenini seçin",
|
||||
"discussions.comment.comments.editedBy": "Düzenleyen",
|
||||
"discussions.comment.comments.reason": "Gerekçe",
|
||||
"discussions.post.closedBy": "Post closed by",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussions.post.closedBy": "Gönderiyi kapatan ",
|
||||
"discussion.comment.repliesHeading": "Eklenen yanıt için {count} yanıt",
|
||||
"discussion.comment.time": "{time} önce",
|
||||
"discussion.thread.notFound": "Tartışma zinciri bulunamadı",
|
||||
"discussions.learner.reported": "{reported} rapor edildi",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} daha önce rapor edildi",
|
||||
"discussions.learner.lastLogin": "Son etkinlik {lastActiveTime}",
|
||||
@@ -43,23 +49,23 @@
|
||||
"discussions.learner.activityForLearner": "{username} için etkinlik",
|
||||
"discussions.learner.mostActivity": "En çok etkinlik",
|
||||
"discussions.learner.reportedActivity": "Rapor edilen etkinlik",
|
||||
"discussions.learner.recentActivity": "Recent activity",
|
||||
"discussions.learner.recentActivity": "Son etkinlik",
|
||||
"discussions.learner.sortFilterStatus": "All learners sorted by {sort, select,\n flagged {reported activity}\n activity {most activity}\n other {{sort}}\n }",
|
||||
"discussion.learner.allActivity": "All activity",
|
||||
"discussion.learner.allActivity": "Tüm etkinlikler",
|
||||
"discussion.learner.posts": "Gönderiler",
|
||||
"discussions.actions.button.alt": "Eylemler menüsü",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.copylink": "Bağlantıyı kopyala",
|
||||
"discussions.actions.unpin": "İşareti kaldır",
|
||||
"discussions.confirmation.button.confirm": "Onayla",
|
||||
"discussions.actions.close": "Kapat",
|
||||
"discussions.actions.reopen": "Yeniden aç",
|
||||
"discussions.actions.report": "Raporla",
|
||||
"discussions.actions.unreport": "Bildirme",
|
||||
"discussions.actions.endorse": "Destekle",
|
||||
"discussions.actions.unendorse": "Destekleme",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.markAnswered": "Cevaplandı olarak işaretle",
|
||||
"discussions.actions.unMarkAnswered": "Cevaplandı olarak işaretini kaldır",
|
||||
"discussions.delete.confirmation.button.cancel": "İptal",
|
||||
"discussions.delete.confirmation.button.delete": "Sil",
|
||||
"discussions.modal.confirmation.button.cancel": "İptal",
|
||||
"discussions.empty.allTopics": "Bu konularla ilgili tüm tartışma etkinlikleri burada gösterilecektir.",
|
||||
"discussions.empty.allPosts": "Dersiniz için tüm tartışma etkinlikleri burada gösterilecektir.",
|
||||
"discussions.empty.myPosts": "Etkileşimde bulunduğunuz gönderiler burada gösterilecektir.",
|
||||
@@ -68,22 +74,22 @@
|
||||
"discussions.empty.noPostSelected": "Gönderi seçilmedi",
|
||||
"discussions.empty.noTopicSelected": "Konu seçilmedi",
|
||||
"discussions.sidebar.noResultsFound": "Sonuç bulunamadı",
|
||||
"discussions.sidebar.differentKeywords": "Try searching different keywords",
|
||||
"discussions.sidebar.differentKeywords": "Farklı anahtar kelimelerle aramayı dene",
|
||||
"discussions.sidebar.removeKeywords": "Farklı anahtar kelimeler aramayı veya bazı filtreleri kaldırmayı deneyin",
|
||||
"discussions.sidebar.removeKeywordsOnly": "Try searching different keywords",
|
||||
"discussions.sidebar.removeKeywordsOnly": "Farklı anahtar kelimelerle aramayı dene",
|
||||
"discussions.sidebar.removeFilters": "Bazı filtreleri kaldırmayı deneyin",
|
||||
"discussions.empty.iconAlt": "Boş",
|
||||
"discussions.authors.label.staff": "Personel",
|
||||
"discussions.authors.label.ta": "TA",
|
||||
"discussions.learner.loadMostPosts": "Daha fazla ileti yükle",
|
||||
"discussions.post.anonymous.author": "anonim",
|
||||
"discussion.banner.welcomeMessage": "🎉 Welcome to the new and improved discussions experience!",
|
||||
"discussion.banner.welcomeMessage": "🎉 Yeni ve geliştirilmiş tartışma deneyimine hoş geldiniz!",
|
||||
"discussion.banner.learnMore": "Daha fazlasını öğren",
|
||||
"discussion.banner.shareFeedback": "Share feedback",
|
||||
"discussion.banner.shareFeedback": "Geri bildirim paylaş",
|
||||
"discussion.blackoutBanner.information": "Blackout dates are currently active. Posting in discussions is unavailable at this time.",
|
||||
"discussions.editor.image.warning.message": "Images having width or height greater than 999px will not be visible when the post, response or comment is viewed using in-line course discussions",
|
||||
"discussions.editor.image.warning.title": "Warning!",
|
||||
"discussions.editor.image.warning.dismiss": "Ok",
|
||||
"discussions.editor.image.warning.title": "Uyarı!",
|
||||
"discussions.editor.image.warning.dismiss": "Tamam",
|
||||
"discussions.navigation.breadcrumbMenu.allTopics": "Konular",
|
||||
"discussions.navigation.breadcrumbMenu.showAll": "Tümünü göster",
|
||||
"discussions.navigation.navigationBar.allPosts": "Tüm iletiler",
|
||||
@@ -96,7 +102,7 @@
|
||||
"discussions.actionBar.searchInfo": "\"{text}\" için {count} sonuç gösteriliyor",
|
||||
"discussions.actionBar.searchRewriteInfo": "No results found for \"{searchString}\". Showing {count} results for \"{textSearchRewrite}\".",
|
||||
"discussions.actionBar.searchInfoSearching": "Aranıyor...",
|
||||
"discussions.actionBar.clearSearch": "Clear results",
|
||||
"discussions.actionBar.clearSearch": "Sonuçları temizle",
|
||||
"discussion.posts.actionBar.add": "Bir ileti ekle",
|
||||
"discussion.posts.actionBar.close": "Kapat",
|
||||
"discussions.post.editor.type": "Gönderi türü",
|
||||
@@ -109,13 +115,13 @@
|
||||
"discussions.post.editor.discussionType": "Forum",
|
||||
"discussions.post.editor.discussionDescription": "Fikirleri paylaşın ve sohbetler başlatın",
|
||||
"discussions.post.editor.topicArea": "Başlık alanı",
|
||||
"discussions.post.editor.topicAreaDescription": "Add your post to a relevant topic to help others find it.",
|
||||
"discussions.post.editor.topicAreaDescription": "Başkalarının bulmasına yardımcı olmak için gönderinizi ilgili bir konuya ekleyin.",
|
||||
"discussions.post.editor.cohortVisibility": "Kohort görünürlüğü",
|
||||
"discussions.post.editor.cohortVisibilityAllLearners": "Tüm öğrenciler",
|
||||
"discussions.post.editor.title": "Post title",
|
||||
"discussions.post.editor.title": "İleti başlığı",
|
||||
"discussions.post.editor.titleDescription": "Katılıma teşvik etmek için, açık ve tanıtıcı bir başlık ekleyin.",
|
||||
"discussions.post.editor.title.error": "Post title cannot be empty.",
|
||||
"discussions.post.editor.content.error": "Post content cannot be empty.",
|
||||
"discussions.post.editor.title.error": "Gönderi başlığı boş olamaz.",
|
||||
"discussions.post.editor.content.error": "Gönderi içeriği boş olamaz.",
|
||||
"discussions.post.editor.questionText": "Sorunuz veya fikriniz (gerekli)",
|
||||
"discussions.post.editor.preview": "Önizleme",
|
||||
"discussions.post.editor.followPost": "Bu iletiyi takip edin",
|
||||
@@ -123,8 +129,8 @@
|
||||
"discussions.post.editor.anonymousToPeersPost": "Akranlarına anonim olarak gönder",
|
||||
"discussions.editor.posts.editReasonCode": "Düzenleme nedeni",
|
||||
"discussions.editor.posts.showPreview.button": "Önizlemeyi Göster",
|
||||
"discussions.topic.noName.label": "Unnamed category",
|
||||
"discussions.subtopic.noName.label": "Unnamed subcategory",
|
||||
"discussions.topic.noName.label": "İsimsiz kategori",
|
||||
"discussions.subtopic.noName.label": "İsimsiz alt kategori",
|
||||
"discussions.posts.filter.showALl": "Tümünü göster",
|
||||
"discussions.posts.filter.discussions": "Forumlar",
|
||||
"discussions.posts.filter.questions": "Sorular",
|
||||
@@ -134,7 +140,7 @@
|
||||
"discussions.posts.status.filter.following": "Takip ediliyor",
|
||||
"discussions.posts.status.filter.reported": "Rapor edildi",
|
||||
"discussions.posts.status.filter.unanswered": "Cevaplanmamış",
|
||||
"discussions.posts.status.filter.unresponded": "Not responded",
|
||||
"discussions.posts.status.filter.unresponded": "Yanıtlanmamış",
|
||||
"discussions.posts.filter.myPosts": "Gönderilerim",
|
||||
"discussions.posts.filter.myDiscussions": "Tartışmalarım",
|
||||
"discussions.posts.filter.myQuestions": "Sorularım",
|
||||
@@ -145,19 +151,22 @@
|
||||
"discussions.posts.sort-filter.sortFilterStatus": "{own, select,\n false {All}\n true {Own}\n other {{own}}\n } {status, select,\n statusAll {}\n statusUnread {unread}\n statusFollowing {followed}\n statusReported {reported}\n statusUnanswered {unanswered}\n statusUnresponded {unresponded}\n other {{status}}\n } {type, select,\n discussion {discussions}\n question {questions}\n all {posts}\n other {{type}}\n } {cohortType, select,\n all {}\n group {in {cohort}}\n other {{cohortType}}\n } sorted by {sort, select,\n lastActivityAt {recent activity}\n commentCount {most activity}\n voteCount {most likes}\n other {{sort}}\n }",
|
||||
"discussions.post.author.anonymous": "anonim",
|
||||
"discussions.post.lastResponse": "Son yanıt {time}",
|
||||
"discussions.post.postedOn": "Posted {time} by {author} {authorLabel}",
|
||||
"discussions.post.postedOn": "{author} {authorLabel} tarafından {time} önce gönderildi",
|
||||
"discussions.post.contentReported": "Rapor edildi",
|
||||
"discussions.post.following": "Takip ediliyor",
|
||||
"discussions.post.follow": "Takip et",
|
||||
"discussions.post.answered": "Yanıtlandı",
|
||||
"discussions.post.unFollow": "Takibi bırak",
|
||||
"discussions.post.like": "Beğen",
|
||||
"discussions.post.removeLike": "Unlike",
|
||||
"discussions.post.removeLike": "Beğenmeme",
|
||||
"discussions.post.viewActivity": "Etkinliği görüntüle",
|
||||
"discussions.post.closed": "Yanıtlar ve yorumlar için gönderi kapatıldı",
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.post.relatedTo": "Bunun ile ilgili",
|
||||
"discussions.editor.delete.post.title": "Gönderiyi sil",
|
||||
"discussions.editor.delete.post.description": "Bu gönderiyi kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Sil",
|
||||
"discussions.editor.report.post.title": "Uygunsuz içerik mi raporlayacaksınız?",
|
||||
"discussions.editor.report.post.description": "Tartışma yöneticileri bu içeriği inceleyecek ve uygun işlemi yapacaktır.",
|
||||
"discussions.post.closePostModal.title": "Gönderiyi kapat",
|
||||
"discussions.post.closePostModal.text": "Bu gönderiyi kapatmak için bir neden girin. Bu sadece diğer moderatörlere gösterilecektir.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Gerekçe",
|
||||
@@ -169,14 +178,14 @@
|
||||
"discussions.post.postWithoutPreview": "Önizleme yok",
|
||||
"discussions.topics.discussions": "{count, plural,\n =0 {Discussion}\n one {# Discussion}\n other {# Discussions}\n }",
|
||||
"discussions.topics.questions": "{count, plural,\n =0 {Question}\n one {# Question}\n other {# Questions}\n }",
|
||||
"discussions.topics.reported": "{reported} reported",
|
||||
"discussions.topics.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.topics.reported": "{reported} rapor edildi",
|
||||
"discussions.topics.previouslyReported": "{previouslyReported} ileti rapor edildi",
|
||||
"discussions.topics.sort.message": "{sortBy} ölçütüne göre sıralandı",
|
||||
"discussions.topics.sort.lastActivity": "Son etkinlik",
|
||||
"discussions.topics.sort.commentCount": "En çok etkinlik",
|
||||
"discussions.topics.sort.courseStructure": "Ders Yapısı",
|
||||
"discussions.topics.find.label": "Search topics",
|
||||
"discussions.topics.find.label": "Konuları ara",
|
||||
"discussions.topics.archived.label": "Arşivlenmiş",
|
||||
"discussions.topics.unnamed.label": "Unnamed category",
|
||||
"discussions.subtopics.unnamed.label": "Unnamed subcategory"
|
||||
"discussions.topics.unnamed.label": "İsimsiz kategori",
|
||||
"discussions.subtopics.unnamed.label": "İsimsiz alt kategori"
|
||||
}
|
||||
@@ -28,6 +28,11 @@
|
||||
"discussions.editor.delete.response.description": "Are you sure you want to permanently delete this response?",
|
||||
"discussions.editor.delete.comment.title": "Delete comment",
|
||||
"discussions.editor.delete.comment.description": "Are you sure you want to permanently delete this comment?",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.response.response.title": "Report inappropriate content?",
|
||||
"discussions.editor.response.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.report.comment.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.comment.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.editor.comments.editReasonCode": "Reason for editing",
|
||||
"discussions.editor.posts.editReasonCode.error": "Select reason for editing",
|
||||
"discussions.comment.comments.editedBy": "Edited by",
|
||||
@@ -35,6 +40,7 @@
|
||||
"discussions.post.closedBy": "Post closed by",
|
||||
"discussion.comment.repliesHeading": "{count} replies for the response added",
|
||||
"discussion.comment.time": "{time} ago",
|
||||
"discussion.thread.notFound": "Thread not found",
|
||||
"discussions.learner.reported": "{reported} reported",
|
||||
"discussions.learner.previouslyReported": "{previouslyReported} previously reported",
|
||||
"discussions.learner.lastLogin": "Last active {lastActiveTime}",
|
||||
@@ -50,6 +56,7 @@
|
||||
"discussions.actions.button.alt": "Actions menu",
|
||||
"discussions.actions.copylink": "Copy link",
|
||||
"discussions.actions.unpin": "Unpin",
|
||||
"discussions.confirmation.button.confirm": "Confirm",
|
||||
"discussions.actions.close": "Close",
|
||||
"discussions.actions.reopen": "Reopen",
|
||||
"discussions.actions.report": "Report",
|
||||
@@ -58,8 +65,7 @@
|
||||
"discussions.actions.unendorse": "Unendorse",
|
||||
"discussions.actions.markAnswered": "Mark as answered",
|
||||
"discussions.actions.unMarkAnswered": "Unmark as answered",
|
||||
"discussions.delete.confirmation.button.cancel": "Cancel",
|
||||
"discussions.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.modal.confirmation.button.cancel": "Cancel",
|
||||
"discussions.empty.allTopics": "All discussion activity for these topics will show up here.",
|
||||
"discussions.empty.allPosts": "All discussion activity for your course will show up here.",
|
||||
"discussions.empty.myPosts": "Posts you've interacted with will show up here.",
|
||||
@@ -158,6 +164,9 @@
|
||||
"discussions.post.relatedTo": "Related to",
|
||||
"discussions.editor.delete.post.title": "Delete post",
|
||||
"discussions.editor.delete.post.description": "Are you sure you want to permanently delete this post?",
|
||||
"discussions.post.delete.confirmation.button.delete": "Delete",
|
||||
"discussions.editor.report.post.title": "Report inappropriate content?",
|
||||
"discussions.editor.report.post.description": "The discussion moderation team will review this content and take appropriate action.",
|
||||
"discussions.post.closePostModal.title": "Close post",
|
||||
"discussions.post.closePostModal.text": "Enter a reason for closing this post. This will only be displayed to other moderators.",
|
||||
"discussions.post.closePostModal.reasonCodeInput": "Reason",
|
||||
|
||||
@@ -118,7 +118,7 @@ $fa-font-path: "~font-awesome/fonts";
|
||||
|
||||
header {
|
||||
.user-dropdown {
|
||||
z-index: 2005;
|
||||
z-index: 1;
|
||||
}
|
||||
.logo {
|
||||
margin-right: 1rem;
|
||||
@@ -227,7 +227,7 @@ header {
|
||||
|
||||
.header-action-bar {
|
||||
background-color: #fff;
|
||||
z-index: 2002;
|
||||
z-index: 1;
|
||||
box-shadow: 0px 2px 4px rgb(0 0 0 / 15%), 0px 2px 8px rgb(0 0 0 / 15%);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -237,16 +237,24 @@ header {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.actions-dropdown {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.discussion-topic-group:last-of-type .divider{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.zindex-5000 {
|
||||
z-index: 5000;
|
||||
z-index: 5000;
|
||||
}
|
||||
|
||||
#paragon-portal-root .pgn__modal-layer {
|
||||
z-index: 1500 !important;
|
||||
z-index: 5000 !important;
|
||||
}
|
||||
|
||||
#iconbutton-tooltip-top {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@@ -254,12 +262,3 @@ header {
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.post-preview,
|
||||
.discussion-comments {
|
||||
blockquote {
|
||||
border-left: 2px solid #ccc;
|
||||
margin-left: 1.5rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user