Compare commits

...
953 Commits
Author SHA1 Message Date
Kiwi 519464ce57 Merge pull request #1226 from coralproject/handle-empty-queue
Fix error when queue is empty
2017-12-19 20:58:34 +01:00
Chi Vinh Le f27de815e6 Minor syntax issue 2017-12-19 20:48:59 +01:00
Chi Vinh Le e8553c5035 Revert debug code :-D 2017-12-19 20:46:59 +01:00
Chi Vinh Le 349341400d Fix error when queue is empty 2017-12-19 20:39:41 +01:00
Kim Gardner 7b92e58ff3 Merge pull request #1225 from coralproject/portal-dialog
Use Portal to put dialogs at the end of the document
2017-12-19 13:48:30 -05:00
Chi Vinh Le f2f7742709 Adapt e2e 2017-12-19 19:40:16 +01:00
Chi Vinh Le 689fb4baf0 Remove z-index 2017-12-19 19:26:22 +01:00
Chi Vinh Le 650f98a080 Merge branch 'portal-dialog' of ssh://github.com/coralproject/talk into portal-dialog 2017-12-19 19:25:35 +01:00
Chi Vinh Le 88d3a53165 Make backdrop work 2017-12-19 19:24:39 +01:00
Kiwi 6e88976294 Merge branch 'master' into portal-dialog 2017-12-19 19:17:50 +01:00
Chi Vinh Le f25cc56ddb Use Portal to put dialogs to the end of the document 2017-12-19 19:15:45 +01:00
Kiwi 4134b2edb2 Merge pull request #1222 from coralproject/app-plugin
Added support for app plugin hook
2017-12-19 19:08:27 +01:00
Kiwi 5b886b6eea Merge branch 'master' into app-plugin 2017-12-19 18:57:31 +01:00
Kiwi 6c80de2981 Merge pull request #1224 from coralproject/e2e-stability
Increase e2e stability
2017-12-19 18:57:17 +01:00
Kiwi b9b3355317 Merge branch 'master' into e2e-stability 2017-12-19 18:49:35 +01:00
Chi Vinh Le 88e9faea00 Increase e2e stability 2017-12-19 18:48:44 +01:00
Kiwi b1c9fbedd8 Merge branch 'master' into app-plugin 2017-12-19 18:37:01 +01:00
Kiwi c9b7eb3494 Merge pull request #1223 from coralproject/fix-dialog
Fix dialog not rendering fully in firefox
2017-12-19 18:34:49 +01:00
Chi Vinh Le 66287f5b7d Fix dialog not rendering fully in firefox 2017-12-19 18:27:19 +01:00
Kiwi b61eeeba74 Merge branch 'master' into app-plugin 2017-12-19 18:02:43 +01:00
Kim Gardner 2179632c94 Merge pull request #1221 from coralproject/e2e-fixes
E2e improvements and fixes
2017-12-19 11:42:10 -05:00
Wyatt Johnson 4342161a70 Merge branch 'master' into app-plugin 2017-12-19 09:31:13 -07:00
Kim Gardner a48688ad35 Merge branch 'master' into e2e-fixes 2017-12-19 11:18:28 -05:00
Kim Gardner 1b4f783abd Merge pull request #1208 from coralproject/virtualized
Mod Queue improvements
2017-12-19 11:18:09 -05:00
Wyatt Johnson e2d8562868 added support for app plugin hook 2017-12-19 09:13:01 -07:00
Kim Gardner 91602b9d34 Merge branch 'master' into virtualized 2017-12-19 10:33:22 -05:00
Kim Gardner eba530eda0 Merge branch 'master' into e2e-fixes 2017-12-19 10:33:18 -05:00
Kim Gardner 8e1cfc3a29 Merge pull request #1219 from coralproject/bump-version-3-9-0
Version 3.9.0
2017-12-19 10:33:05 -05:00
Chi Vinh Le c78bb598e7 Merge branch 'e2e-fixes' of ssh://github.com/coralproject/talk into e2e-fixes 2017-12-19 16:27:20 +01:00
Chi Vinh Le f12abbf39e Default timeout to 10000 for ci 2017-12-19 16:26:55 +01:00
Kiwi 7dcb1dfbaa Merge branch 'master' into e2e-fixes 2017-12-19 16:16:59 +01:00
Chi Vinh Le 1fce2451c7 Remove some blank lines 2017-12-19 16:16:59 +01:00
Chi Vinh Le e4f1f5d08b Allow disabling e2e in ci 2017-12-19 16:14:59 +01:00
Chi Vinh Le d06ff8c93c Double default WaitForTimeout 2017-12-19 15:56:54 +01:00
Kim Gardner 9d9056ef86 Merge branch 'master' into bump-version-3-9-0 2017-12-19 08:28:01 -06:00
Kim Gardner 1b61ca8abf Merge branch 'master' into virtualized 2017-12-19 08:27:58 -06:00
Kim Gardner f75a743090 Merge pull request #1220 from coralproject/schema-level-plugin-support
Schema + Connector Plugin Support
2017-12-19 08:27:32 -06:00
Chi Vinh Le 82e617b19b Enable firefox and edge 2017-12-19 14:48:58 +01:00
Chi Vinh Le 7a4b87f743 Fix popup issues 2017-12-19 14:42:54 +01:00
Chi Vinh Le 71f0887a82 Make browsers configurable through ENV E2E_BROWSERS 2017-12-19 14:42:29 +01:00
Chi Vinh Le 4116e206a3 Configurable timeout 2017-12-19 14:41:51 +01:00
Chi Vinh Le e78f17460f Fix wrong spec 2017-12-19 14:27:34 +01:00
Kim Gardner 70bfd91359 Merge branch 'master' into virtualized 2017-12-18 17:37:04 -06:00
Kim Gardner b3432a5e0d Merge branch 'master' into bump-version-3-9-0 2017-12-18 17:36:56 -06:00
Wyatt Johnson 382cb42dcf Merge branch 'master' into schema-level-plugin-support 2017-12-18 16:27:38 -07:00
Wyatt Johnson dbd106d523 added support for plugging into schema level resolve 2017-12-18 16:24:28 -07:00
Kim Gardner e8f94d4d4a Merge pull request #1209 from coralproject/i18n-serverside-plugins
i18n + Email Support
2017-12-18 17:03:47 -06:00
Kim Gardner 3ea141d4b0 Merge branch 'master' into i18n-serverside-plugins 2017-12-18 16:44:23 -06:00
Kim Gardner f783c8423d Merge pull request #1211 from coralproject/premod-admin-comments
Fix new admin comments not showing up in premod
2017-12-18 16:44:15 -06:00
Kim Gardner 9d4a9861f2 Merge branch 'master' into premod-admin-comments 2017-12-18 16:34:13 -06:00
Kim Gardner 6d69286df6 Merge pull request #1214 from coralproject/confirmation-featured
Confirmation Dialog for Featuring Comments on the Admin Side
2017-12-18 16:34:01 -06:00
Kim Gardner 3121ffb55a Version 3.9.0 2017-12-18 17:31:25 -05:00
Kim Gardner c0af51fbc0 Merge branch 'master' into confirmation-featured 2017-12-18 16:27:00 -06:00
Kim Gardner ad85b0fcc8 Merge pull request #1216 from coralproject/change-permalink-share
Update permalink copy to "Share" on stream
2017-12-18 16:26:43 -06:00
Kim Gardner 5ad73b1c14 Merge branch 'master' into change-permalink-share 2017-12-18 16:17:31 -06:00
Kim Gardner bf83f462e0 Merge pull request #1217 from coralproject/fix-login-profile
Fix sign in on profile tab
2017-12-18 16:17:19 -06:00
Kim Gardner 8dd79a19c3 Merge branch 'master' into fix-login-profile 2017-12-18 16:09:37 -06:00
Kim Gardner a8368eb78d Merge pull request #1218 from coralproject/ci-fix
Disabling Firefox/Edge on E2E until fix pass
2017-12-18 13:58:02 -06:00
Wyatt Johnson e88bac6e0f Merge branch 'master' into ci-fix 2017-12-18 12:45:40 -07:00
Kim Gardner 281d1f65f1 Merge branch 'master' into i18n-serverside-plugins 2017-12-18 13:44:20 -06:00
Kim Gardner 2704d71b09 Merge branch 'master' into fix-login-profile 2017-12-18 13:43:45 -06:00
Wyatt Johnson 583ab0ff74 disabling firefox,edge 2017-12-18 12:42:58 -07:00
Kim Gardner ad5c0444f7 Merge branch 'master' into virtualized 2017-12-18 12:43:16 -06:00
Belén Curcio 2a74e75506 Merge branch 'master' into confirmation-featured 2017-12-18 15:39:55 -03:00
Wyatt Johnson fb7ad76b8b Merge pull request #1215 from coralproject/ci-fix
*Fixes for sorted window handler
2017-12-18 11:36:47 -07:00
Kiwi eddb471366 Merge branch 'master' into virtualized 2017-12-18 19:29:35 +01:00
okbel 35c88ffab4 spreading the rest first 2017-12-18 15:21:02 -03:00
okbel 1cdef8f864 bounded 2017-12-18 15:20:06 -03:00
Kim Gardner 82fd56dc67 Update permalink copy to Share on stream 2017-12-18 13:09:39 -05:00
Chi Vinh Le 0e01d40aa7 Fix sign in on profile tab 2017-12-18 19:01:43 +01:00
Wyatt Johnson f7d1543aa3 fixes for sorted window handler 2017-12-18 10:24:11 -07:00
Belén Curcio d2ebc81e25 Merge branch 'master' into confirmation-featured 2017-12-18 13:52:01 -03:00
Belen Curcio 278e1cec1d done 2017-12-18 13:42:59 -03:00
Kim Gardner 31436e627d Merge branch 'master' into i18n-serverside-plugins 2017-12-18 10:39:27 -06:00
Kim Gardner 4e50865927 Merge branch 'master' into premod-admin-comments 2017-12-18 10:39:06 -06:00
Belen Curcio 6ad218782e styling 2017-12-18 13:39:02 -03:00
Belen Curcio 8f1f875d76 less data to the store 2017-12-18 13:36:30 -03:00
Belen Curcio 9fb8e01cd2 working, still wip 2017-12-18 13:34:48 -03:00
Kim Gardner 950a35310b Merge pull request #1212 from coralproject/user-detail-load-more-fix
Fix load more in UserDetail issue
2017-12-18 10:23:50 -06:00
Kiwi 12884cce01 Merge branch 'master' into i18n-serverside-plugins 2017-12-18 17:12:54 +01:00
Kiwi f8d153cf95 Merge branch 'master' into virtualized 2017-12-18 17:12:49 +01:00
Kiwi c871f1c797 Merge branch 'master' into premod-admin-comments 2017-12-18 17:12:41 +01:00
Kiwi 9af7ae0357 Merge branch 'master' into user-detail-load-more-fix 2017-12-18 17:12:36 +01:00
Wyatt Johnson 073eea2847 Merge pull request #1213 from coralproject/version-bump
Version Bump
2017-12-18 09:11:52 -07:00
Kiwi 9cb6ff3847 Merge branch 'master' into virtualized 2017-12-18 16:59:31 +01:00
Wyatt Johnson c699e044fd Update package.json 2017-12-18 08:55:49 -07:00
Kiwi 7d3ec7da1e Merge branch 'master' into premod-admin-comments 2017-12-18 16:55:38 +01:00
Belen Curcio 5d288da69d Merge branch 'master' of github.com:coralproject/talk into confirmation-featured 2017-12-18 12:55:31 -03:00
Kiwi 4ef7abc132 Merge branch 'master' into user-detail-load-more-fix 2017-12-18 16:55:31 +01:00
Wyatt Johnson 9e486f3a9d Merge pull request #1210 from coralproject/redis-optim
Redis Optimization Pass
2017-12-18 08:55:18 -07:00
Chi Vinh Le fbcd390220 Fix load more issue 2017-12-18 16:52:57 +01:00
okbel 338c23dc3d unnecesary class 2017-12-18 12:46:24 -03:00
okbel 4d6f38a3d9 wip 2017-12-18 12:43:46 -03:00
Chi Vinh Le 5b8f335b2a Fix new admin comments not showing up in premod 2017-12-18 16:41:05 +01:00
Wyatt Johnson f0330ed21c fixed version paths 2017-12-18 08:35:17 -07:00
okbel 02da749c65 Adding containers and components 2017-12-18 12:20:20 -03:00
okbel 5a1393c039 Adding translations 2017-12-18 12:20:06 -03:00
okbel d7a5e613fa Adding reducer 2017-12-18 12:19:46 -03:00
Wyatt Johnson 75a944eba8 upgrades, fixes to comment count logic 2017-12-18 08:02:43 -07:00
Chi Vinh Le 9a0fb95d06 Pagination fixes 2017-12-18 15:03:54 +01:00
Wyatt Johnson 6850dd1a53 redis optim
- removes call for comment count when we already have
  totalCommentCount
- removes job processor cleaner on non-processing nodes
- fixed some template issues
2017-12-15 15:49:56 -06:00
Wyatt Johnson ecb01224fd Merge branch 'master' into i18n-serverside-plugins 2017-12-15 10:40:08 -06:00
Wyatt Johnson fdd5cbb0d7 moved email contents to translation files 2017-12-14 16:56:24 -06:00
Wyatt Johnson eb9827a3ae more fixes for i18n 2017-12-14 16:48:03 -06:00
Wyatt Johnson d207b240f2 added support for changing the subject prefi 2017-12-14 16:28:08 -06:00
Wyatt Johnson d9654b52cf some fixes 2017-12-14 16:09:41 -06:00
Wyatt Johnson d3965924aa fixed template 2017-12-14 15:51:53 -06:00
Wyatt Johnson 36d535546c plugins serverside can now provide translations 2017-12-14 15:03:35 -06:00
Chi Vinh Le 19568afde5 Reduce view more movements 2017-12-14 21:08:13 +01:00
Chi Vinh Le 2b312dbf8e Next try 2017-12-14 20:41:05 +01:00
Chi Vinh Le 5446abe3a9 Fix bug with featured comments 2017-12-14 20:37:51 +01:00
Chi Vinh Le c66c100dcb Cache callbacks to preserve immutability 2017-12-14 20:27:19 +01:00
Chi Vinh Le d4051f6828 Fix view more styling 2017-12-14 20:08:09 +01:00
Chi Vinh Le 33781c3d16 Fix view new comments 2017-12-14 20:01:33 +01:00
Chi Vinh Le defc4049cb Sort correctly + refactors and comments 2017-12-14 19:47:42 +01:00
Chi Vinh Le 243d0c1493 Limit to 100 comments 2017-12-14 18:33:49 +01:00
Kiwi a448c69a2a Merge branch 'master' into virtualized 2017-12-14 18:32:28 +01:00
Chi Vinh Le 0b774402cf Introduce dangling comments and queue cleanup 2017-12-14 18:19:00 +01:00
Chi Vinh Le 0bda44e97f Fix cursor bug 2017-12-14 16:51:50 +01:00
Chi Vinh Le 60f6c63c8a Restrict notifications to comments which are rendered 2017-12-14 16:29:31 +01:00
Chi Vinh Le 62c2d551f8 Append comments only 2017-12-14 15:57:44 +01:00
Chi Vinh Le f32bb5ce8f Small adjustments 2017-12-14 13:55:08 +01:00
Chi Vinh Le 5e6d22f1af Handle removing comments from queue 2017-12-14 13:38:01 +01:00
Chi Vinh Le 34289e3340 Refactor view 2017-12-14 12:35:26 +01:00
Wyatt Johnson 98ef60a48e Merge pull request #1205 from stephendonner/patch-1
s/setup/setup
2017-12-13 12:34:30 -06:00
Wyatt Johnson 8323344d7d Merge branch 'master' into patch-1 2017-12-13 12:26:24 -06:00
Wyatt Johnson fbecc363cf Merge pull request #1206 from coralproject/feature/infer-asset-url
Fix logic to generate asset_url even if the asset_id is provided
2017-12-13 12:25:27 -06:00
Chi Vinh Le 2779734ec0 Workaround 2017-12-13 15:25:47 +01:00
Chi Vinh Le 5548deb6b5 Auto Load More and other bug fixes 2017-12-13 15:06:01 +01:00
Jeff Nelson df925f5a1a Fix logic to generate asset_url even if the asset_id is provided so
an error is avoided
2017-12-13 07:38:10 -06:00
Stephen Donner 30073b88f1 s/setup/setup 2017-12-13 03:49:35 -06:00
Chi Vinh Le 51bd109f13 Fix some bugs 2017-12-12 17:28:38 +01:00
Chi Vinh Le b12d5f6bd7 Reimplement keyboard navigation 2017-12-12 17:19:11 +01:00
Chi Vinh Le f32e4523e8 Make view more coments work with virtualized 2017-12-12 12:53:54 +01:00
Chi Vinh Le ed959ca07a Integrate react-virtualized 2017-12-11 20:21:27 +01:00
Wyatt Johnson 27ecbd1bdd Merge pull request #1204 from coralproject/document-optimization-reapply
Reapply optimizations
2017-12-08 16:01:47 -07:00
Chi Vinh Le 4477c0981f Reapply optimizations 2017-12-08 23:38:10 +01:00
Wyatt Johnson 2c9eae9264 Merge pull request #1202 from coralproject/fix-load-more-replies
Fix load more replies
2017-12-08 15:19:27 -07:00
Wyatt Johnson 812a4ee704 Update package.json 2017-12-08 15:19:01 -07:00
Wyatt Johnson d3caf350ac Merge branch 'master' into fix-load-more-replies 2017-12-08 15:18:35 -07:00
Wyatt Johnson 864e3f1a1f Merge pull request #1203 from coralproject/revert-1201-document-optimization-v2
Revert "Optimizations v2"
2017-12-08 15:18:23 -07:00
Wyatt Johnson 61d16fbe08 Revert "Optimizations v2" 2017-12-08 15:17:28 -07:00
Wyatt Johnson 000e26e3e1 Merge pull request #1201 from coralproject/document-optimization-v2
Optimizations v2
2017-12-08 15:15:47 -07:00
Chi Vinh Le 71f0200557 Fix load more replies 2017-12-08 23:14:40 +01:00
Wyatt Johnson d79edcd412 Merge branch 'master' into document-optimization-v2 2017-12-08 15:08:15 -07:00
Wyatt Johnson 485b9d036f version bump 2017-12-08 15:07:15 -07:00
Wyatt Johnson 041ba95a5b Merge pull request #1199 from coralproject/less-lazy-assets
Less Lazy Assets
2017-12-08 15:06:33 -07:00
Wyatt Johnson d0d047f641 fixed bug with load more 2017-12-08 15:04:33 -07:00
Wyatt Johnson b057131d34 Merge branch 'master' into less-lazy-assets 2017-12-08 13:59:15 -07:00
Chi Vinh Le ba572fbf48 Typo 2017-12-07 20:24:45 +01:00
Chi Vinh Le e3c1f8c231 Merge branch 'document-optimization-v2' of ssh://github.com/coralproject/talk into document-optimization-v2 2017-12-07 20:23:38 +01:00
Chi Vinh Le 07ddb94327 Fix yarn.lock 2017-12-07 20:23:05 +01:00
Kiwi 0addb938ae Merge branch 'master' into document-optimization-v2 2017-12-07 19:54:17 +01:00
Wyatt Johnson c0d01e55e1 Merge pull request #1200 from coralproject/delay-subscription-handler
Delay throttled subscription handler until query has loaded
2017-12-07 11:44:37 -07:00
Chi Vinh Le 3ac301142e Update graphql-ast-tools 2017-12-07 19:43:32 +01:00
Chi Vinh Le 7072aa013b document optimizations v2 2017-12-07 18:41:46 +01:00
Chi Vinh Le 091be25f36 Delay throttled subscription handler until query has loaded 2017-12-07 16:55:36 +01:00
Wyatt Johnson 41a3639d31 Merge branch 'master' into less-lazy-assets 2017-12-06 16:33:13 -07:00
Wyatt Johnson f96146bfd9 Merge pull request #1195 from coralproject/graphql-ast-tools
Use graphql-ast-tools
2017-12-06 16:32:59 -07:00
Wyatt Johnson 2eec87aa80 modified asset loading to be less lazy 2017-12-06 16:10:42 -07:00
Chi Vinh Le aabd40d53a Remove apollo-utilities 2017-12-06 11:45:16 +01:00
Wyatt Johnson 9bce69a7cd Merge branch 'master' into graphql-ast-tools 2017-12-05 13:41:48 -07:00
Kim Gardner 7afa6c018b Merge pull request #1196 from coralproject/logic-fix
Staff Configuration Fix
2017-12-05 19:51:00 +00:00
Wyatt Johnson 94b56b547f fixed small bug 2017-12-05 12:31:36 -07:00
Kiwi 6329e9f618 Merge branch 'master' into graphql-ast-tools 2017-12-05 19:52:27 +01:00
Kim Gardner ea7266595d Merge pull request #1194 from coralproject/perf-pass
Performance Pass
2017-12-05 18:44:31 +00:00
Kiwi 4f2d97cd82 Merge branch 'master' into graphql-ast-tools 2017-12-05 19:42:24 +01:00
Chi Vinh Le 6a00d3d249 Remove unused code 2017-12-05 19:40:53 +01:00
Chi Vinh Le d3040804a2 Upgrade graphql-anywhere-optimized and graphql-ast-tools 2017-12-05 19:39:14 +01:00
Wyatt Johnson 24596a48bd Merge branch 'master' into perf-pass 2017-12-05 11:29:21 -07:00
Chi Vinh Le 04ae844a1a Use graphql-ast-tools 2017-12-05 19:25:32 +01:00
Wyatt Johnson a8a8455f40 removed reference 2017-12-05 11:23:36 -07:00
Wyatt Johnson d7302e4b3c added support for deep route caching, settings cache, template optim 2017-12-05 11:17:44 -07:00
Kim Gardner f09ca6d060 Merge pull request #1193 from coralproject/fix-incorrect-class-reason-popup
Update CSS classname
2017-12-05 17:57:43 +00:00
Kim Gardner 73f24fd75b Update CSS classname 2017-12-05 17:16:39 +00:00
Wyatt Johnson 001beb7a5b Merge pull request #1186 from coralproject/performance-enhancements
Performance enhancements
2017-12-04 15:16:57 -07:00
Chi Vinh Le 0b04a011c4 Merge branch 'performance-enhancements' of ssh://github.com/coralproject/talk into performance-enhancements 2017-12-04 22:50:06 +01:00
Chi Vinh Le 00fb2e277b Merge branch 'master' into performance-enhancements 2017-12-04 22:49:06 +01:00
Chi Vinh Le a79dd76f4b Use graphql document optimizations only in production 2017-12-04 22:46:33 +01:00
Chi Vinh Le 0d91396b1c Remove death star button 2017-12-04 22:45:23 +01:00
Wyatt Johnson e1324a168b Merge pull request #1191 from coralproject/graph-flags
Graph flags
2017-12-04 14:44:48 -07:00
Kiwi af9180f114 Merge branch 'master' into graph-flags 2017-12-04 22:28:36 +01:00
Wyatt Johnson 8f5e54520b Merge branch 'master' into performance-enhancements 2017-12-04 14:26:29 -07:00
Chi Vinh Le 2061a7b97d Use @coralproject/graphql-anywhere-optimized 2017-12-04 22:21:40 +01:00
Wyatt Johnson 3b4e69f06e fixed based on e2e finding a bug! 2017-12-04 14:06:32 -07:00
Kim Gardner f71be09bca Merge pull request #1189 from coralproject/user-badges-fix
User Badges Styling Fix
2017-12-04 19:31:17 +00:00
Wyatt Johnson 87ef0f1cb9 Adjusted flag beheviour for staff 2017-12-04 12:17:39 -07:00
Belen Curcio 0640be2a77 Timestamp no break 2017-12-04 15:00:43 -03:00
Belen Curcio fdf11fa277 Adding extra container and styling 2017-12-04 13:42:22 -03:00
Wyatt Johnson 8b71175c46 adjusted logic flow for comment flags 2017-12-04 09:27:56 -07:00
Belen Curcio 6da4439b94 Adding header container 2017-12-02 00:20:59 -03:00
Belen Curcio 7731ec42de css tag label 2017-12-01 23:43:19 -03:00
Belen Curcio 67a4d63a23 Good margin 2017-12-01 15:31:05 -03:00
Belen Curcio ce9ee0a5b0 Adding styles for mob devs 2017-12-01 15:28:09 -03:00
Kiwi 2e8f5f2e69 Merge branch 'master' into performance-enhancements 2017-12-01 17:57:24 +01:00
Chi Vinh Le 099186d030 Make polling interval longer 2017-12-01 17:56:53 +01:00
Kim Gardner 99daa0b2c9 Merge pull request #1187 from coralproject/remove-dash
Remove Dashboard for the interim
2017-12-01 16:27:53 +00:00
Chi Vinh Le c2b488fa98 Don't use murmurhash 2017-12-01 17:11:38 +01:00
Chi Vinh Le 612d2596f9 Turn NamedFragments with directives always into InlineFragments 2017-12-01 17:02:45 +01:00
Chi Vinh Le 835d30d362 Put document optimizations behind a option 2017-12-01 16:54:45 +01:00
Chi Vinh Le 015e3d3ed9 Tiny refactor 2017-12-01 16:47:54 +01:00
Chi Vinh Le 4c7c852af7 Only merge definitions with directives when they are the same 2017-12-01 16:44:01 +01:00
Chi Vinh Le 72123cabe7 Rename getDefinitionName to getDefinitionID 2017-12-01 16:33:38 +01:00
Chi Vinh Le f17b296e2e Cache resolved fragments (globally) 2017-12-01 16:31:26 +01:00
Chi Vinh Le 2c72975137 Preoptimize mutation, fragments and batched subscription documents 2017-12-01 15:42:13 +01:00
Chi Vinh Le 5c1314165c Upgrade graphql-anywhere-optimized 2017-12-01 14:16:32 +01:00
Chi Vinh Le fd83fed7bb Preoptimize queries and subscriptions documents 2017-12-01 14:10:38 +01:00
Kim Gardner dff89ec6cd Remove Dashboard docs 2017-12-01 12:53:17 +00:00
Wyatt Johnson ef200a85cb removed backend for metrics 2017-11-30 17:16:32 -07:00
Kim Gardner 9c0e6ccb36 Remove Dashboard 2017-11-30 23:21:01 +00:00
Kim Gardner 64276cd157 Remove Dashboard 2017-11-30 23:20:01 +00:00
Chi Vinh Le 214de045fb One subscription queue per query 2017-11-30 22:44:29 +01:00
Chi Vinh Le 92a9a535c6 Merge branch 'master' into performance-enhancements 2017-11-30 22:23:11 +01:00
Chi Vinh Le 3db7439d76 Use custom optimized graphql-anywhere 2017-11-30 21:55:16 +01:00
Chi Vinh Le 65be2b89a4 Throttle instead of debounce 2017-11-30 21:44:32 +01:00
Kim Gardner c9f6ec327a Merge pull request #1185 from coralproject/qbox-fix
Fix Stream: Question Box
2017-11-30 19:33:52 +00:00
Chi Vinh Le 06ddb30d77 Decouple apollo store 2017-11-30 20:26:08 +01:00
Belen Curcio af3542aec5 adding and enabling question box 2017-11-30 15:30:21 -03:00
Kim Gardner 016eb472eb Merge pull request #1184 from coralproject/jobs-stream-fix
Jobs + Pending Box Fixes
2017-11-30 17:06:56 +00:00
Chi Vinh Le ab772839c5 Debounce and batch subscription updates 2017-11-30 16:38:38 +01:00
Wyatt Johnson 1b9c2404db fixed job cli, reverted comment box pending beheviour 2017-11-29 15:57:28 -07:00
Chi Vinh Le cf96d07a7a Better death star 2017-11-29 11:54:51 +01:00
Kim Gardner 1c01a3320f Merge pull request #1179 from coralproject/firefox-hover-tab
Firefox hover tab
2017-11-28 20:16:22 +00:00
Wyatt Johnson 8d018df0d1 Merge branch 'master' into firefox-hover-tab 2017-11-28 13:05:50 -07:00
Kim Gardner b2a2b135a4 Merge pull request #1173 from coralproject/refactor-configure
Rewrite/Refactor stream configure
2017-11-28 19:49:49 +00:00
Kim Gardner ccd22ea334 Merge branch 'master' of git+ssh://github.com/coralproject/talk into refactor-configure 2017-11-28 19:40:22 +00:00
Kim Gardner 83910f7fce Merge pull request #1163 from coralproject/extendable-embed-stream-tab
Extendable embed stream tabs
2017-11-28 19:39:36 +00:00
Wyatt Johnson 28873ed961 Merge branch 'master' into refactor-configure 2017-11-28 09:46:11 -07:00
Kim Gardner e3febf4a0c Merge branch 'master' into firefox-hover-tab 2017-11-28 16:32:57 +00:00
Kim Gardner c3b25d2d0a Merge branch 'master' into extendable-embed-stream-tab 2017-11-28 16:31:50 +00:00
Kim Gardner 96a375e38a Merge pull request #1183 from coralproject/bump-version-3-8-1
Version 3.8.1
2017-11-28 16:30:45 +00:00
Wyatt Johnson 417a7a3c36 added excemption as no fix available as of yet 2017-11-28 09:16:33 -07:00
Wyatt Johnson c903d8c0f9 Merge branch 'master' into bump-version-3-8-1 2017-11-28 08:44:46 -07:00
Kim Gardner 24e895460b Merge branch 'master' into firefox-hover-tab 2017-11-27 17:23:36 +00:00
Kim Gardner d6a83201ad Merge branch 'master' into extendable-embed-stream-tab 2017-11-27 17:21:24 +00:00
Kim Gardner bbdde50858 Merge pull request #1177 from coralproject/graph-context-connectors
Graph Context Connectors
2017-11-27 17:20:48 +00:00
Kim Gardner 8730ada87c Merge branch 'master' into extendable-embed-stream-tab 2017-11-27 16:30:22 +00:00
Kim Gardner 506b938536 Merge branch 'master' into firefox-hover-tab 2017-11-27 16:30:12 +00:00
Kim Gardner 043e722d95 Merge branch 'master' into graph-context-connectors 2017-11-27 16:30:04 +00:00
Kim Gardner fb1dc23fa9 Version 3.8.1 2017-11-27 16:28:46 +00:00
Kim Gardner e882b51ed0 Merge pull request #1172 from coralproject/update-bug-report-link
Update Report Bug link in Admin Settings
2017-11-27 16:27:40 +00:00
Kim Gardner e52a6fd9c1 Merge branch 'master' into update-bug-report-link 2017-11-27 16:15:04 +00:00
Kim Gardner 24af7b2812 Merge pull request #1180 from coralproject/autclose-firefox-bug
auto close input: fix styling bug in firefox
2017-11-27 13:17:30 +00:00
Kim Gardner 24b5a58584 Merge branch 'master' into autclose-firefox-bug 2017-11-27 13:07:10 +00:00
Kim Gardner a868cc9c67 Merge pull request #1178 from coralproject/more-padding-qbox
More padding for question box
2017-11-27 13:05:52 +00:00
Kim Gardner af83d32de1 Merge branch 'master' into more-padding-qbox 2017-11-27 12:51:50 +00:00
Kim Gardner fa82824d03 Merge pull request #1181 from coralproject/firefox-stories
Fix radiogroup not working properly in ff
2017-11-27 12:51:39 +00:00
Kim Gardner f0033a7912 Merge branch 'master' into firefox-stories 2017-11-27 12:41:14 +00:00
Kim Gardner 0924531677 Merge pull request #1182 from coralproject/sort-stories
Sort by publication_date
2017-11-27 12:40:50 +00:00
Kim Gardner 44b77597ed Merge branch 'master' into update-bug-report-link 2017-11-27 12:36:59 +00:00
Chi Vinh Le ec2bf3cb7f Sort by publication_date 2017-11-24 12:41:18 +01:00
Chi Vinh Le 37f3c11104 Fix radiogroup not working properly in ff 2017-11-24 12:29:29 +01:00
Chi Vinh Le 9359bfc322 Fix styling bug in firefox 2017-11-23 20:09:16 +01:00
Kiwi 111ebd67ba Merge branch 'master' into extendable-embed-stream-tab 2017-11-23 14:49:54 +01:00
Chi Vinh Le 31f87dc192 Pass hover props to extendable tabs in order to support firefox 2017-11-23 14:46:23 +01:00
Chi Vinh Le c9dad30c71 Merge branch 'extendable-embed-stream-tab' into firefox-hover-tab 2017-11-23 14:46:18 +01:00
Chi Vinh Le 7f53375c67 More padding for question box 2017-11-23 13:40:19 +01:00
Chi Vinh Le df0c016e37 Merge branch 'refactor-configure' of ssh://github.com/coralproject/talk into refactor-configure 2017-11-23 13:33:21 +01:00
Chi Vinh Le bf3fe2ab8e Merge branch 'master' into refactor-configure 2017-11-23 13:27:18 +01:00
Wyatt Johnson 9629ba2f83 added connector support 2017-11-22 14:48:34 -07:00
Kim Gardner ac7b4d56a1 Merge pull request #1174 from coralproject/show-all-comments-button
new design for show all comments button
2017-11-22 16:35:40 +00:00
Kim Gardner c29bb02b1c Merge branch 'master' into show-all-comments-button 2017-11-22 12:09:23 +00:00
Kim Gardner 8c72e32a25 Merge branch 'master' into update-bug-report-link 2017-11-22 12:09:17 +00:00
Kim Gardner 4a31bb7ba2 Merge branch 'master' into extendable-embed-stream-tab 2017-11-22 12:09:02 +00:00
Kim Gardner 3be1c94f8f Merge branch 'master' into refactor-configure 2017-11-22 12:07:26 +00:00
Kim Gardner 7fba0428bb Merge pull request #1175 from coralproject/cli-users-fix
User CLI Fix
2017-11-21 19:24:35 +00:00
Wyatt Johnson c7d433deb5 added better logic around removing users for clearning out their stale data. 2017-11-21 12:13:28 -07:00
Chi Vinh Le a665dbd88e Reproduce modqueue freeze issue 2017-11-21 18:07:00 +01:00
Chi Vinh Le c990a812a4 new design for show all comments button 2017-11-21 15:59:20 +01:00
Kim Gardner 3f26a8d7ad Merge branch 'master' into extendable-embed-stream-tab 2017-11-21 12:31:45 +00:00
Kiwi 4a3e5942b0 Merge branch 'master' into refactor-configure 2017-11-21 12:58:16 +01:00
Chi Vinh Le 5360bdc8ec Add some docs 2017-11-21 12:42:17 +01:00
Chi Vinh Le 548a204665 Expose StreamConfiguration 2017-11-21 11:13:41 +01:00
Chi Vinh Le a8e8b78441 Pass updatePending and errors through slots 2017-11-21 11:08:18 +01:00
Chi Vinh Le 258788fd88 Add updatePending and errors to admin settings slots 2017-11-21 11:06:11 +01:00
Chi Vinh Le 8cc3d19819 Fix query 2017-11-21 10:35:38 +01:00
Chi Vinh Le 0de5a328ab Slot streamSettings 2017-11-20 21:11:59 +01:00
Kim Gardner 4830aec138 Update Report Bug link in Admin Settings 2017-11-20 19:59:57 +00:00
Kim Gardner 4269fd1eb9 Merge pull request #1171 from coralproject/copy-updates
Update suspend copy
2017-11-20 19:53:00 +00:00
Kim Gardner 12e61bbc66 Update suspend copy 2017-11-20 19:41:14 +00:00
Chi Vinh Le 511e71f63a Change default settings=null to settings={} 2017-11-20 20:19:58 +01:00
Chi Vinh Le e675d716cb Remove deprecated code 2017-11-20 20:18:14 +01:00
Chi Vinh Le 2d6143af62 Fully implement mutation 2017-11-20 19:48:12 +01:00
Chi Vinh Le 873d1915c3 Implement apply 2017-11-20 19:20:09 +01:00
Chi Vinh Le 67f3f8cdef SimpleMDE don't trap keyboard 2017-11-20 18:14:17 +01:00
Chi Vinh Le 8f0eef7cb5 Reimplement QuestionBoxBuilder 2017-11-20 17:53:26 +01:00
Chi Vinh Le 4c7c3c9e42 Add premodLinks configuration 2017-11-20 12:36:49 +01:00
Chi Vinh Le 8f9724ed90 Implement configure and redux state 2017-11-20 12:29:23 +01:00
Chi Vinh Le 9fb7aa2657 Start implementing settings ui 2017-11-18 11:40:44 +01:00
Kiwi d714586279 Merge branch 'master' into extendable-embed-stream-tab 2017-11-17 17:12:42 +01:00
Chi Vinh Le 3e4c9dcb48 Refactor query tree 2017-11-17 17:02:32 +01:00
Chi Vinh Le 285ec98d54 Refactor styles 2017-11-17 16:53:56 +01:00
Chi Vinh Le 853b0ca6dd Automatic asset closure 2017-11-17 15:42:06 +01:00
Chi Vinh Le c58d9068e3 Implement open and close asset 2017-11-17 12:39:34 +01:00
Chi Vinh Le 78e0fb6cc6 Add UpdateAssetStatus mutation 2017-11-16 20:31:08 +01:00
Chi Vinh Le dfbb9ad96f Implement AssetStatusInfo UI 2017-11-16 20:31:00 +01:00
Kim Gardner 2d43eef508 Merge pull request #1167 from coralproject/query-status-history
Fix SetCommentStatus mutation on admin side
2017-11-16 19:05:23 +00:00
Kiwi fa22e45a4d Merge branch 'master' into query-status-history 2017-11-16 19:53:23 +01:00
Chi Vinh Le abdf5335da Add status_history to query 2017-11-16 19:52:47 +01:00
Wyatt Johnson c24454e234 Merge pull request #1165 from alleyinteractive/expose-recaptcha
Export CheckRecaptcha, so that it can be used in other services.
2017-11-16 11:36:25 -07:00
Wyatt Johnson 97e2e61a4b Merge branch 'master' into expose-recaptcha 2017-11-16 10:19:18 -07:00
Kim Gardner 57ced3c91f Merge pull request #1155 from coralproject/bump-version-3-8-0
Bump version 3.8.0
2017-11-16 16:57:36 +00:00
Chi Vinh Le f7c46b1a42 Move asset fragment up one level 2017-11-16 16:19:36 +01:00
Max Eddy c664438ade Export CheckRecaptcha, so that it can be used in other services. 2017-11-16 09:09:16 -05:00
Kim Gardner a5b5043a0d Merge branch 'master' into bump-version-3-8-0 2017-11-16 11:47:34 +00:00
Chi Vinh Le b5b6b113d4 Restructure coral-embed-stream 2017-11-16 10:57:16 +01:00
Chi Vinh Le a13d384cee Merge branch 'extendable-embed-stream-tab' into refactor-configure 2017-11-16 10:42:15 +01:00
Kiwi 3a0a854317 Merge branch 'master' into extendable-embed-stream-tab 2017-11-16 10:39:52 +01:00
Chi Vinh Le 73c3d31fbc Merge branch 'master' into refactor-configure 2017-11-16 10:30:16 +01:00
Belén Curcio 03a0d904d2 Merge pull request #1164 from coralproject/correct-proptype
Correct proptype
2017-11-15 16:45:30 -03:00
Chi Vinh Le 315d3babde Correct prop types 2 2017-11-15 20:03:41 +01:00
Chi Vinh Le 4d6055b9b8 Correct prop type 2017-11-15 19:53:58 +01:00
Chi Vinh Le d3d1148ee6 Merge branch 'master' into refactor-configure 2017-11-15 19:49:09 +01:00
Kiwi ecd9219e17 Merge branch 'master' into extendable-embed-stream-tab 2017-11-15 19:46:04 +01:00
Chi Vinh Le ce4ad426a7 Extendable embed stream tabs 2017-11-15 19:38:25 +01:00
Kim Gardner 77c8d966ab Merge pull request #1162 from coralproject/slot-classnames
Slot Classnames
2017-11-15 18:20:21 +00:00
Kim Gardner cabadf467f Merge branch 'master' into slot-classnames 2017-11-15 18:09:11 +00:00
Kim Gardner 0807acc98f Merge pull request #1159 from coralproject/more-undo
Enhanced undo
2017-11-15 18:09:04 +00:00
Belén Curcio 3c5b56c599 Merge branch 'master' into more-undo 2017-11-15 15:00:48 -03:00
Belen Curcio 899bba7327 Adding Proptypes and classNames for the Slots 🎉 2017-11-15 14:50:33 -03:00
Belen Curcio 41dd3eb180 Merge branch 'master' of github.com:coralproject/talk 2017-11-15 14:40:22 -03:00
Chi Vinh Le e02537df13 Fix mutation syntax 2017-11-15 17:53:24 +01:00
Kim Gardner 81d90cb138 Merge pull request #1161 from coralproject/break-word-2
Support long words for my and featured comments
2017-11-15 12:46:49 +00:00
Chi Vinh Le e4a359e0b4 Add mutation to framework 2017-11-15 13:38:02 +01:00
Chi Vinh Le 2882dfbadb Fix flexbox overflowing 2017-11-15 13:34:29 +01:00
Chi Vinh Le f2b9db9dbc Support long words for my and featured comments 2017-11-15 13:07:33 +01:00
Kim Gardner c563a13e7c Merge pull request #1160 from coralproject/break-word
Break long words in comment
2017-11-14 16:31:55 +00:00
Belen Curcio 5976595871 Merge branch 'master' of github.com:coralproject/talk 2017-11-14 13:03:10 -03:00
Chi Vinh Le 8a4a7d3589 Break long words in comment 2017-11-14 15:37:26 +01:00
Chi Vinh Le 5073e60df5 Translate 2017-11-14 14:05:30 +01:00
Chi Vinh Le 5a71db2568 Undo to previous status + Live updates 2017-11-14 13:58:18 +01:00
Kiwi ac0acea22b Merge pull request #1149 from devonJS/undo-reject
undo reject comment on stream
2017-11-14 12:49:48 +01:00
Belen Curcio 6198c9e730 Merge branch 'master' of github.com:coralproject/talk 2017-11-13 12:34:44 -03:00
Kiwi 9ac06281e9 Merge branch 'master' into undo-reject 2017-11-13 14:00:21 +01:00
Kim Gardner 78e5cb7aa6 Merge branch 'master' into bump-version-3-8-0 2017-11-13 12:49:47 +00:00
Kiwi 882bf57bbc Merge pull request #1152 from coralproject/user-status
More e2e tests - User Status
2017-11-10 21:16:59 +01:00
Chi Vinh Le 789fb3dfce Disable bs on this branch 2017-11-10 20:59:01 +01:00
Belen Curcio 819b1c597c refactor: working tests 2017-11-10 13:04:46 -03:00
Belen Curcio 38148ad51c Adding post animation test 2017-11-10 12:09:55 -03:00
Belen Curcio 8f6ff46244 passing suspendUserDialog to the adminPage scope 2017-11-10 11:16:35 -03:00
Belen Curcio 4727c52de4 camelCase lodash 2017-11-10 10:48:12 -03:00
Belen Curcio f461d27810 Merge branch 'master' of github.com:coralproject/talk into user-status 2017-11-10 10:46:53 -03:00
Belen Curcio fbc5a9d74b moderate 2017-11-10 10:45:26 -03:00
Belen Curcio 6ff4994d0d lodash.camelcase 2017-11-10 10:33:55 -03:00
Belen Curcio c793a840ea Merge branch 'user-status' of github.com:coralproject/talk into user-status 2017-11-10 10:27:28 -03:00
Belen Curcio ebda51dc0f Adding suspension test 2017-11-10 10:26:54 -03:00
Belen Curcio b0573749ee Adding classes and missingproptypes 2017-11-10 10:26:34 -03:00
Chi Vinh Le 933903de2f Remove IE 64bit from ci until they fix the keyboard input issues 2017-11-10 14:05:43 +01:00
Kim Gardner 4373c382e1 Merge pull request #1151 from coralproject/feature/fix-email-config-docs
Fix incorrect email configuration in docs
2017-11-10 12:02:22 +00:00
Kim Gardner af6787bc0f Merge branch 'master' into feature/fix-email-config-docs 2017-11-10 11:37:15 +00:00
Chi Vinh Le dd1fbf30ca Add navigateAndLogin 2017-11-10 10:51:30 +01:00
Chi Vinh Le a5aa59e255 Merge branch 'master' into user-status 2017-11-10 10:09:29 +01:00
Kiwi 19b8d0a6ea Merge pull request #1150 from coralproject/e2e-v2
e2e v2
2017-11-10 10:08:27 +01:00
Chi Vinh Le bcf8370359 Temporarily enable bs testing on this branch 2017-11-10 10:04:22 +01:00
Wyatt Johnson 0da0b1a37e Merge branch 'master' into feature/fix-email-config-docs 2017-11-09 16:23:24 -07:00
Chi Vinh Le 31ee8139b6 Use visible were suitable and wait for drawer to dissappear 2017-11-09 23:32:03 +01:00
Wyatt Johnson 51977dcf54 Merge branch 'master' into bump-version-3-8-0 2017-11-09 15:10:24 -07:00
Chi Vinh Le 0b18bb06e7 More tests 2017-11-09 22:31:53 +01:00
Chi Vinh Le 9abb3d30da e2e fixes 2017-11-09 22:04:32 +01:00
Chi Vinh Le f0839c57df Change to allowed name 2017-11-09 21:52:08 +01:00
Chi Vinh Le b2929e9a83 Fail fast 2017-11-09 21:51:41 +01:00
Chi Vinh Le ca7b790962 Return this 2017-11-09 21:51:31 +01:00
Chi Vinh Le 42a477ae41 Fix firefox popup bug e2e 2017-11-09 21:51:03 +01:00
Chi Vinh Le 53461df287 Increase wait for iframe time 2017-11-09 19:30:22 +01:00
Kiwi 9b18a78ce0 Merge branch 'master' into user-status 2017-11-09 19:20:06 +01:00
Chi Vinh Le da35f39baf Set resolution 2017-11-09 19:19:47 +01:00
Chi Vinh Le e885178dfc Refactor 2 2017-11-09 19:03:01 +01:00
Kim Gardner 24e8aab0fe Merge branch 'master' into e2e-v2 2017-11-09 17:09:56 +00:00
Kim Gardner 44d6ad340d Merge pull request #1156 from coralproject/queue-fix
Queue fix for custom assets
2017-11-09 17:09:25 +00:00
Chi Vinh Le 63b6315435 Refactor #1 2017-11-09 17:50:47 +01:00
Kiwi 95ca43ff8c Merge branch 'master' into e2e-v2 2017-11-09 16:23:20 +01:00
Chi Vinh Le 55e4aed511 Merge branch 'master' into user-status 2017-11-09 15:53:42 +01:00
Kim Gardner 6d5adc8f54 Bump version number to 3.8.0 2017-11-09 13:19:05 +00:00
Kim Gardner 247e05383e One more fix 2017-11-09 11:23:48 +00:00
Kim Gardner 3988fb9e93 Merge branch 'feature/fix-email-config-docs' of git+ssh://github.com/coralproject/talk into feature/fix-email-config-docs 2017-11-09 11:20:07 +00:00
Kim Gardner 7d524efaad Merge branch 'master' into feature/fix-email-config-docs 2017-11-09 11:19:57 +00:00
Kim Gardner d7a88cdc2a Fix config key 2017-11-09 11:18:58 +00:00
Wyatt Johnson 18f5b0cc5e queue fix for sometimes null settings 2017-11-08 14:24:48 -07:00
Kiwi 2df18f07cb Merge pull request #1140 from coralproject/user-pending
Users with PENDING status should not be allowed to post & E2E for User Status
2017-11-08 19:27:41 +01:00
Chi Vinh Le 786e85686d Fix invalid regexp for ie 2017-11-08 18:57:06 +01:00
Belen Curcio 9a651880a2 Updated login 2017-11-08 14:00:01 -03:00
Belen Curcio 82e01eac00 Merge branch 'master' of github.com:coralproject/talk into user-status 2017-11-08 13:56:48 -03:00
Belen Curcio 5efdc9865f refacotr 2017-11-08 12:59:08 -03:00
Belen Curcio 62d01cf2a0 perform login 2017-11-08 12:31:33 -03:00
Belen Curcio 81bf63836a tests 2017-11-08 12:23:40 -03:00
Belen Curcio 54ac2985ba Adding classes 2017-11-08 12:23:29 -03:00
Belen Curcio e9bd5703f1 refactor 2017-11-08 11:49:32 -03:00
Jeff Nelson a394ba29b3 Update 02-02-advanced-configuration.md
Change TALK_SMTP_EMAIL to TALK_SMTP_FROM_EMAIL
2017-11-08 07:11:03 -05:00
Belen Curcio a2470fa01b More 2017-11-07 16:43:58 -03:00
Belen Curcio 9b98e3cac9 missing classes 2017-11-07 15:20:14 -03:00
Chi Vinh Le 4f89c1e1c3 Add some comments and description 2017-11-07 17:50:56 +01:00
Chi Vinh Le c3e551deb5 Disable bs for branches 2017-11-07 17:48:12 +01:00
Chi Vinh Le 0678ea0344 Small tweak 2017-11-07 17:07:50 +01:00
Chi Vinh Le b09b56bd24 Temporarily enable browserstack 2017-11-07 16:52:27 +01:00
Chi Vinh Le 2a0f70f084 Clean DB before serve 2017-11-07 16:42:37 +01:00
Kiwi bf2e11ef9a Merge branch 'master' into e2e-v2 2017-11-07 16:29:51 +01:00
Chi Vinh Le 0fc810a7b1 e2e v2 2017-11-07 16:21:09 +01:00
Belen Curcio 918ad915b8 Tests 2017-11-06 23:53:33 -03:00
Belen Curcio d51b6b31f6 Adding missing classes and proptypes 2017-11-06 23:53:19 -03:00
Belén Curcio e88445beac Merge branch 'master' into user-pending 2017-11-06 13:48:26 -03:00
Belen Curcio 33be7531a0 Merge branch 'master' of github.com:coralproject/talk 2017-11-06 12:58:15 -03:00
Devon Jue 2131638f48 undo reject comment on stream 2017-11-04 17:17:30 -07:00
Kim Gardner 39a980b22f Merge pull request #1146 from coralproject/isStaff
Use isStaff instead
2017-11-01 17:38:37 +00:00
Chi Vinh Le ce0b63fe75 Use isStaff instead 2017-11-01 13:29:04 +01:00
Kim Gardner c0cb641df3 Merge branch 'master' into user-pending 2017-11-01 11:27:04 +00:00
Kiwi cee68ae471 Merge pull request #1142 from PepeFranco/reportedComments
Reported comments
2017-11-01 12:17:25 +01:00
Kiwi 33cd783b37 Merge branch 'master' into reportedComments 2017-11-01 12:10:39 +01:00
Kiwi 82ef16a4ee Merge pull request #1144 from blackcathacker/queue_shortcuts
add numbered shortcuts for mod queue
2017-11-01 12:10:17 +01:00
Kiwi 736ab6066f Merge branch 'master' into reportedComments 2017-11-01 12:06:34 +01:00
Kiwi 3327604a58 Merge branch 'master' into queue_shortcuts 2017-11-01 12:04:03 +01:00
Kiwi 0c3cfd21a9 Merge pull request #1143 from blackcathacker/staff_badge
show staff instead of user badge when reported by staff
2017-11-01 11:59:56 +01:00
blackcathacker 903e70d641 updates per review 2017-10-31 17:10:25 -07:00
blackcathacker 21f6caa942 cleaner method chain per review 2017-10-31 16:50:35 -07:00
PepeFranco f70ccf641a Fixed lint issue 2017-10-31 13:29:44 -06:00
PepeFranco dd4e3d7ec8 Merge branch 'reportedComments' of https://github.com/PepeFranco/talk into reportedComments 2017-10-31 13:00:05 -06:00
PepeFranco 886a468993 Reverting comment changes 2017-10-31 12:56:32 -06:00
PepeFranco de0dad6243 Merge branch 'master' of https://github.com/coralproject/talk into reportedComments
Updating
2017-10-31 12:49:44 -06:00
Kiwi 7226c475e3 Merge branch 'master' into user-pending 2017-10-31 19:25:51 +01:00
Kim Gardner 173c9262d1 Merge branch 'master' into queue_shortcuts 2017-10-31 17:18:59 +00:00
Kim Gardner 5e7ee344ec Merge branch 'master' into staff_badge 2017-10-31 17:18:54 +00:00
Kim Gardner b2d0c58a72 Merge branch 'master' into reportedComments 2017-10-31 17:12:02 +00:00
Kiwi b34b033a18 Merge pull request #1139 from coralproject/bs-stabilize
Stabilize browserstack tests
2017-10-31 17:47:50 +01:00
Chi Vinh Le 4195d8b419 Merge branch 'bs-stabilize' of ssh://github.com/coralproject/talk into bs-stabilize 2017-10-31 17:34:59 +01:00
Chi Vinh Le bfb2da519f Exit code can be negative 2017-10-31 17:34:28 +01:00
Chi Vinh Le 8821c0aa5c Typos 2017-10-31 17:33:44 +01:00
Kiwi a56031ac47 Merge branch 'master' into bs-stabilize 2017-10-31 17:13:25 +01:00
Wyatt Johnson a3eeec34df Merge pull request #1137 from blackcathacker/premod_setting
Send user an email when they are banned #1050
2017-10-31 10:06:00 -06:00
Kim Gardner c4ad667788 Merge branch 'master' into user-pending 2017-10-31 16:03:07 +00:00
Wyatt Johnson d20666adb9 Update users.js
Prefix added by mailer service
2017-10-31 10:00:47 -06:00
Chi Vinh Le 96b44b2b99 Prefix env variables 2017-10-31 16:39:41 +01:00
Wyatt Johnson b92b4027b0 Merge branch 'master' into premod_setting 2017-10-31 09:32:43 -06:00
Jose Franco f1423abdea Merge branch 'master' into reportedComments 2017-10-31 09:31:32 -06:00
Chi Vinh Le c31e6347d0 Sleep between retries 2017-10-31 16:29:32 +01:00
Chi Vinh Le 48179b413c Merge branch 'bs-stabilize' of ssh://github.com/coralproject/talk into bs-stabilize 2017-10-31 16:25:24 +01:00
Kiwi c955fcd29e Merge branch 'master' into bs-stabilize 2017-10-31 16:25:18 +01:00
Kim Gardner 457322e3d0 Merge pull request #1145 from coralproject/readme-updates
Readme updates
2017-10-31 14:40:53 +00:00
Kim Gardner 9ba8cbcbe1 Fix logo link 2017-10-31 14:30:32 +00:00
Kim Gardner 93363a0650 Remove indenting 2017-10-31 14:27:38 +00:00
Chi Vinh Le 7f442ce91e Let MAX_RETRIES be customizable 2017-10-31 14:58:40 +01:00
Chi Vinh Le 42f0d76d98 Add retry number to console outpu 2017-10-31 14:58:25 +01:00
Chi Vinh Le 1578316363 Retry browsers when failed, print summary 2017-10-31 14:25:58 +01:00
Kim Gardner 5c033dbfdf Tweaks 2017-10-31 11:40:33 +00:00
Kim Gardner 3cdf2a3118 Formatting 2017-10-31 11:31:13 +00:00
Kim Gardner 4e5e989d22 Update one-click directions 2017-10-31 11:25:22 +00:00
Kim Gardner 62660ed144 Fix header 2017-10-31 11:18:24 +00:00
Kim Gardner 2d44f7abf4 Spruce up README 2017-10-31 11:12:14 +00:00
Kim Gardner ea98f0275d Merge branch 'master' into premod_setting 2017-10-31 10:35:44 +00:00
blackcathacker 07e6c15c3a add numbered shortcuts for mod queue 2017-10-30 23:08:33 -07:00
blackcathacker 05e91129f4 show staff instead of user badge when reported by staff 2017-10-30 22:16:59 -07:00
PepeFranco 350e679abf Added check for user & comments 2017-10-30 16:58:51 -06:00
PepeFranco ae07dfb2cd Added check for user & comments 2017-10-30 16:56:52 -06:00
Chi Vinh Le 88d012755c Always use windows 10 2017-10-30 23:16:23 +01:00
Chi Vinh Le 0cdefa0066 Fix wrong typed characters 2017-10-30 21:52:36 +01:00
Chi Vinh Le e4688f9876 Pause to let iframe load 2017-10-30 19:08:42 +01:00
Chi Vinh Le e091fa552a Upgrade selenium standalone 2017-10-30 17:02:20 +01:00
Chi Vinh Le 53b1104cf8 Add little pause waiting for popup to open 2017-10-30 16:09:16 +01:00
Chi Vinh Le 975fe550e0 Harmonize local chrome headless window-size 2017-10-30 16:08:03 +01:00
Chi Vinh Le 8adff14263 Reactivate e2e on ci 2017-10-30 15:53:52 +01:00
Kiwi 5f07d0256c Merge branch 'master' into bs-stabilize 2017-10-30 15:40:17 +01:00
Kim Gardner f573504a3c Merge pull request #1141 from coralproject/update-version
Update version number to be correct
2017-10-30 14:34:26 +00:00
Kim Gardner 8c0118106b Update version number to be correct 2017-10-30 14:24:15 +00:00
Kiwi 4ce720e510 Merge branch 'master' into bs-stabilize 2017-10-30 14:46:32 +01:00
Kim Gardner 81c669d63f Merge branch 'master' into user-pending 2017-10-30 13:34:09 +00:00
Chi Vinh Le 97a8f95b93 Use win10 for ie browsers 2017-10-30 14:25:18 +01:00
Kim Gardner 7bf114c01a Merge branch 'master' into premod_setting 2017-10-30 13:25:14 +00:00
Kim Gardner 6460cbd536 Merge pull request #1138 from blackcathacker/disable_report
disable report button when comment already reported
2017-10-30 13:24:10 +00:00
Chi Vinh Le 05b326b91c Add comments 2017-10-30 14:14:49 +01:00
Chi Vinh Le 9af206da1a Correct echo output 2017-10-30 14:08:13 +01:00
Chi Vinh Le 0c3a9db443 Add more console logs 2017-10-30 13:52:11 +01:00
Chi Vinh Le 511f4f0975 Refactor 2017-10-30 13:26:50 +01:00
Chi Vinh Le 95545a0e7d Merge branch 'bs-stabilize' of ssh://github.com/coralproject/talk into bs-stabilize 2017-10-30 13:13:23 +01:00
Chi Vinh Le 12a71fa117 Wait before click 2017-10-30 13:11:41 +01:00
Belen Curcio 302d30cde1 Adding missing classnames and proptypes, plus e2e testing covering userstatus 2017-10-30 08:54:32 -03:00
Kiwi 3da4a70442 Merge branch 'master' into bs-stabilize 2017-10-30 12:50:15 +01:00
Belen Curcio 6d7afc7bbc Adding missing classes and props 2017-10-30 08:07:03 -03:00
Belen Curcio b6786f614e Adding missing props 2017-10-30 07:56:51 -03:00
Belen Curcio a6a903c459 e2e tests 2017-10-30 07:52:08 -03:00
Belen Curcio 34b58779e8 User PENDING status should not be able to post 2017-10-30 07:04:39 -03:00
blackcathacker 82a332c787 disable report button when comment already reported 2017-10-29 19:48:42 -07:00
blackcathacker bfe82218ed Send user an email when they are banned #1050 2017-10-29 18:48:15 -07:00
Chi Vinh Le 5f5c64870a Stabilize e2e 2017-10-27 19:00:48 +02:00
Chi Vinh Le ad4a5595f9 Enable screenshot on failure for bs 2017-10-27 13:19:00 +02:00
Wyatt Johnson b7137fbcd4 Merge pull request #1132 from coralproject/docker-regression
Docker Regression Fix
2017-10-26 09:43:15 -06:00
Chi Vinh Le b84daf0422 Set resolution to 1600x1200 bs 2017-10-26 17:30:55 +02:00
Wyatt Johnson 4089d09681 fix regression missing yarn cache clean 2017-10-26 09:19:29 -06:00
Kiwi a7eb588f7f Merge pull request #1122 from coralproject/onbuild
Docker Updates
2017-10-26 14:40:45 +02:00
Kiwi cd92dbf682 Merge branch 'master' into onbuild 2017-10-26 14:33:02 +02:00
Kiwi 89ab71eb1d Merge pull request #1130 from coralproject/tests-e2e
Missing Classes and testing Admin Drawer
2017-10-26 14:31:58 +02:00
Kiwi c1cfe3b200 Merge branch 'master' into onbuild 2017-10-26 14:28:59 +02:00
Kiwi d7ed679384 Merge branch 'master' into tests-e2e 2017-10-26 14:20:53 +02:00
Wyatt Johnson 7446712109 Merge pull request #1131 from coralproject/wyattjoh-patch-1
Disable e2e
2017-10-25 14:10:39 -06:00
Wyatt Johnson 6647e22d1c Update circle.yml 2017-10-25 14:05:04 -06:00
Belen Curcio 59acdc5c02 new e2e test 2017-10-25 16:53:18 -03:00
Belen Curcio b06ae9001e Adding missing classes 2017-10-25 16:31:46 -03:00
Belén Curcio 1e718532f3 Merge pull request #1129 from coralproject/community-pagination-
Adding a pause after admin login - Cross browser compat [E2E]
2017-10-25 16:05:27 -03:00
Belén Curcio 6d797b44c8 Merge branch 'master' into community-pagination- 2017-10-25 15:59:33 -03:00
Belen Curcio dbd7f26311 Adding pause after login 2017-10-25 15:57:57 -03:00
Kim Gardner 11f774ecab Merge pull request #1123 from coralproject/community-pagination-
Community/Stories Refactor and Paginate Component
2017-10-25 19:23:14 +01:00
Chi Vinh Le d472223ee3 Fix/Implement sorting for stories 2017-10-25 19:32:47 +02:00
Chi Vinh Le b4daf8fc98 Move searchValue to Redux 2017-10-25 19:19:59 +02:00
Chi Vinh Le e41c224e3d Remove unused 2017-10-25 19:14:25 +02:00
Chi Vinh Le 20b5525c48 Refactor and fix query 2017-10-25 19:07:14 +02:00
Chi Vinh Le 23da613f2b Declaratively set page 2017-10-25 18:02:18 +02:00
Chi Vinh Le df079d29bd Set current page declaratively for People 2017-10-25 17:38:58 +02:00
Kiwi e782df815b Merge branch 'master' into community-pagination- 2017-10-25 17:09:34 +02:00
Kiwi 9bfc17d332 Merge pull request #1128 from coralproject/viewing-options-bug
Viewing Options Styling bug
2017-10-25 17:09:21 +02:00
Chi Vinh Le 3ff47dc610 Fix ci 2017-10-25 16:47:51 +02:00
Kim Gardner ed929fa2c6 Merge branch 'master' into viewing-options-bug 2017-10-25 14:32:07 +01:00
Kim Gardner 369e974a0c Merge branch 'master' into community-pagination- 2017-10-25 14:32:03 +01:00
Kim Gardner 2a90956a1d Merge pull request #1127 from coralproject/iefixes
IE & Edge fixes
2017-10-25 14:31:46 +01:00
Belen Curcio 833922f0aa Missing reference to the dropdownContainer class 2017-10-25 09:35:08 -03:00
Kiwi f6f9d380f1 Merge branch 'master' into iefixes 2017-10-25 14:22:06 +02:00
Chi Vinh Le 823bf18335 Add edge to ci 2017-10-25 14:19:13 +02:00
Chi Vinh Le 16bf887161 Add ie to ci testing 2017-10-25 13:06:00 +02:00
Chi Vinh Le 27eb159a75 Add special popup handling for ie 11 2017-10-25 13:04:41 +02:00
Wyatt Johnson 04540c658e Merge branch 'master' into community-pagination- 2017-10-24 11:30:07 -06:00
Kim Gardner 327c87cda6 Merge pull request #1126 from coralproject/mailer-fix
Mail Service Fix
2017-10-24 18:17:15 +01:00
Kim Gardner b43b84acff Merge branch 'master' into community-pagination- 2017-10-24 18:05:53 +01:00
Wyatt Johnson 1dec169520 added port parsing for smtp 2017-10-24 11:03:15 -06:00
Kim Gardner edce550587 Merge pull request #1099 from coralproject/email-verification
Email Verification Resend
2017-10-24 17:53:19 +01:00
Chi Vinh Le 934b630ce2 Simplified Spinner for IE and Edge for Spinner (using css hacks) 2017-10-24 18:47:55 +02:00
Belen Curcio 812483931d ref 2017-10-24 13:13:44 -03:00
Wyatt Johnson 01c5bc4e26 Merge branch 'master' into email-verification 2017-10-24 10:09:52 -06:00
Wyatt Johnson dd7ca9fd0c added docs 2017-10-24 10:08:03 -06:00
Belen Curcio 7ef9e2783b Initial e2e 2017-10-24 12:58:27 -03:00
Belen Curcio be994d033b Adding classes 2017-10-24 12:58:15 -03:00
Belen Curcio cd0ce14254 Merge branch 'community-pagination-' of github.com:coralproject/talk into community-pagination- 2017-10-24 12:32:12 -03:00
Belen Curcio a0929fd773 Updated tests 2017-10-24 12:30:07 -03:00
Belén Curcio adc06911f3 Merge branch 'master' into community-pagination- 2017-10-24 12:25:12 -03:00
Chi Vinh Le ca1ce9ba76 Dont cache auth 2017-10-24 17:23:10 +02:00
Belen Curcio f3bf9d28a7 Search Value 2017-10-24 11:47:18 -03:00
Belen Curcio 61108337cc Even tinier 2017-10-24 11:42:21 -03:00
Belen Curcio 2aed5d1224 Merge branch 'community-pagination-' of github.com:coralproject/talk into community-pagination- 2017-10-24 11:36:11 -03:00
Belen Curcio 3777b4b1ce Filter Streams fully working 2017-10-24 11:35:27 -03:00
Belen Curcio 55b2208a49 Pagination and refactor for Stories 2017-10-24 11:29:17 -03:00
Kim Gardner 5037af9100 Merge pull request #1125 from coralproject/userDetailBugs
Fix UserDetail bugs
2017-10-24 14:49:27 +01:00
Belen Curcio fed6654f52 Support pagination for search 2017-10-24 10:45:25 -03:00
Kim Gardner 7ba42f059c Merge branch 'master' into userDetailBugs 2017-10-24 14:30:09 +01:00
Kim Gardner cf2746fc28 Merge pull request #1124 from coralproject/fix-doc-formatting
Fix formatting typo in docs
2017-10-24 14:23:08 +01:00
Chi Vinh Le b7b9da9509 Change fetchPolicy 2017-10-24 15:16:45 +02:00
Kim Gardner 24ec898a15 Fix formatting 2017-10-24 14:14:26 +01:00
Chi Vinh Le 46359b4a1b Show errors 2017-10-24 14:49:32 +02:00
Kim Gardner 1f170c1dca Merge branch 'master' into onbuild 2017-10-24 13:20:24 +01:00
Chi Vinh Le b189c9d2b0 Add cursor pointer and increase clickable area 2017-10-24 12:08:46 +02:00
Kiwi 85890b4e6e Merge branch 'master' into email-verification 2017-10-24 12:01:59 +02:00
Belén Curcio 6d3cdb176e Merge branch 'master' into community-pagination- 2017-10-24 00:23:53 -03:00
Belen Curcio 38abf63cc9 removing unused files 2017-10-24 00:21:26 -03:00
Belen Curcio 34334b8152 Pagination only shows when there are results to show 2017-10-24 00:18:03 -03:00
Belen Curcio 0b973f24ff Replacing paginate from Stories 2017-10-24 00:14:47 -03:00
Belen Curcio abff1c763a More styling 2017-10-24 00:12:18 -03:00
Belen Curcio 9f4a913655 Passing props 2017-10-24 00:03:35 -03:00
Belen Curcio d363c977dc Refactor 2017-10-23 23:47:43 -03:00
Belen Curcio f004573ed2 Replacing Pagination Component 2017-10-23 23:47:05 -03:00
Kim Gardner fb9419f2ad Merge pull request #1098 from coralproject/talk-product-guide-features
Talk Product Guide - features and configuration
2017-10-23 19:41:58 +01:00
Wyatt Johnson 9217239caf Merge branch 'master' into onbuild 2017-10-23 12:33:56 -06:00
Kim Gardner 9fc0fc37db Fix merge conflicts 2017-10-23 19:30:36 +01:00
Kim Gardner c442b8bb70 Merge branch 'master' into talk-product-guide-features 2017-10-23 19:27:05 +01:00
Kim Gardner e1f897ec17 Merge pull request #1104 from facuesr/bulk-approve-reject-actions
Bulk approve/reject actions for Moderators
2017-10-23 19:26:00 +01:00
Kiwi 1803c740fc Merge branch 'master' into bulk-approve-reject-actions 2017-10-23 19:29:24 +02:00
Wyatt Johnson fac028c22b update to docker build process 2017-10-23 10:50:29 -06:00
Chi Vinh Le d75ae3aca8 Revive resend verification feature 2017-10-23 18:46:41 +02:00
Kiwi a3216dd33e Merge branch 'master' into email-verification 2017-10-23 18:45:11 +02:00
Kim Gardner 6b7ceb99c9 Merge branch 'master' into talk-product-guide-features 2017-10-23 17:00:32 +01:00
Kim Gardner 4ae9928224 Merge pull request #1121 from coralproject/config-fix
Config Fix
2017-10-23 16:58:36 +01:00
Wyatt Johnson dae8dc0509 patched config bug 2017-10-23 09:51:34 -06:00
Kim Gardner 017d560421 Merge branch 'master' into bulk-approve-reject-actions 2017-10-23 15:52:20 +01:00
Kiwi 3f59ed1e46 Merge branch 'master' into email-verification 2017-10-23 11:56:40 +02:00
Facu 9c38bab83b notify error messages 2017-10-20 17:01:52 -03:00
Wyatt Johnson a9cb206415 formatting 2017-10-20 13:14:00 -06:00
Wyatt Johnson c1b954965f Fixed incorrect plugin naming 2017-10-20 11:40:55 -06:00
Kim Gardner e0713a5ec4 Update auth section 2017-10-20 17:56:24 +01:00
Kim Gardner 0ee56fe8d3 Merge branch 'master' into talk-product-guide-features 2017-10-20 17:53:31 +01:00
Kim Gardner 88390f13c7 Merge pull request #1119 from coralproject/turn-off-flagged-edited-notification
Turn off notifications for comments flagged and edited
2017-10-20 17:02:04 +01:00
Chi Vinh Le 7e709ec41d Merge branch 'turn-off-flagged-edited-notification' of ssh://github.com/coralproject/talk into turn-off-flagged-edited-notification 2017-10-20 17:56:07 +02:00
Chi Vinh Le 1bfecdd77c Don't show notification when featuring comment 2017-10-20 17:55:37 +02:00
Kim Gardner 487e1e34db Merge branch 'master' into talk-product-guide-features 2017-10-20 16:48:49 +01:00
Kiwi c054992741 Merge branch 'master' into turn-off-flagged-edited-notification 2017-10-20 17:33:09 +02:00
Kim Gardner 12b83d3904 Merge pull request #1120 from coralproject/disable-ie-e2e
Temporarily disable IE in browserstack ci
2017-10-20 16:30:27 +01:00
Kim Gardner 7ebba3018f Merge branch 'talk-product-guide-features' of git+ssh://github.com/coralproject/talk into talk-product-guide-features 2017-10-20 16:26:23 +01:00
Kim Gardner 0e089b8ff8 Merge branch 'master' into talk-product-guide-features 2017-10-20 16:25:08 +01:00
Chi Vinh Le 5695599f74 Temporarily disable IE in browserstack ci 2017-10-20 17:23:31 +02:00
Chi Vinh Le bef3e3e33c Turn off notifications for flagged and edited 2017-10-20 17:19:44 +02:00
Kiwi 8dbd1789e0 Merge pull request #1118 from coralproject/improve-e2e
Disable network logging
2017-10-20 15:01:03 +02:00
Chi Vinh Le ee548d7180 Disable network logging 2017-10-20 14:45:12 +02:00
Kim Gardner 8ce9f2d4bb Clean up docs, fix links, remove Tutorials section for now 2017-10-20 11:28:03 +01:00
Kim Gardner 76f9e1487c Merge branch 'master' into email-verification 2017-10-19 21:55:14 +01:00
Kim Gardner e729da8e01 Merge branch 'master' into talk-product-guide-features 2017-10-19 21:54:50 +01:00
Facu 011d8830fb Merge branch 'master' into bulk-approve-reject-actions 2017-10-19 14:12:08 -03:00
Kim Gardner 5713e2e2f6 Merge pull request #1116 from coralproject/no-comments
No Comments Text
2017-10-19 16:16:21 +01:00
Belen Curcio f23a5132d6 Missing proptypes 2017-10-19 11:35:40 -03:00
Belen Curcio 101b6cbe59 Missing proptypes 2017-10-19 11:26:22 -03:00
Belen Curcio 7494752019 Translations, Proptypes, NoComments Component 2017-10-19 11:20:09 -03:00
Belen Curcio 11999d751a No inline styling 2017-10-19 11:01:27 -03:00
Belen Curcio 2a85b9fdd2 Adding missing proptypes 2017-10-19 10:58:24 -03:00
Belen Curcio fdddd5f8af Adding missing proptypes 2017-10-19 10:44:17 -03:00
Kim Gardner 6086bfd3cf Merge branch 'master' into talk-product-guide-features 2017-10-19 12:00:03 +01:00
Kim Gardner 2a8dc3b506 Merge pull request #1090 from coralproject/e2e-browserstack
E2e browserstack
2017-10-19 11:58:53 +01:00
Kim Gardner 1a31d9eb97 Merge branch 'master' into email-verification 2017-10-19 11:49:10 +01:00
Kim Gardner bceebca39f Merge branch 'master' into bulk-approve-reject-actions 2017-10-19 11:48:58 +01:00
Kim Gardner 1df48e27f1 Fix merge conflicts 2017-10-19 11:45:59 +01:00
Kim Gardner 5da8475806 Merge pull request #1115 from coralproject/settings-fix
Setup fixes
2017-10-18 23:21:57 +01:00
Wyatt Johnson 1dea6267d7 fixes to the toObject, added test 2017-10-18 16:07:20 -06:00
Kim Gardner 8d5d73312d Merge branch 'master' into talk-product-guide-features 2017-10-18 22:42:36 +01:00
Kim Gardner 3a18cd88ad Merge branch 'master' into bulk-approve-reject-actions 2017-10-18 22:42:31 +01:00
Kim Gardner a1ee09ad9b Merge pull request #1113 from coralproject/snyk
Replacing Snyk with NSP
2017-10-18 22:22:18 +01:00
Wyatt Johnson ae09d5c72e replaced snyk with nsp 2017-10-18 15:09:19 -06:00
Wyatt Johnson 2965877346 fix issues detected by snyk 2017-10-18 14:57:54 -06:00
Wyatt Johnson 0b9c058ad8 fixed package.json/yarn.lock 2017-10-18 14:53:51 -06:00
Wyatt Johnson 5657fde7dc Merge branch 'master' into e2e-browserstack 2017-10-18 13:25:59 -06:00
Wyatt Johnson a69dd02e52 adjusted the circle.yml 2017-10-18 13:16:21 -06:00
Kim Gardner 71cf565018 Merge branch 'master' into bulk-approve-reject-actions 2017-10-18 19:57:28 +01:00
Kim Gardner b4865546d4 Merge pull request #1112 from coralproject/my-profile-tab-fix
Load username from graph and not auth
2017-10-18 19:31:07 +01:00
Wyatt Johnson b97b5e97f2 load username from graph and not auth 2017-10-18 12:23:16 -06:00
Belén Curcio 0265b9bc56 Merge branch 'master' into bulk-approve-reject-actions 2017-10-18 14:05:19 -03:00
Kiwi f06e171def Merge branch 'master' into e2e-browserstack 2017-10-18 18:45:22 +02:00
Kiwi 9930bf5e7a Merge pull request #1111 from coralproject/snyk-fix-3586ed18
[Snyk] Fix for 1 vulnerable dependency path
2017-10-18 18:45:03 +02:00
snyk-bot 2227ec423f fix: package.json & .snyk to reduce vulnerabilities
The following vulnerabilities are ignored:
- https://snyk.io/vuln/npm:tunnel-agent:20170305

Latest report for coralproject/talk:
https://snyk.io/test/github/coralproject/talk
2017-10-18 16:36:12 +00:00
Chi Vinh Le 8fafa93cf5 Fix package.json 2017-10-18 23:35:54 +07:00
Chi Vinh Le 2991fe4ca5 Pingelig 2017-10-18 23:27:46 +07:00
Chi Vinh Le 1126ab48ad Add edge version to comment 2017-10-18 23:26:16 +07:00
Chi Vinh Le 91f6c5a088 Remove edge from ci testing 2017-10-18 23:24:46 +07:00
Chi Vinh Le c8325c91a4 Merge branch 'master' into e2e-browserstack
Conflicts:
	package.json
2017-10-18 23:23:47 +07:00
Chi Vinh Le 039c1b82d1 Merge branch 'e2e-browserstack' of ssh://github.com/coralproject/talk into e2e-browserstack 2017-10-18 23:18:09 +07:00
Chi Vinh Le 4fbb0678e0 Stabilize browserstack testing 2017-10-18 23:17:14 +07:00
Kiwi fb82ef7faf Merge pull request #1110 from coralproject/snyk-fix-d774546f
[Snyk] Fix for 4 vulnerable dependency paths
2017-10-18 17:58:20 +02:00
snyk-bot b362da56ab fix: package.json & .snyk to reduce vulnerabilities
The following vulnerabilities are ignored:
- https://snyk.io/vuln/npm:marked:20170907
- https://snyk.io/vuln/npm:shelljs:20140723

Latest report for coralproject/talk:
https://snyk.io/test/github/coralproject/talk
2017-10-18 15:49:54 +00:00
Wyatt Johnson 5f9f712a9b Merge branch 'master' into email-verification 2017-10-18 09:34:32 -06:00
Kim Gardner 94d253fdbc Merge branch 'master' into bulk-approve-reject-actions 2017-10-18 14:18:41 +01:00
Belen Curcio 86e5e5e955 Adding wait for a button selector 2017-10-18 09:19:32 -03:00
Belen Curcio c3b2eb5a98 Using respect instead of like reaction 2017-10-18 09:17:05 -03:00
Belén Curcio 627ae50fda Merge branch 'master' into e2e-browserstack 2017-10-18 09:02:00 -03:00
Belen Curcio 367c2df3da Modifying test conf 2017-10-18 08:53:25 -03:00
Belen Curcio 14a8fcd475 Removing test output 2017-10-18 08:51:38 -03:00
Kim Gardner 82d0d427ec Merge pull request #1101 from coralproject/bump-version-3-7-0
Update version 3.7.0
2017-10-18 11:12:47 +01:00
Facu 4b068b22b7 Merge branch 'master' into bulk-approve-reject-actions 2017-10-17 17:10:22 -03:00
Belen Curcio 2c757e9d57 Missing classes 2017-10-17 15:18:53 -03:00
Belen Curcio 8633a0f457 Missing classes 2017-10-17 14:54:06 -03:00
Chi Vinh Le a7b33fdc3e Typos 2017-10-17 22:49:03 +07:00
Chi Vinh Le ce131dd067 Run all browsers before failing 2017-10-17 22:48:00 +07:00
Chi Vinh Le afb591d990 Quote path 2017-10-17 22:29:31 +07:00
Chi Vinh Le fac0f53ea8 Sort reports by browser 2017-10-17 22:24:45 +07:00
Chi Vinh Le 89feea70fd Only run browserstack on master 2017-10-17 22:22:54 +07:00
Chi Vinh Le 77dae9922c Integrate reports with circle ci 2017-10-17 21:59:50 +07:00
Chi Vinh Le 427c6e10a4 Integrate browserstack into ci 2017-10-17 21:38:50 +07:00
Chi Vinh Le 30fe43624f Use better env names 2017-10-17 20:53:50 +07:00
Chi Vinh Le 2723be2eb9 Integrate local e2e in CI 2017-10-17 20:10:38 +07:00
Chi Vinh Le 1542888080 yarn e2e-local is now e2e, add new yarn e2e-browserstack 2017-10-17 19:34:55 +07:00
Chi Vinh Le 3a58088420 Fix paths, add headless env 2017-10-17 19:29:46 +07:00
Chi Vinh Le db91e2a27a Env test for e2e-local 2017-10-17 18:54:53 +07:00
Kim Gardner 39a2092310 Add faq 2017-10-17 12:32:56 +01:00
Kim Gardner a586756ac9 Add FAQ and Tutorial sections 2017-10-17 12:27:33 +01:00
Chi Vinh Le 5197cab2b4 Add tags 2017-10-17 18:26:43 +07:00
Chi Vinh Le 8cf04c5c66 Use sections for install e2e 2017-10-17 16:58:50 +07:00
Kim Gardner 3a8ed3033a Fix styling 2017-10-17 10:28:56 +01:00
Chi Vinh Le 7ffc7a76f5 Unify names 2017-10-17 16:15:53 +07:00
Kim Gardner 988cb870bb Global Configuration docs 2017-10-17 10:13:40 +01:00
Chi Vinh Le 343f009150 Refactor serve 2017-10-17 15:57:34 +07:00
Kim Gardner a167b6ce2c Add Stream Configuration docs 2017-10-16 18:20:25 +01:00
Chi Vinh Le 94f0205d9c Unused config 2017-10-16 22:31:40 +07:00
Chi Vinh Le f38e718373 First isolated e2e 2017-10-16 22:27:49 +07:00
Kim Gardner c8f432268b Add Nav for Configuring Talk section 2017-10-14 18:41:50 +01:00
Kim Gardner 759338dc02 Added more Moderator Features 2017-10-14 18:36:17 +01:00
Kim Gardner aa0c41c342 Add section Moderator Features 2017-10-14 18:25:41 +01:00
Kim Gardner 840f3f7145 Merge branch 'master' into bump-version-3-7-0 2017-10-14 17:46:21 +01:00
Kim Gardner ca2c2469bf Merge branch 'master' into talk-product-guide-features 2017-10-14 17:46:10 +01:00
Kim Gardner 606871e4b7 Merge branch 'master' into e2e-browserstack 2017-10-14 17:46:00 +01:00
Kim Gardner 1a8f954707 Merge pull request #1106 from coralproject/reject-rate-fix
Reject Rate Fixes
2017-10-14 17:09:05 +01:00
Kim Gardner 20cd38e47b Merge branch 'master' into reject-rate-fix 2017-10-14 16:58:47 +01:00
Belen Curcio 70d92978c0 Adding admin tests 2017-10-13 21:14:27 -03:00
Belen Curcio b750d9e9a9 Output path 2017-10-13 21:14:10 -03:00
Belen Curcio 887dd3825c Missing propTypes and classes 2017-10-13 21:13:59 -03:00
Belen Curcio adae679bc7 Merge branch 'e2e-browserstack' of github.com:coralproject/talk into e2e-browserstack 2017-10-13 21:12:26 -03:00
Belen Curcio da8dee175d Adding admin tests 2017-10-13 21:07:58 -03:00
Belen Curcio 316971302b Using testData from Install 2017-10-13 21:07:39 -03:00
Belen Curcio bdbffba902 Missing propTypes and classes 2017-10-13 21:07:09 -03:00
Belen Curcio 703fabf586 Adding globals 2017-10-13 21:06:56 -03:00
Wyatt Johnson 2ec1d3fa51 Reject Rate Fixes
- Corrected query to select all statuses (default was accepted/none)
- Fixed up some missing prop-types
- Improved count code
2017-10-13 11:26:02 -06:00
Kiwi 93f2c95700 Merge pull request #1082 from coralproject/dropdown
Dropdown and Option Component
2017-10-13 19:11:48 +02:00
Chi Vinh Le fce1d60d09 Increase contrast in viewing options 2017-10-14 00:06:18 +07:00
Chi Vinh Le f9967dbc48 Increase focus contrast 2017-10-13 23:47:53 +07:00
Chi Vinh Le 4fdb2d5af6 Merge branch 'dropdown' of ssh://github.com/coralproject/talk into dropdown 2017-10-13 23:22:59 +07:00
Chi Vinh Le 00512bfaf0 Support arrow keys 2017-10-13 23:22:07 +07:00
Belén Curcio 37148f69d5 Merge branch 'master' into dropdown 2017-10-13 13:02:56 -03:00
Chi Vinh Le 08d6eadbb7 Fix Stories Dropdown handlers 2017-10-13 22:53:53 +07:00
Kim Gardner 5dd08d84e5 Added Commenter Features section 2017-10-13 16:48:21 +01:00
Chi Vinh Le 10cba651e6 Better accessbility 2017-10-13 22:39:53 +07:00
Kim Gardner 06d0da9286 Reorganize file order and reinstate h2s 2017-10-13 15:50:13 +01:00
Facu 1660d6c1d1 Merge remote-tracking branch 'origin/master' into bulk-approve-reject-actions 2017-10-13 11:46:26 -03:00
Facu 9d36426a1b format UserDetail css 2017-10-13 11:41:47 -03:00
Kim Gardner b721b4e10a Merge branch 'master' into talk-product-guide-features 2017-10-13 15:18:08 +01:00
Belén Curcio 8e72381081 Merge branch 'master' into e2e-browserstack 2017-10-13 10:56:37 -03:00
Belen Curcio 0dfff2ce53 Nightwatch Config global timeout 2017-10-13 10:55:02 -03:00
Belen Curcio 54971f37ad Adding Install tests 2017-10-13 10:54:26 -03:00
Belen Curcio cac6eecde2 Missing propTypes and classes 2017-10-13 10:53:44 -03:00
Kim Gardner 3efd86a4cb Update version 3.7.0 2017-10-13 14:38:34 +01:00
Kiwi 299b083816 Merge pull request #1091 from Goyapa/dismiss-shortcuts-help-menu
Fix Shortcuts help menu doesn't dismiss forever.
2017-10-13 15:21:58 +02:00
Kiwi 7d2a0cf7cc Merge branch 'master' into dismiss-shortcuts-help-menu 2017-10-13 15:16:48 +02:00
Belen Curcio 7c02f21210 Removed yarn error 2017-10-13 10:01:42 -03:00
Belen Curcio a7ad7a2267 Updated drivers 2017-10-13 10:01:27 -03:00
Belen Curcio f0ac56221c Updated yarn 2017-10-13 09:59:27 -03:00
Belen Curcio cd45bf6042 Adding standalone selenium in case someone wants to run then locally 2017-10-13 09:58:48 -03:00
Belen Curcio 895eb5a69a Adding local nightwatch config 2017-10-13 09:58:19 -03:00
Michael Macherey f6be48a4a8 Merge remote-tracking branch 'origin/master' into dismiss-shortcuts-help-menu 2017-10-13 14:05:04 +02:00
Michael Macherey 2dcab1fb12 add noop function, handle undefined 2017-10-13 14:00:28 +02:00
Belén Curcio d8bce3f4ce Merge branch 'master' into e2e-browserstack 2017-10-13 08:07:21 -03:00
Belen Curcio 8f3aa789f5 Merge branch 'dropdown' of github.com:coralproject/talk into dropdown 2017-10-13 08:04:05 -03:00
Belen Curcio be6b1466c6 render label 2017-10-13 08:03:47 -03:00
Belen Curcio 233bc68128 Merge branch 'master' of github.com:coralproject/talk into e2e-browserstack 2017-10-13 08:02:58 -03:00
Belén Curcio 7fd09c3534 Merge branch 'master' into dropdown 2017-10-13 07:59:17 -03:00
Kiwi 8102ef7157 Merge pull request #1078 from dagjaneiro/cannot-ignore-staff
Cannot ignore staff members
2017-10-13 12:57:02 +02:00
Kiwi 1edf320779 Merge branch 'master' into cannot-ignore-staff 2017-10-13 12:47:55 +02:00
Kiwi d8a443e790 Merge pull request #1100 from coralproject/fix-withMutation-hoc
Prevent calling updators when there is an error
2017-10-13 12:44:40 +02:00
Chi Vinh Le 2fd7829b88 Prevent calling updators when there is an error 2017-10-13 17:33:59 +07:00
Daniel Janeiro 27c6d830d9 Remove error handling code
Remove error handling code since the withMutation HoC already handles
errors for us.
2017-10-13 01:13:53 +01:00
Wyatt Johnson 910acdd52b added cli tools for verifying email address 2017-10-12 15:49:21 -06:00
Wyatt Johnson 675e8fa604 Merge branch 'master' into talk-product-guide-features 2017-10-12 15:38:44 -06:00
Wyatt Johnson 5e74a044f3 Merge branch 'master' into cannot-ignore-staff 2017-10-12 15:38:18 -06:00
Wyatt Johnson 9d5739b396 better support for email verification 2017-10-12 15:27:57 -06:00
Facu e0e481373b bulk approve/reject actions for moderators 2017-10-12 17:59:04 -03:00
Michael Macherey 8e466befb4 Fix Shortcuts help menu doesn't dismiss forever. 2017-10-12 20:30:23 +02:00
Belen Curcio c98cb02a4a Adding dropdown to ViewOptions 2017-10-12 13:52:17 -03:00
Belen Curcio 351ebc9105 Find label based on value 2017-10-12 13:40:43 -03:00
Belen Curcio 27ef2ad0d4 Find label based on value 2017-10-12 13:33:18 -03:00
Belen Curcio 798acaf320 Support for Keyboard and Accesibility 2017-10-12 13:18:07 -03:00
Belen Curcio 21122016da Adding tabIndex to clickable buttons 2017-10-12 13:07:14 -03:00
Belen Curcio c9ae622ec3 merge conflicts 2017-10-12 13:00:16 -03:00
Kim Gardner b5a0483603 Update nav 2017-10-12 16:58:12 +01:00
Kim Gardner 987acb64f5 Merge pull request #1097 from coralproject/configure-styling-fix
Fix configure styling issues
2017-10-12 16:51:43 +01:00
Kim Gardner 43d92e5b76 Merge branch 'master' into configure-styling-fix 2017-10-12 16:27:06 +01:00
Kim Gardner 618b8b5135 Merge pull request #1096 from coralproject/long-usernames
Handle really long usernames in Community > People page
2017-10-12 16:06:26 +01:00
Chi Vinh Le 24d73b2770 Use page objects + one more test 2017-10-12 21:56:56 +07:00
Belen Curcio 36be112744 Keyboard accesible 2017-10-12 11:04:17 -03:00
Kiwi caac76bb3f Merge branch 'master' into configure-styling-fix 2017-10-12 16:04:07 +02:00
Chi Vinh Le 3035ba0bcf Fix configure styling issues 2017-10-12 20:57:34 +07:00
Belén Curcio 562586c130 Merge branch 'master' into long-usernames 2017-10-12 10:32:02 -03:00
Belen Curcio a7064bbfdb Adding missing proptypes and ellipsis 2017-10-12 10:29:23 -03:00
Kim Gardner 1b30327fe0 Merge pull request #1094 from coralproject/change-flagged-usernames-copy
Flagged Usernames --> Reported Usernames
2017-10-12 14:24:49 +01:00
Kim Gardner e1f7d1da99 Merge branch 'master' into change-flagged-usernames-copy 2017-10-12 14:17:35 +01:00
Kim Gardner bbfb4c8ae0 Merge pull request #1095 from coralproject/fix-typo
Fix some typos, copy, styling in Docs
2017-10-12 14:17:25 +01:00
Belén Curcio dbcd0aacb1 Merge branch 'master' into change-flagged-usernames-copy 2017-10-12 10:13:23 -03:00
Belén Curcio b0f6ab2b48 Merge branch 'master' into fix-typo 2017-10-12 10:12:40 -03:00
Belen Curcio 612adb2990 Merge branch 'dropdown' of github.com:coralproject/talk into dropdown 2017-10-12 10:08:43 -03:00
Belen Curcio c4e3904a95 Update 2017-10-12 10:08:21 -03:00
Belén Curcio 0d9d2d4871 Merge branch 'master' into dropdown 2017-10-12 10:07:39 -03:00
Kim Gardner 69acb6d5a0 Fix typos and clean up styling 2017-10-12 14:06:09 +01:00
Kim Gardner 58aff2487a Merge pull request #1093 from coralproject/user-search
User Search Improvements
2017-10-12 13:39:50 +01:00
Kim Gardner 4f72f5d4ae Merge branch 'master' into user-search 2017-10-12 13:25:23 +01:00
Kim Gardner 27c44e942e Merge pull request #1086 from coralproject/count-whitespace-to-char-max
Count leading and trailing whitespace towards char count
2017-10-12 13:22:49 +01:00
Kim Gardner 22bbe5c614 Merge branch 'master' into user-search 2017-10-12 13:15:21 +01:00
Kim Gardner bccce1d9bd Merge branch 'master' into count-whitespace-to-char-max 2017-10-12 13:11:28 +01:00
Kim Gardner a914cf1591 Merge branch 'master' into dropdown 2017-10-12 13:10:25 +01:00
Kim Gardner ba7ee5d327 Merge pull request #1092 from coralproject/snyk-patch
SNYK Patch of yarn.lock
2017-10-12 13:09:51 +01:00
Kim Gardner f035a9d1e9 Flagged Usernames --> Reported Usernames 2017-10-12 13:05:13 +01:00
Kim Gardner 1c6f3b80c4 Merge branch 'master' into snyk-patch 2017-10-12 11:27:58 +01:00
Kim Gardner 1b00cdbea3 Merge pull request #1063 from coralproject/talk-product-guide
Talk Product Guide - part 1
2017-10-12 11:27:02 +01:00
Kiwi 1e41ae9402 Merge branch 'master' into count-whitespace-to-char-max 2017-10-12 10:26:23 +02:00
Wyatt Johnson 86f48cea96 Modified user search to include whole word search 2017-10-11 16:41:09 -06:00
Wyatt Johnson 94f4c57038 patched 2017-10-11 15:38:08 -06:00
Wyatt Johnson 97eee92499 updated docs 2017-10-11 15:32:25 -06:00
Kim Gardner 5dfc5d87ad Merge branch 'master' into dropdown 2017-10-11 17:04:04 +01:00
Chi Vinh Le e4399b734e Use TALK_ROOT_URL, global timeout, other improvements 2017-10-11 21:02:46 +07:00
Kim Gardner 09ecd2a055 Merge branch 'master' into talk-product-guide 2017-10-11 14:20:18 +01:00
Kiwi 1fffa1427d Merge pull request #1089 from coralproject/add-testing-info-to-readme
Small Readme tweaks
2017-10-11 15:03:39 +02:00
Chi Vinh Le cde3c4e17e Move logs to test/e2e 2017-10-11 20:01:27 +07:00
Kim Gardner ac28106251 Add docs on Toxic Comments 2017-10-11 13:56:35 +01:00
Chi Vinh Le 3abbe3119d E2e with nightwatch and browserstack 2017-10-11 19:50:13 +07:00
Kim Gardner 1dd1a0d986 Update Trust details and update nav 2017-10-11 13:43:48 +01:00
Kim Gardner a7d87f4ee1 Add Trust Product Docs 2017-10-11 13:34:15 +01:00
Kim Gardner 025d0cf812 Merge branch 'master' into talk-product-guide 2017-10-11 12:41:24 +01:00
Kim Gardner 8ac93c9785 Merge branch 'master' into count-whitespace-to-char-max 2017-10-11 11:26:50 +01:00
Kim Gardner 1ec71ebd00 Merge branch 'master' into cannot-ignore-staff 2017-10-11 11:26:45 +01:00
Kim Gardner 48d4eeddf3 Merge branch 'master' into dropdown 2017-10-11 11:26:35 +01:00
Kim Gardner 0615be9ab4 Merge branch 'master' into add-testing-info-to-readme 2017-10-11 11:26:07 +01:00
Kim Gardner e0dc41b721 Merge pull request #1088 from coralproject/add-testing-info-to-readme
Add Testing section to Readme with Browserstack logo
2017-10-11 11:22:09 +01:00
Kim Gardner b46ad5448c Update readme 2017-10-11 11:08:19 +01:00
Kiwi 8e9e61a610 Update README.md 2017-10-11 12:05:25 +02:00
Kim Gardner 341e8d9af6 Cleanup license text 2017-10-11 10:40:28 +01:00
Kim Gardner 674d7837f6 Change logo size 2017-10-11 10:38:23 +01:00
Kim Gardner b827abffbb Update Readme 2017-10-11 10:32:35 +01:00
Kim Gardner a48bfbaa69 Merge branch 'master' into dropdown 2017-10-11 09:49:19 +01:00
Kim Gardner dcfdec4df1 Merge branch 'master' into cannot-ignore-staff 2017-10-11 09:49:06 +01:00
Kim Gardner 0fde69608a Merge branch 'master' into count-whitespace-to-char-max 2017-10-11 09:29:19 +01:00
Kim Gardner 0225d38560 Merge pull request #1083 from coralproject/refactor-configure
Refactor Configure, Add Slots
2017-10-11 09:26:37 +01:00
Chi Vinh Le 34178919dc Count leading and trailing whitespace towards char count 2017-10-11 15:16:21 +07:00
Chi Vinh Le 7b76450eb5 Merge branch 'master' into refactor-configure
Conflicts:
	client/coral-admin/src/routes/Configure/components/Configure.css
	client/coral-admin/src/routes/Moderation/components/Moderation.js
2017-10-11 14:17:36 +07:00
Kiwi 3adc3e87cd Merge pull request #1084 from coralproject/danish-lang-config
Update i18n config to support new Danish translation
2017-10-11 09:03:50 +02:00
Kiwi b25fa9c7f3 Merge branch 'master' into danish-lang-config 2017-10-11 08:51:07 +02:00
Kiwi f712e426e2 Merge pull request #1081 from PepeFranco/ReadersNotifications
Added notifications when flagging failed
2017-10-11 08:50:52 +02:00
Kiwi a9882c8904 Merge branch 'master' into danish-lang-config 2017-10-11 08:45:16 +02:00
Kiwi a0f9242f02 Merge branch 'master' into ReadersNotifications 2017-10-11 08:44:36 +02:00
Wyatt Johnson fa6c0afe93 Merge pull request #1085 from coralproject/snyk-fix-cdba6ef9
[Snyk Update] New fixes for 4 vulnerable dependency paths
2017-10-11 00:36:52 -06:00
Chi Vinh Le 1d2f7b5298 Use correct import path 2017-10-11 13:34:27 +07:00
snyk-bot 5f9d47a199 fix: package.json & .snyk to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/npm:mime:20170907


The following vulnerabilities are fixed with a Snyk patch:
- https://snyk.io/vuln/npm:marked:20170112

Latest report for coralproject/talk:
https://snyk.io/test/github/coralproject/talk
2017-10-11 02:07:15 +00:00
Wyatt Johnson 29d7494385 fixed more yaml issues, added lint step 2017-10-10 14:04:37 -06:00
Kim Gardner 6145fd2855 Merge branch 'danish-lang-config' of git+ssh://github.com/coralproject/talk into danish-lang-config 2017-10-10 19:27:24 +01:00
Jose Franco 14d2b63f2e Merge branch 'master' into ReadersNotifications 2017-10-10 12:58:43 -05:00
PepeFranco cf59bb213c Changed FlagButton to use getErrorMessages util for failed flagging instead of custom messages 2017-10-10 12:55:32 -05:00
PepeFranco cecf2f4606 Merge branch 'ReadersNotifications' of https://github.com/PepeFranco/talk into ReadersNotifications 2017-10-10 12:54:51 -05:00
Kim Gardner bd7dfdbe55 Fix yml indentation 2017-10-10 18:52:53 +01:00
Wyatt Johnson 98ee3c7b55 Merge branch 'master' into danish-lang-config 2017-10-10 11:44:05 -06:00
Wyatt Johnson 0fc0e9c467 Merge branch 'master' into cannot-ignore-staff 2017-10-10 11:30:00 -06:00
Kim Gardner 398dedf75b Merge pull request #1080 from facuesr/ie11-issues
Fix issue 1071
2017-10-10 18:19:50 +01:00
Kim Gardner d11ac54e1d Merge branch 'master' into cannot-ignore-staff 2017-10-10 18:19:11 +01:00
Kim Gardner 764d562497 Merge branch 'master' into ReadersNotifications 2017-10-10 18:18:58 +01:00
Kim Gardner 4548134e3f Merge branch 'master' into dropdown 2017-10-10 18:18:34 +01:00
Kim Gardner 4efcd624c3 Merge branch 'master' into talk-product-guide 2017-10-10 18:14:37 +01:00
Kim Gardner 48af316380 Merge branch 'master' into ie11-issues 2017-10-10 18:13:28 +01:00
Kim Gardner 98f46409ca Merge pull request #1070 from coralproject/viewing-options
Viewing Options, and bug fixing
2017-10-10 18:13:09 +01:00
Kim Gardner dee5651709 Merge branch 'master' into ie11-issues 2017-10-10 18:09:54 +01:00
Belen Curcio c5cee13bd7 Accesibility 2017-10-10 13:24:56 -03:00
Kim Gardner e40a30d200 Fixes and cleanup 2017-10-10 17:17:04 +01:00
Belen Curcio 0d66e42313 Merge branch 'viewing-options' of github.com:coralproject/talk into viewing-options 2017-10-10 13:16:37 -03:00
Belen Curcio 154949ff47 Update 2017-10-10 13:12:55 -03:00
Kim Gardner 33e25403e7 Rename file to da.yml 2017-10-10 17:04:27 +01:00
PepeFranco c8dc1f84e6 Merge branch 'master' of https://github.com/coralproject/talk into ReadersNotifications 2017-10-10 11:03:15 -05:00
Belen Curcio 7fcc7753f8 Update 2017-10-10 12:50:31 -03:00
Kim Gardner 569260a4b9 Fix configuration and alphabetize languages 2017-10-10 16:47:33 +01:00
Belen Curcio 2028e56f48 using props, not state for selected 2017-10-10 12:40:09 -03:00
Belen Curcio 1c535bda89 Lowering down the animation 2017-10-10 12:27:32 -03:00
Belen Curcio 1f9ff3f36d Merge branch 'dropdown' of github.com:coralproject/talk into dropdown 2017-10-10 12:27:18 -03:00
Belen Curcio 18b18a7aef Removing global listeners 2017-10-10 12:26:41 -03:00
Belen Curcio f2ea269f7a Merge branch 'master' of github.com:coralproject/talk into dropdown 2017-10-10 12:26:29 -03:00
Belen Curcio bbad09d271 Missing proptype 2017-10-10 12:26:06 -03:00
Belén Curcio 932cec27de Merge branch 'master' into dropdown 2017-10-10 12:25:18 -03:00
Kim Gardner 2063c4a90e Fixes per code review 2017-10-10 16:24:49 +01:00
Belén Curcio 4d0d0735e8 Merge branch 'master' into viewing-options 2017-10-10 12:20:59 -03:00
Kiwi bd73140f23 Merge branch 'master' into ReadersNotifications 2017-10-10 15:38:54 +02:00
Kim Gardner b77c330823 Update i18n code 2017-10-10 14:02:07 +01:00
Kim Gardner 9f02165aa6 Merge branch 'master' of git+ssh://github.com/coralproject/talk into danish-lang-config 2017-10-10 14:01:12 +01:00
Kim Gardner 522857f0d6 Merge pull request #1079 from Rarer/Danish-Translation
Danish translation
2017-10-10 13:59:58 +01:00
Kim Gardner f1e81575cb Update i18n config to support Danish 2017-10-10 13:56:47 +01:00
Kim Gardner 69ace56172 Merge branch 'master' into Danish-Translation 2017-10-10 13:08:44 +01:00
Kim Gardner 0a991c938a Merge branch 'master' into talk-product-guide 2017-10-10 13:08:23 +01:00
Kim Gardner 6a2b6bb845 Merge branch 'master' into ReadersNotifications 2017-10-10 13:07:37 +01:00
Kim Gardner 78857e8de0 Merge branch 'master' into ie11-issues 2017-10-10 13:07:03 +01:00
Kim Gardner 3c7e0462f5 Merge branch 'master' into cannot-ignore-staff 2017-10-10 13:06:54 +01:00
Kim Gardner c0a54b6538 Merge branch 'master' into viewing-options 2017-10-10 13:06:18 +01:00
Kim Gardner 15f07b1360 Merge pull request #1068 from tylerbrewer2/fix-shortcut-icon
fix hidden shortcut icon
2017-10-10 13:05:20 +01:00
Chi Vinh Le 61604a7d07 Export ConfigureCard in plugin-api 2017-10-10 17:06:45 +07:00
Chi Vinh Le dfcb9e24df Refactor components 2017-10-10 17:00:25 +07:00
Belen Curcio 7b38bac525 Stories Dropdown, Proptypes and tiny refactor 2017-10-10 03:18:28 -03:00
Belen Curcio 16847f9fec Translations and PropTypes 2017-10-10 02:48:12 -03:00
Belen Curcio 71af62585a Adding Dropdown and Option Compoennt 2017-10-10 02:47:51 -03:00
Belén Curcio 29c7c9e810 Merge branch 'master' into viewing-options 2017-10-10 00:18:03 -03:00
PepeFranco c81d9c0bd1 Added notifications when flagging failed 2017-10-09 21:59:47 -05:00
Facu 0519b1d1ff fix 1071 2017-10-09 15:41:06 -03:00
Morten Nissen 046a17801e Fixed some mistakes, and general proof reading 2017-10-09 20:38:29 +02:00
Chi Vinh Le 21342b8b81 Fix title styling 2017-10-09 23:56:16 +07:00
Chi Vinh Le ec436bcb39 Refactor Configure styles 2017-10-09 23:50:43 +07:00
Chi Vinh Le 59eff3e29e Refactor moderationSettings styles 2017-10-09 23:37:37 +07:00
Chi Vinh Le 574cbf8e79 Refactor TechSettings styles 2017-10-09 23:28:32 +07:00
Chi Vinh Le b3fc920919 Refactor EmbedLink styles 2017-10-09 23:26:15 +07:00
Chi Vinh Le 1d089ee151 Refactor Domainlist styles 2017-10-09 23:00:21 +07:00
Chi Vinh Le 0434ecf755 Refactor Wordlist styles 2017-10-09 22:58:58 +07:00
Tyler Brewer 48c291a9c3 Merge branch 'master' into fix-shortcut-icon 2017-10-09 11:01:26 -04:00
Chi Vinh Le c0ff9c1beb Merge branch 'master' into refactor-configure
Conflicts:
	client/coral-admin/src/routes/Moderation/components/Moderation.js
2017-10-09 21:30:03 +07:00
Chi Vinh Le 3d3e0491a4 Remove updateWordlist and add test 2017-10-09 21:13:47 +07:00
Chi Vinh Le c52e42c644 Allow changing wordlist and domains using the updateSettings mutation 2017-10-09 16:51:27 +07:00
Kiwi 77d30bdbc1 Merge pull request #1066 from gerardogalvez/moderate-shortcuts
Add moderator shortcuts to open search and switch between queues.
2017-10-09 08:59:03 +02:00
Daniel Janeiro efdf7a6b25 Handle IgnoreUser mutation errors
We now check if the IgnoreUser mutation returned an error before
updating the apollo store. If the mutation returns an error we keep
the store as it is, otherwise the user is added to the ignore list.
2017-10-07 23:02:33 +01:00
Daniel Janeiro 7eaad1541b Implement cannot ignore staff in users service
`UsersService.ignoreUsers` now checks if any user provided is a staff
member. In case it is it throws a ErrCannotIgnoreStaff error.
2017-10-07 23:02:25 +01:00
Daniel Janeiro 0c7b35ffde Add cannot ignore staff error 2017-10-07 21:51:58 +01:00
Gerardo Galvez e4ff48ea88 Merge branch 'moderate-shortcuts' of https://github.com/gerardogalvez/talk into moderate-shortcuts 2017-10-06 20:20:48 -05:00
Gerardo Galvez cbd7337dbc Add spanish translations and cleaner way to get the activeTabIndex 2017-10-06 20:19:30 -05:00
Morten Nissen c0e9836a57 Added danish translation 2017-10-07 01:50:11 +02:00
Belén Curcio c7bf3c1a3c Merge branch 'master' into moderate-shortcuts 2017-10-06 18:07:30 -03:00
Tyler Brewer bb78ba9b0b Merge branch 'master' into fix-shortcut-icon 2017-10-06 16:09:59 -04:00
Kiwi 62834ae412 Merge pull request #1067 from lancekruegger/Issue-1024-forgot-password-flow
Update forgot password flow to match site styling
2017-10-06 21:43:14 +02:00
David Erwin 0c62ff0f9f Merge branch 'master' into Issue-1024-forgot-password-flow 2017-10-06 15:38:26 -04:00
Kiwi 380f20d525 Merge pull request #1072 from kamos1/fix-1037
fix issue 1037
2017-10-06 21:35:45 +02:00
Lance Ruegger 252ec8f6ac Change full constructor to use class property, fix typo in handleChangeEmail, pass value to TextField to ensure they stay in sync. 2017-10-06 12:26:03 -07:00
kamos1 e95e0381c2 remove removeNewLine and add .trim to length variable 2017-10-06 13:25:32 -06:00
kamos1 8ab31d7009 add trim to prevent empty spaces, tabs and other whitespace characters 2017-10-06 13:19:37 -06:00
kamos1 57f8a64cf4 fix issue 1037 2017-10-06 12:24:58 -06:00
Chi Vinh Le 0a190a9838 Add slots 2017-10-07 01:01:14 +07:00
Chi Vinh Le 6ff2e38003 Little Optimization 2017-10-07 00:54:46 +07:00
Chi Vinh Le 3a28eae384 Move activeSection to redux 2017-10-07 00:47:50 +07:00
Chi Vinh Le 5fbabcaa1b Simplify Configure 2017-10-07 00:31:44 +07:00
Kim Gardner 387316849a Merge branch 'master' into moderate-shortcuts 2017-10-06 17:34:46 +01:00
Kim Gardner 26c1d22ec3 Merge branch 'master' into fix-shortcut-icon 2017-10-06 17:30:28 +01:00
Chi Vinh Le eae5b85d1a Turn ModerationSettings into container 2017-10-06 23:08:56 +07:00
Belen Curcio dbe6e675c9 Modal Keys should show on tablet 2017-10-06 13:02:18 -03:00
Chi Vinh Le 2c8366d6b7 Turn TechSettings to container 2017-10-06 22:32:02 +07:00
Chi Vinh Le ae3d1c1819 Turn StreamSettings to container 2017-10-06 22:17:51 +07:00
Kim Gardner 916596fe53 Merge branch 'master' into Issue-1024-forgot-password-flow 2017-10-06 15:36:38 +01:00
Belen Curcio 0f6bbb21a3 Fix drawer too 2017-10-06 11:05:38 -03:00
Belen Curcio c2cbf91cad Merge branch 'master' of github.com:coralproject/talk into viewing-options 2017-10-06 11:02:46 -03:00
Belen Curcio fe689c5888 Margin Top 2017-10-06 10:52:16 -03:00
Belen Curcio e1f5fe1f77 Responsive Ready 2017-10-06 10:50:48 -03:00
Belen Curcio 848c04539c Select working 2017-10-06 10:35:04 -03:00
Belen Curcio e4b225b4c2 ViewingOptions, Cards, Proptypes and MediaQueries 2017-10-06 10:10:08 -03:00
Kiwi 787f11118c Merge pull request #1059 from Rishabh04-02/master
displaying time in X minutes Y seconds
2017-10-06 14:38:20 +02:00
Kiwi cca0a6df71 Merge branch 'master' into master 2017-10-06 13:43:21 +02:00
Chi Vinh Le 5073ef6c1b Implement save settings 2017-10-06 18:27:10 +07:00
Kim Gardner 596cd57274 Merge pull request #1065 from amorimgustavo/patch-1
Update pt_BR.yml
2017-10-06 12:14:17 +01:00
Kim Gardner b02ccd792c Merge branch 'master' into patch-1 2017-10-06 12:09:41 +01:00
Kiwi ad5a6c539a Merge branch 'master' into master 2017-10-06 12:04:42 +02:00
tylerbrewer2 a4591ecb55 fix hidden shortcut icon 2017-10-05 20:51:54 -04:00
Lance Ruegger 6c95502b4e Change DOM input to coral-ui TextField to inherit styling, add prop-types validation, convert from using ref to using state. 2017-10-05 17:36:38 -07:00
Gerardo Gálvez 931b5ad3ac Merge branch 'master' into moderate-shortcuts 2017-10-05 17:18:18 -05:00
Gerardo Galvez c0bb5e5cb2 Add moderator shortcuts to open search and switch between queues. 2017-10-05 16:57:46 -05:00
Wyatt Johnson 1b33b62af0 Merge pull request #1057 from vickychijwani/slackbot
Slack notifications plugin for new comments
2017-10-05 15:27:04 -06:00
Vicky Chijwani bf0901e77f Wrap Slack call in process.nextTick() to avoid blocking comment creation. 2017-10-06 02:17:45 +05:30
amorimgustavo f164ad8013 Update pt_BR.yml
Hello Folks,

Just edited some (several actually :) messages in your pt_BR.yml for your consideration.

You may consider using:

- "Banido" instead of "proibido"
- "Perfil" or "Usuario" instead of "Bio"
- "Opinião" instead of "Feedback"
- "Denunciar" instead of "Reportar"
- "Usuários(as)" instead of "Comentaristas"
- "Listas" instead of "Hilos" or "Filas"
- "Conversas" instead of "Histórias"

Hope you like those suggestions.

Cheers.
Gustavo
2017-10-05 17:10:42 -03:00
Rishabh04-02 f1bad9e8f2 modifications - displaying time
modifications in displaying like X minutes Y seconds
2017-10-05 23:07:51 +05:30
Kim Gardner ba51645c87 Merge branch 'master' into slackbot 2017-10-05 17:08:17 +01:00
Kim Gardner bc0a188c57 Merge branch 'master' into master 2017-10-05 17:06:41 +01:00
Kim Gardner f497fdb277 Merge pull request #1056 from tylerbrewer2/fix-nav-width
fix admin navigation width
2017-10-05 17:06:17 +01:00
Kim Gardner a677c698bf Merge branch 'master' into master 2017-10-05 16:53:52 +01:00
Kim Gardner 73b4cfd2c4 Merge branch 'master' into slackbot 2017-10-05 16:53:43 +01:00
Kim Gardner 5f758d3437 Merge branch 'master' into fix-nav-width 2017-10-05 16:53:02 +01:00
Kim Gardner e8808f9232 Merge pull request #1061 from coralproject/clean-up-readme
Clean up README
2017-10-05 16:52:30 +01:00
Wyatt Johnson 6713397d02 Merge branch 'master' into clean-up-readme 2017-10-05 08:39:47 -06:00
Chi Vinh Le 9c00050f6a Load settings from graph 2017-10-05 21:05:05 +07:00
Kim Gardner 6259c1869d Merge pull request #1062 from dusty-wil/master
#1043 - Better error message for 1 character comments
2017-10-05 14:43:24 +01:00
Kim Gardner 2e7a59a6e1 Merge branch 'master' into talk-product-guide 2017-10-05 13:53:44 +01:00
dusty-wil 1ad942f06c Merge branch 'master' into master 2017-10-05 08:46:58 -04:00
Kim Gardner 6ffab51bcf Cleanup titles 2017-10-05 13:41:54 +01:00
Kim Gardner 71de5a33a9 Update nav 2017-10-05 13:40:53 +01:00
Kim Gardner a1978571e8 First part of Product Guide 2017-10-05 13:38:08 +01:00
Dusty Williams 1510ade47a revised error message for comments less than two characters in length - dmw 2017-10-05 08:33:29 -04:00
Kim Gardner f330c385e5 Clean up README 2017-10-05 12:29:27 +01:00
Belen Curcio 886df1cdca Now every section is full width :D 2017-10-05 08:21:17 -03:00
Belen Curcio 91a25fc3c1 max-width 2017-10-05 08:00:08 -03:00
Belén Curcio 474a3a12ef Merge branch 'master' into master 2017-10-05 07:34:49 -03:00
Belén Curcio 9b9e9c0292 Merge branch 'master' into fix-nav-width 2017-10-05 07:34:04 -03:00
Kim Gardner 34292f467d Merge pull request #1052 from lancekruegger/max-resize-other-box
Add a max-width to flag-reason text box to prevent cutoff
2017-10-05 11:30:33 +01:00
Belén Curcio c72dfdddf3 Merge branch 'master' into max-resize-other-box 2017-10-05 07:25:09 -03:00
Kim Gardner ec74262089 Merge branch 'master' into fix-nav-width 2017-10-05 10:53:43 +01:00
Rishabh04-02 b3486ce614 displaying time in X minutes Y seconds 2017-10-05 10:48:12 +05:30
tylerbrewer2 85f9000a64 fix admin navigation width 2017-10-04 20:22:39 -04:00
Vicky Chijwani 95580f5ffe Add Slack notifications plugin for new comments. 2017-10-05 05:32:37 +05:30
Kim Gardner 57b7829189 Merge pull request #1054 from PepeFranco/patch-2
Updated running-advanced-configuration.md
2017-10-04 23:40:50 +01:00
Jose Franco 551ac9dd90 Update running-advanced-configuration.md 2017-10-04 17:31:48 -05:00
Wyatt Johnson 2568f65fe5 Merge pull request #1053 from PepeFranco/defaultLanguage
Added env variable TALK_DEFAULT_LAN
2017-10-04 15:27:45 -06:00
PepeFranco 8d6f79ab79 Fixed typo from LAN to LANG 2017-10-04 16:16:07 -05:00
PepeFranco 841ab53ea7 Added env variable TALK_DEFAULT_LAN 2017-10-04 15:42:02 -05:00
Lance Ruegger 5147ca6b86 Add a max-width to the flag-reason text box to prevent cutoff 2017-10-04 11:04:47 -07:00
Kiwi 197d94ffb1 Merge pull request #1004 from coralproject/jest-unit-test
Introduce Jest Unit Testing Framework
2017-10-04 18:22:09 +02:00
Kiwi d23d3be4ef Merge branch 'master' into jest-unit-test 2017-10-04 13:13:09 +02:00
Kiwi ff9ae03522 Merge pull request #1009 from coralproject/revert-1008-revert-1002-es6-modules-tree-shaking
Es6 modules + tree shaking
2017-10-04 13:12:53 +02:00
Wyatt Johnson a50c16c00f Merge pull request #1010 from coralproject/revert-1007-revert-1005-rm-babelrc-subscriber
Revert "Revert "Remove .babelrc from plugin""
2017-10-03 14:56:22 -06:00
Wyatt Johnson d75257a832 Revert "Revert "Remove .babelrc from plugin"" 2017-10-03 14:55:20 -06:00
Wyatt Johnson 074fbca231 Revert "Revert "Es6 modules + tree shaking"" 2017-10-03 14:54:08 -06:00
Kiwi bd01d5f3fe Merge branch 'master' into jest-unit-test 2017-10-03 18:53:42 +02:00
Chi Vinh Le 52595bb3f8 Merge branch 'master' into jest-unit-test 2017-10-03 22:48:14 +07:00
Chi Vinh Le faf75c5c2f Upgrade linters 2017-10-03 22:08:55 +07:00
Chi Vinh Le 33920afc74 Port form chai to jest 2017-10-03 21:54:15 +07:00
Chi Vinh Le bd83e9e118 Add first Snapshot testing 2017-10-03 21:31:10 +07:00
Chi Vinh Le 2be8750d0e Add yarn jest-watch 2017-10-03 21:30:55 +07:00
Chi Vinh Le 14ce9b1e77 relax language 2017-10-03 21:19:19 +07:00
Chi Vinh Le 51e40ce185 Merge branch 'es6-modules-tree-shaking' into jest-unit-test 2017-10-03 21:16:08 +07:00
Chi Vinh Le c1f7ef4f32 Introduce Jest Unit Testing framework 2017-10-03 21:08:02 +07:00
436 changed files with 13705 additions and 7077 deletions
+10 -4
View File
@@ -1,9 +1,8 @@
{
"presets": [
"es2015"
["es2015", {modules: false}]
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
@@ -11,5 +10,12 @@
"transform-async-to-generator",
"transform-react-jsx",
"syntax-dynamic-import"
]
}
],
"env": {
"test": {
"plugins": [
["transform-es2015-modules-commonjs", "dynamic-import-node"]
]
}
}
}
+5
View File
@@ -15,6 +15,10 @@ client/coral-framework/graphql/introspection.json
*.DS_STORE
coverage/
test/e2e/reports/
test/e2e/bslocal.log
test/e2e/selenium-debug.log
browserstack.err
plugins.json
plugins/*
@@ -45,5 +49,6 @@ plugins/*
!plugins/talk-plugin-deep-reply-count
!plugins/talk-plugin-subscriber
!plugins/talk-plugin-flag-details
!plugins/talk-plugin-slack-notifications
**/node_modules/*
+6
View File
@@ -0,0 +1,6 @@
{
"exceptions": [
"https://nodesecurity.io/advisories/531",
"https://nodesecurity.io/advisories/532"
]
}
+11 -4
View File
@@ -1,11 +1,18 @@
FROM coralproject/talk:latest
# Setup the build arguments
ONBUILD ARG TALK_THREADING_LEVEL=3
ONBUILD ARG TALK_DEFAULT_STREAM_TAB=all
ONBUILD ARG TALK_DEFAULT_LANG=en
ONBUILD ARG TALK_PLUGINS_JSON
# Bundle app source
ONBUILD COPY . /usr/src/app
# At this stage, we need to install the development dependancies again because
# we need to have webpack available. We then build the new dependancies and
# clear out the development dependancies again. After this we of course need to
# At this stage, we need to install the development dependencies again because
# we need to have webpack available. We then build the new dependencies and
# clear out the development dependencies again. After this we of course need to
# clear out the yarn cache, this saves quite a lot of size.
ONBUILD RUN cli plugins reconcile && \
yarn build
yarn build && \
yarn cache clean
+7 -3
View File
@@ -4,8 +4,12 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied.
See the License for the specific language governing permissions and limitations under the License.
See the License for the specific language governing permissions
and limitations under the License.
+27 -20
View File
@@ -1,30 +1,37 @@
# Talk [![CircleCI](https://circleci.com/gh/coralproject/talk.svg?style=svg)](https://circleci.com/gh/coralproject/talk)
# Talk · [![CircleCI](https://circleci.com/gh/coralproject/talk.svg?style=svg)](https://circleci.com/gh/coralproject/talk) · [![NSP Status](https://nodesecurity.io/orgs/coralproject/projects/07ce2e4c-99fb-48f8-b50b-69d2d2c081b8/badge)](https://nodesecurity.io/orgs/coralproject/projects/07ce2e4c-99fb-48f8-b50b-69d2d2c081b8) · [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md#pull-requests)
Online comments are broken. Our open-source commenting platform, Talk, rethinks how moderation, comment display, and conversation function, creating the opportunity for safer, smarter discussions around your work. [Read more about Talk here](https://coralproject.net/products/talk.html).
Built with <3 by The Coral Project & Mozilla.
## Try Talk!
You're just one click away from trying Talk - all you need is a Heroku account and a few minutes of your time.
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://dashboard.heroku.com/new?template=https%3A%2F%2Fgithub.com%2Fcoralproject%2Ftalk&env[TALK_FACEBOOK_APP_ID]=ignore&env[TALK_FACEBOOK_APP_SECRET]=ignore)
Online comments are broken. Our open-source Talk tool rethinks how moderation, comment display, and conversation function, creating the opportunity for safer, smarter discussions around your work. [Read more about Talk here](https://coralproject.net/products/talk.html).
## Technical Documentation
## Documentation
From getting up and running, to advanced configuration, to how to scale Talk, our [Talk Technical Docs](https://coralproject.github.io/talk/) have everything you need to know.
Developer Documentation & Setup Guides https://coralproject.github.io/talk/.
## Product Guide
Learn more about Talk, including a deep dive into features for commenters and moderators, and FAQs in our [Talk Product Guide](https://coralproject.github.io/talk/how-talk-works).
## Relevant Links
- Blog: https://blog.coralproject.net/
- Community Forums: https://community.coralproject.net/
- Community Guides for Journalism: https://guides.coralproject.net/
- Project: https://coralproject.net/
- Roadmap: https://www.pivotaltracker.com/n/projects/1863625
- [Our Blog](https://blog.coralproject.net/)
- [Community Forums](https://community.coralproject.net/)
- [Community Guides for Journalism](https://guides.coralproject.net/)
- [More About Us](https://coralproject.net/)
- [Talk Roadmap](https://www.pivotaltracker.com/n/projects/1863625)
## End-to-End Testing
Talk uses [Nightwatch](https://nightwatchjs.org/) as our e2e testing framework. The testing infrastructure that allows us to run our tests in real browsers is provided with love by our friends at [Browserstack](https://browserstack.com).
[![Browserstack](/public/img/browserstack_logo.png)](https://browserstack.com)
## License
Copyright 2017 Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
Talk is released under the [Apache License, v2.0](/LICENSE).
+21 -12
View File
@@ -1,19 +1,37 @@
const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const path = require('path');
const uuid = require('uuid');
const merge = require('lodash/merge');
const helmet = require('helmet');
const plugins = require('./services/plugins');
const compression = require('compression');
const cookieParser = require('cookie-parser');
const {HELMET_CONFIGURATION} = require('./config');
const {MOUNT_PATH} = require('./url');
const {applyLocals} = require('./services/locals');
const routes = require('./routes');
const debug = require('debug')('talk:app');
const app = express();
// Request Identity Middleware
app.use((req, res, next) => {
req.id = uuid.v4();
next();
});
//==============================================================================
// PLUGIN PRE APPLICATION MIDDLEWARE
//==============================================================================
// Inject server route plugins.
plugins.get('server', 'app').forEach(({plugin, app: callback}) => {
debug(`added plugin '${plugin.name}'`);
// Pass the app to the plugin to mount it's routes.
callback(app);
});
//==============================================================================
// APPLICATION WIDE MIDDLEWARE
//==============================================================================
@@ -36,12 +54,6 @@ app.use(helmet(merge(HELMET_CONFIGURATION, {
// Compress the responses if appropriate.
app.use(compression());
// Parse the cookies on the request.
app.use(cookieParser());
// Parse the body json if it's there.
app.use(bodyParser.json());
//==============================================================================
// VIEW CONFIGURATION
//==============================================================================
@@ -53,9 +65,6 @@ app.set('view engine', 'ejs');
// ROUTES
//==============================================================================
// Add the locals to the app renderer.
applyLocals(app.locals);
debug(`mounting routes on the ${MOUNT_PATH} path`);
// Actually apply the routes.
+44 -23
View File
@@ -12,7 +12,7 @@ const mongoose = require('../services/mongoose');
const kue = require('../services/kue');
util.onshutdown([
() => mongoose.disconnect()
() => mongoose.disconnect(),
]);
/**
@@ -20,17 +20,17 @@ util.onshutdown([
*/
function processJobs() {
// Start the scraper processor.
scraper.process();
// Start the mail processor.
mailer.process();
// The scraper only needs to shutdown when the scraper has actually been
// started.
util.onshutdown([
() => kue.Task.shutdown()
]);
// Start the scraper processor.
scraper.process();
// Start the mail processor.
mailer.process();
}
/**
@@ -48,22 +48,13 @@ function removeJob(job) {
}));
}
/**
* Removes the jobs passed in and returns a promise.
* @param {Array} jobs array of jobs
* @return {Promise}
*/
function removeJobs(jobs) {
return Promise.all(jobs.map(removeJob));
}
/**
* Get the top n jobs with a specific state.
* @param {String} [state='complete'] state to list jobs by
* @param {Number} limit limit of jobs to load
* @return {Promise}
*/
function rangeJobsByState(state = 'complete', limit) {
function rangeJobsByState(state, limit) {
return new Promise((resolve, reject) => {
kue.Job.rangeByState(state, 0, limit, 'asc', (err, jobs) => {
if (err) {
@@ -75,22 +66,52 @@ function rangeJobsByState(state = 'complete', limit) {
});
}
async function getJobBatch(n, includeStuck) {
let jobs = [];
jobs = await rangeJobsByState('complete', n);
if (includeStuck) {
jobs = jobs.concat(await rangeJobsByState('failed', n));
}
return jobs;
}
/**
* Cleans up the jobs that are in the queue.
*/
async function cleanupJobs(options) {
// The scraper only needs to shutdown when the scraper has actually been
// started.
util.onshutdown([
() => kue.Task.shutdown()
]);
const n = 100;
try {
const joblists = await Promise.all([
rangeJobsByState('complete', n),
options.stuck ? rangeJobsByState('failed', n) : false
]);
await joblists.filter((jobs) => jobs).map(removeJobs);
// Connect to redis by establishing a queue.
kue.Task.connect();
let jobCount = 0;
let jobs = await getJobBatch(n, options.stuck);
while (jobs.length > 0) {
// Remove all the jobs.
await Promise.all(jobs.map((job) => removeJob(job)));
jobCount += jobs.length;
// Get the next batch of jobs.
jobs = await getJobBatch(n, options.stuck);
}
util.shutdown();
console.log('Removed old jobs');
console.log(`Removed ${jobCount} jobs`);
} catch (err) {
console.error(err);
util.shutdown(1);
+6 -174
View File
@@ -1,161 +1,8 @@
#!/usr/bin/env node
const program = require('./commander');
const app = require('../app');
const debug = require('debug')('talk:cli:serve');
const errors = require('../errors');
const {createServer} = require('http');
const scraper = require('../services/scraper');
const mailer = require('../services/mailer');
const MigrationService = require('../services/migration');
const SetupService = require('../services/setup');
const kue = require('../services/kue');
const mongoose = require('../services/mongoose');
const util = require('./util');
const cache = require('../services/cache');
const {createSubscriptionManager} = require('../graph/subscriptions');
const {
PORT
} = require('../config');
/**
* Get port from environment and store in Express.
*/
const port = normalizePort(PORT);
app.set('port', port);
/**
* Create HTTP server.
*/
const server = createServer(app);
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
let bind = typeof port === 'string'
? `Pipe ${port}`
: `Port ${port}`;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(`${bind} requires elevated privileges`);
break;
case 'EADDRINUSE':
console.error(`${bind} is already in use`);
break;
}
throw error;
}
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
let port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "listening" event.
*/
async function onListening() {
// Start the cache instance.
await cache.init();
let addr = server.address();
let bind = typeof addr === 'string'
? `pipe ${addr}`
: `port ${addr.port}`;
debug(`API Server Listening on ${bind}`);
}
/**
* Start the app.
*/
async function startApp(program) {
try {
// Check to see if the application is installed. If the application
// has been installed, then it will throw errors.ErrSettingsNotInit, this
// just means we don't have to check that the migrations have run.
await SetupService.isAvailable();
debug('setup is currently available, migrations not being checked');
} catch (e) {
// Check the error.
switch (e) {
case errors.ErrInstallLock, errors.ErrSettingsInit:
debug('setup is not currently available, migrations now being checked');
// The error was expected, just continue.
break;
default:
// The error was not expected, throw the error!
throw e;
}
// Now try and check the migration status.
try {
// Verify that the minimum migration version is met.
await MigrationService.verify();
} catch (e) {
console.error(e);
process.exit(1);
}
debug('migrations do not have to be run');
}
/**
* Listen on provided port, on all network interfaces.
*/
server.on('error', onError);
server.on('listening', onListening);
server.on('listening', () => {
});
server.listen(port, () => {
// Mount the websocket server if requested.
if (program.websockets) {
debug(`Websocket Server Listening on ${port}`);
// Mount the subscriptions server on the application server.
createSubscriptionManager(server);
}
});
}
const serve = require('../serve');
//==============================================================================
// Setting up the program command line arguments.
@@ -166,24 +13,9 @@ program
.option('-w, --websockets', 'enable the websocket (subscriptions) handler on this thread')
.parse(process.argv);
// Start the application serving.
startApp(program);
// Start serving.
serve({jobs: program.jobs, websockets: program.websockets}).catch((err) => {
console.error(err);
util.shutdown(1);
});
// Enable job processing on the thread if enabled.
if (program.jobs) {
// Start the scraper processor.
scraper.process();
// Start the mail processor.
mailer.process();
}
// Define a safe shutdown function to call in the event we need to shutdown
// because the node hooks are below which will interrupt the shutdown process.
// Shutdown the mongoose connection, the app server, and the scraper.
util.onshutdown([
() => program.jobs ? kue.Task.shutdown() : null,
() => mongoose.disconnect(),
() => server.close()
]);
+1 -1
View File
@@ -195,7 +195,7 @@ const performSetup = async () => {
password: user.password
}
});
console.log('Settings created.');
console.log(`User ${newUser.id} created.`);
console.log('\nTalk is now installed!');
+70 -15
View File
@@ -8,10 +8,13 @@ const program = require('./commander');
const inquirer = require('inquirer');
const UsersService = require('../services/users');
const UserModel = require('../models/user');
const CommentModel = require('../models/comment');
const ActionModel = require('../models/action');
const USER_ROLES = require('../models/enum/user_roles');
const mongoose = require('../services/mongoose');
const util = require('./util');
const Table = require('cli-table');
const databaseVerifications = require('./verifications/database');
const validateRequired = (msg = 'Field is required', len = 1) => (input) => {
if (input && input.length >= len) {
@@ -122,26 +125,48 @@ async function createUser(options) {
} catch (err) {
console.error(err);
util.shutdown();
util.shutdown(1);
}
}
/**
* Deletes a user.
*/
function deleteUser(userID) {
UserModel
.findOneAndRemove({
id: userID
})
.then(() => {
console.log('Deleted user');
util.shutdown();
})
.catch((err) => {
console.error(err);
util.shutdown();
});
async function deleteUser(userID) {
try {
// Find the user we're removing.
const user = await UserModel.findOne({id: userID});
if (!user) {
throw new Error(`user with id ${userID} not found`);
}
// Remove all the user's actions.
await ActionModel
.where({user_id: user.id})
.setOptions({multi: true})
.remove();
// Remove all the user's comments.
await CommentModel
.where({author_id: user.id})
.setOptions({multi: true})
.remove();
// Update the counts that might have changed.
for (const verification of databaseVerifications) {
await verification({fix: true, limit: Infinity, batch: 1000});
}
// Remove the user.
await user.remove();
util.shutdown();
} catch (err) {
console.error(err);
util.shutdown(1);
}
}
/**
@@ -241,13 +266,21 @@ function listUsers() {
});
users.forEach((user) => {
let state = user.disabled ? 'Disabled' : 'Enabled';
const profile = user.profiles.find(({provider}) => provider === 'local');
if (profile && profile.metadata && profile.metadata.confirmed_at) {
state += ', Verified';
} else {
state += ', Unverified';
}
table.push([
user.id,
user.username,
user.profiles.map((p) => p.provider).join(', '),
user.roles.join(', '),
user.status,
user.disabled ? 'Disabled' : 'Enabled'
state
]);
});
@@ -396,6 +429,23 @@ function enableUser(userID) {
});
}
/**
* Verifies an email address for a user.
*
* @param userID the user's id
* @param email the user's email address to be verified
*/
async function verify(userID, email) {
try {
await UsersService.confirmEmail(userID, email);
console.log(`User ${userID} had their email ${email} verified.`);
util.shutdown();
} catch (err) {
console.error(err);
util.shutdown(1);
}
}
//==============================================================================
// Setting up the program command line arguments.
//==============================================================================
@@ -467,6 +517,11 @@ program
.description('enable a given user from logging in')
.action(enableUser);
program
.command('verify <userID> <email>')
.description('verifies the given user\'s email address')
.action(verify);
program.parse(process.argv);
// If there is no command listed, output help.
-14
View File
@@ -1,14 +0,0 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
+15 -4
View File
@@ -7,9 +7,7 @@ machine:
environment:
PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin"
NODE_ENV: "test"
dependencies:
override:
pre:
# TODO: use the following to add in support for MongoDB 3.4.
# # Upgrade the database version to 3.4.
# - sudo apt-get purge mongodb-org*
@@ -19,10 +17,20 @@ dependencies:
# - sudo apt-get install -y mongodb-org
# - sudo service mongod restart
# Install chromium for e2e and remove old google-chrome
- sudo rm -rf /opt/google/chrome
- sudo rm -f /usr/bin/google-chrome*
- sudo apt-get update
- sudo apt-get install chromium-browser
dependencies:
override:
# Install node dependencies.
- yarn --version
- yarn global add node-gyp --force
- yarn global add node-gyp nsp --force
- yarn
post:
# Build the static assets.
- yarn build
@@ -40,6 +48,9 @@ test:
override:
# Run the tests using the junit reporter.
- MOCHA_FILE=$CIRCLE_TEST_REPORTS/junit/test-results.xml MOCHA_REPORTER=mocha-junit-reporter yarn test
# Check dependancies using nsp.
- nsp check
- yarn e2e-ci
deployment:
release:
-2
View File
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import {Router, Route, IndexRedirect, IndexRoute} from 'react-router';
import Configure from 'routes/Configure';
import Dashboard from 'routes/Dashboard';
import Install from 'routes/Install';
import Stories from 'routes/Stories';
import Community from 'routes/Community/containers/Community';
@@ -18,7 +17,6 @@ const routes = (
<IndexRedirect to='/admin/moderate' />
<Route path='configure' component={Configure} />
<Route path='stories' component={Stories} />
<Route path='dashboard' component={Dashboard} />
{/* Community Routes */}
+20 -13
View File
@@ -1,11 +1,12 @@
import queryString from 'query-string';
import {
FETCH_COMMENTERS_REQUEST,
FETCH_COMMENTERS_SUCCESS,
FETCH_COMMENTERS_FAILURE,
FETCH_USERS_REQUEST,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE,
SORT_UPDATE,
COMMENTERS_NEW_PAGE,
SET_PAGE,
SET_SEARCH_VALUE,
SET_ROLE,
SET_COMMENTER_STATUS,
SHOW_BANUSER_DIALOG,
@@ -16,13 +17,13 @@ import {
import t from 'coral-framework/services/i18n';
export const fetchAccounts = (query = {}) => (dispatch, _, {rest}) => {
dispatch(requestFetchAccounts());
export const fetchUsers = (query = {}) => (dispatch, _, {rest}) => {
dispatch(requestFetchUsers());
rest(`/users?${queryString.stringify(query)}`)
.then(({result, page, count, limit, totalPages}) =>{
dispatch({
type: FETCH_COMMENTERS_SUCCESS,
accounts: result,
type: FETCH_USERS_SUCCESS,
users: result,
page,
count,
limit,
@@ -32,12 +33,12 @@ export const fetchAccounts = (query = {}) => (dispatch, _, {rest}) => {
.catch((error) => {
console.error(error);
const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString();
dispatch({type: FETCH_COMMENTERS_FAILURE, error: errorMessage});
dispatch({type: FETCH_USERS_FAILURE, error: errorMessage});
});
};
const requestFetchAccounts = () => ({
type: FETCH_COMMENTERS_REQUEST
const requestFetchUsers = () => ({
type: FETCH_USERS_REQUEST
});
export const updateSorting = (sort) => ({
@@ -45,8 +46,14 @@ export const updateSorting = (sort) => ({
sort
});
export const newPage = () => ({
type: COMMENTERS_NEW_PAGE
export const setPage = (page) => ({
type: SET_PAGE,
page,
});
export const setSearchValue = (value) => ({
type: SET_SEARCH_VALUE,
value,
});
export const setRole = (id, role) => (dispatch, _, {rest}) => {
@@ -0,0 +1,13 @@
import * as actions from 'constants/configure';
export const updatePending = ({updater, errorUpdater}) => {
return {type: actions.UPDATE_PENDING, updater, errorUpdater};
};
export const clearPending = () => {
return {type: actions.CLEAR_PENDING};
};
export const setActiveSection = (section) => {
return {type: actions.SET_ACTIVE_SECTION, section};
};
@@ -34,3 +34,8 @@ export const storySearchChange = (value) => ({
export const clearState = () => ({
type: actions.MODERATION_CLEAR_STATE
});
export const selectCommentId = (id) => ({
type: actions.MODERATION_SELECT_COMMENT,
id,
});
@@ -1,58 +0,0 @@
import t from 'coral-framework/services/i18n';
export const SETTINGS_LOADING = 'SETTINGS_LOADING';
export const SETTINGS_RECEIVED = 'SETTINGS_RECEIVED';
export const SETTINGS_FETCH_ERROR = 'SETTINGS_FETCH_ERROR';
export const SETTINGS_UPDATED = 'SETTINGS_UPDATED';
export const SAVE_SETTINGS_LOADING = 'SAVE_SETTINGS_LOADING';
export const SAVE_SETTINGS_SUCCESS = 'SAVE_SETTINGS_SUCCESS';
export const SAVE_SETTINGS_FAILED = 'SAVE_SETTINGS_FAILED';
export const WORDLIST_UPDATED = 'WORDLIST_UPDATED';
export const DOMAINLIST_UPDATED = 'DOMAINLIST_UPDATED';
export const fetchSettings = () => (dispatch, _, {rest}) => {
dispatch({type: SETTINGS_LOADING});
rest('/settings')
.then((settings) => {
dispatch({type: SETTINGS_RECEIVED, settings});
})
.catch((error) => {
console.error(error);
const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString();
dispatch({type: SETTINGS_FETCH_ERROR, error: errorMessage});
});
};
// for updating top-level settings
export const updateSettings = (settings) => {
return {type: SETTINGS_UPDATED, settings};
};
// this is a nested property, so it needs a special action.
export const updateWordlist = (listName, list) => {
return {type: WORDLIST_UPDATED, listName, list};
};
export const updateDomainlist = (listName, list) => {
return {type: DOMAINLIST_UPDATED, listName, list};
};
export const saveSettingsToServer = () => (dispatch, getState, {rest}) => {
let settings = getState().settings;
if (settings.charCount) {
settings.charCount = parseInt(settings.charCount);
}
dispatch({type: SAVE_SETTINGS_LOADING});
rest('/settings', {method: 'PUT', body: settings})
.then(() => {
dispatch({type: SAVE_SETTINGS_SUCCESS, settings});
})
.catch((error) => {
console.error(error);
const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString();
dispatch({type: SAVE_SETTINGS_FAILED, error: errorMessage});
});
};
@@ -1,12 +1,17 @@
import queryString from 'query-string';
import {
FETCH_ASSETS_REQUEST,
FETCH_ASSETS_SUCCESS,
FETCH_ASSETS_FAILURE,
SET_PAGE,
SET_SEARCH_VALUE,
SET_CRITERIA,
UPDATE_ASSET_STATE_REQUEST,
UPDATE_ASSET_STATE_SUCCESS,
UPDATE_ASSET_STATE_FAILURE,
UPDATE_ASSETS
} from '../constants/assets';
} from '../constants/stories';
import t from 'coral-framework/services/i18n';
@@ -16,13 +21,16 @@ import t from 'coral-framework/services/i18n';
// Fetch a page of assets
// Get comments to fill each of the three lists on the mod queue
export const fetchAssets = (skip = '', limit = '', search = '', sort = '', filter = '') => (dispatch, _, {rest}) => {
export const fetchAssets = (query = {}) => (dispatch, _, {rest}) => {
dispatch({type: FETCH_ASSETS_REQUEST});
return rest(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`)
.then(({result, count}) =>
return rest(`/assets?${queryString.stringify(query)}`)
.then(({result, page, count, limit, totalPages}) =>
dispatch({type: FETCH_ASSETS_SUCCESS,
assets: result,
count
page,
count,
limit,
totalPages,
}))
.catch((error) => {
console.error(error);
@@ -47,3 +55,19 @@ export const updateAssetState = (id, closedAt) => (dispatch, _, {rest}) => {
export const updateAssets = (assets) => (dispatch) => {
dispatch({type: UPDATE_ASSETS, assets});
};
export const setPage = (page) => ({
type: SET_PAGE,
page,
});
export const setSearchValue = (value) => ({
type: SET_SEARCH_VALUE,
value,
});
export const setCriteria = (criteria) => ({
type: SET_CRITERIA,
criteria,
});
@@ -20,3 +20,9 @@ export const toggleSelectCommentInUserDetail = (id, active) => {
};
};
export const toggleSelectAllCommentInUserDetail = (ids, active) => {
return {
type: active ? actions.SELECT_ALL_USER_DETAIL_COMMENT : actions.CLEAR_USER_DETAIL_SELECTIONS,
ids
};
};
@@ -32,8 +32,9 @@ class ActionsMenu extends React.Component {
};
render() {
const {className = ''} = this.props;
return (
<div className={styles.root} onBlur={this.syncOpenState} >
<div className={cn(styles.root, className)} onBlur={this.syncOpenState} >
<Button
cStyle='actions'
className={cn(styles.button, {[styles.buttonOpen]: this.state.open})}
@@ -59,6 +60,7 @@ class ActionsMenu extends React.Component {
ActionsMenu.propTypes = {
icon: PropTypes.string,
children: PropTypes.node,
className: PropTypes.string,
};
export default ActionsMenu;
@@ -3,12 +3,14 @@ import cn from 'classnames';
import {MenuItem} from 'react-mdl';
import PropTypes from 'prop-types';
import styles from './ActionsMenu.css';
import camelCase from 'lodash/camelCase';
const ActionsMenuItem = (props) =>
<MenuItem className={cn(styles.menuItem, props.className)} {...props} />;
<MenuItem className={cn(styles.menuItem, props.className, 'action-menu-item')} {...props} id={camelCase(props.children)}/>;
ActionsMenuItem.propTypes = {
className: PropTypes.string,
children: PropTypes.string,
};
export default ActionsMenuItem;
@@ -4,6 +4,7 @@ import Layout from 'coral-admin/src/components/ui/Layout';
import styles from './NotFound.css';
import {Button, TextField, Alert, Success} from 'coral-ui';
import Recaptcha from 'react-recaptcha';
import cn from 'classnames';
class AdminLogin extends React.Component {
@@ -34,19 +35,22 @@ class AdminLogin extends React.Component {
render () {
const {errorMessage, loginMaxExceeded, recaptchaPublic} = this.props;
const signInForm = (
<form onSubmit={this.handleSignIn}>
<form className="talk-admin-login-sign-in" onSubmit={this.handleSignIn}>
{errorMessage && <Alert>{errorMessage}</Alert>}
<TextField
id="email"
label='Email Address'
value={this.state.email}
onChange={(e) => this.setState({email: e.target.value})} />
<TextField
id="password"
label='Password'
value={this.state.password}
onChange={(e) => this.setState({password: e.target.value})}
type='password' />
<div style={{height: 10}}></div>
<Button
className="talk-admin-login-sign-in-button"
type='submit'
cStyle='black'
full
@@ -90,7 +94,7 @@ class AdminLogin extends React.Component {
);
return (
<Layout fixedDrawer restricted={true}>
<div className={styles.loginLayout}>
<div className={cn(styles.loginLayout, 'talk-admin-login')}>
<h1 className={styles.loginHeader}>Team sign in</h1>
<p className={styles.loginCTA}>Sign in to interact with your community.</p>
{ this.state.requestPassword ? requestPasswordForm : signInForm }
@@ -7,11 +7,11 @@ import {Icon} from 'coral-ui';
import t from 'coral-framework/services/i18n';
const ApproveButton = ({active, minimal, onClick}) => {
const ApproveButton = ({active, minimal, onClick, className}) => {
const text = active ? t('modqueue.approved') : t('modqueue.approve');
return (
<button
className={cn(styles.root, {[styles.minimal]: minimal, [styles.active]: active})}
className={cn(styles.root, {[styles.minimal]: minimal, [styles.active]: active}, className)}
onClick={onClick}
>
<Icon name={'done'} className={styles.icon} />
@@ -21,6 +21,7 @@ const ApproveButton = ({active, minimal, onClick}) => {
};
ApproveButton.propTypes = {
className: PropTypes.string,
active: PropTypes.bool,
minimal: PropTypes.bool,
onClick: PropTypes.func,
@@ -1,4 +1,5 @@
import React from 'react';
import cn from 'classnames';
import PropTypes from 'prop-types';
import {Dialog} from 'coral-ui';
import styles from './BanUserDialog.css';
@@ -8,28 +9,34 @@ import t from 'coral-framework/services/i18n';
const BanUserDialog = ({open, onCancel, onPerform, username, info}) => (
<Dialog
className={styles.dialog}
className={cn(styles.dialog, 'talk-ban-user-dialog')}
id="banUserDialog"
open={open}
onCancel={onCancel}
title={t('bandialog.ban_user')}>
<span className={styles.close} onClick={onCancel}>×</span>
<div>
<div className={styles.header}>
<h2>{t('bandialog.ban_user')}</h2>
</div>
<div className={styles.separator}>
<h3>{t('bandialog.are_you_sure', username)}</h3>
<i>{info}</i>
</div>
<div className={styles.buttons}>
<Button cStyle="cancel" className={styles.cancel} onClick={onCancel} raised>
{t('bandialog.cancel')}
</Button>
<Button cStyle="black" className={styles.ban} onClick={onPerform} raised>
{t('bandialog.yes_ban_user')}
</Button>
</div>
<div className={styles.header}>
<h2>{t('bandialog.ban_user')}</h2>
</div>
<div className={styles.separator}>
<h3>{t('bandialog.are_you_sure', username)}</h3>
<i>{info}</i>
</div>
<div className={styles.buttons}>
<Button
className={cn(styles.cancel, 'talk-ban-user-dialog-button-cancel')}
cStyle="cancel"
onClick={onCancel}
raised >
{t('bandialog.cancel')}
</Button>
<Button
className={cn(styles.ban, 'talk-ban-user-dialog-button-confirm')}
cStyle="black"
onClick={onPerform}
raised >
{t('bandialog.yes_ban_user')}
</Button>
</div>
</Dialog>
);
@@ -15,7 +15,15 @@ function generateRegExp(phrases) {
.join('[\\s"?!.]+')
).join('|');
return new RegExp(`(^|[^\\w])(${inner})(?=[^\\w]|$)`, 'iu');
const pattern = `(^|[^\\w])(${inner})(?=[^\\w]|$)`;
try {
return new RegExp(pattern, 'iu');
}
catch (_err) {
// IE does not support unicode support, so we'll create one without.
return new RegExp(pattern, 'i');
}
}
// Generate a regular expression detecting `suspectWords` and `bannedWords` phrases.
@@ -21,10 +21,11 @@ class CommentDetails extends Component {
this.setState((state) => ({
showDetail: !state.showDetail
}));
this.props.clearHeightCache && this.props.clearHeightCache();
}
render() {
const {data, root, comment} = this.props;
const {data, root, comment, clearHeightCache} = this.props;
const {showDetail} = this.state;
const queryData = {
root,
@@ -44,12 +45,14 @@ class CommentDetails extends Component {
<Slot
fill="adminCommentDetailArea"
data={data}
clearHeightCache={clearHeightCache}
queryData={queryData}
more={showDetail}
/>
{showDetail && <Slot
fill="adminCommentMoreDetails"
data={data}
clearHeightCache={clearHeightCache}
queryData={queryData}
/>}
</div>
@@ -61,6 +64,7 @@ CommentDetails.propTypes = {
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
comment: PropTypes.object.isRequired,
clearHeightCache: PropTypes.func,
};
export default CommentDetails;
@@ -6,10 +6,21 @@ import FlagLabel from 'coral-ui/components/FlagLabel';
import cn from 'classnames';
import styles from './CommentLabels.css';
const staffRoles = ['ADMIN', 'STAFF', 'MODERATOR'];
function isUserFlagged(actions) {
return actions.some((action) => action.__typename === 'FlagAction' && action.user);
}
function getUserFlaggedType(actions) {
return actions
.some((action) =>
action.__typename === 'FlagAction' &&
action.user &&
action.user.roles.some((role) => staffRoles.includes(role))
) ? 'Staff' : 'User';
}
function hasSuspectedWords(actions) {
return actions.some((action) => action.__typename === 'FlagAction' && action.reason === 'Matched suspect word filter');
}
@@ -24,7 +35,7 @@ const CommentLabels = ({comment, comment: {className, status, actions, hasParent
<div className={styles.coreLabels}>
{hasParent && <Label iconName="reply" className={styles.replyLabel}>reply</Label>}
{status === 'PREMOD' && <Label iconName="query_builder" className={styles.premodLabel}>Pre-Mod</Label>}
{isUserFlagged(actions) && <FlagLabel iconName="person">User</FlagLabel>}
{isUserFlagged(actions) && <FlagLabel iconName="person">{getUserFlaggedType(actions)}</FlagLabel>}
{hasSuspectedWords(actions) && <FlagLabel iconName="sms_failed">Suspect</FlagLabel>}
{hasHistoryFlag(actions) && <FlagLabel iconName="sentiment_very_dissatisfied">History</FlagLabel>}
</div>
@@ -0,0 +1,13 @@
@custom-media --table-viewport (max-width: 1024px);
:global {
.mdl-layout__drawer-button {
visibility: hidden;
}
@media (--table-viewport) {
.mdl-layout__drawer-button {
visibility: visible;
}
}
}
@@ -5,34 +5,31 @@ import {IndexLink, Link} from 'react-router';
import styles from './Drawer.css';
import t from 'coral-framework/services/i18n';
import {can} from 'coral-framework/services/perms';
import cn from 'classnames';
const CoralDrawer = ({handleLogout, auth}) => (
<Drawer className={styles.header}>
const CoralDrawer = ({handleLogout, auth = {}}) => (
<Drawer className={cn('talk-admin-drawer-nav', styles.drawer)}>
{ auth && auth.user && can(auth.user, 'ACCESS_ADMIN') ?
<div>
<Navigation className={styles.nav}>
<IndexLink
className={styles.navLink}
to="/admin/dashboard"
activeClassName={styles.active}>
{t('configure.dashboard')}
</IndexLink>
{
can(auth.user, 'MODERATE_COMMENTS') && (
<Link
className={styles.navLink}
<IndexLink
className={cn('talk-admin-nav-moderate', styles.navLink)}
to="/admin/moderate"
activeClassName={styles.active}>
{t('configure.moderate')}
</Link>
</IndexLink>
)
}
<Link className={styles.navLink}
<Link
className={cn('talk-admin-nav-stories', styles.navLink)}
to="/admin/stories"
activeClassName={styles.active}>
{t('configure.stories')}
</Link>
<Link className={styles.navLink}
<Link
className={cn('talk-admin-nav-community', styles.navLink)}
to="/admin/community"
activeClassName={styles.active}>
{t('configure.community')}
@@ -41,7 +38,7 @@ const CoralDrawer = ({handleLogout, auth}) => (
can(auth.user, 'UPDATE_CONFIG') &&
(
<Link
className={styles.navLink}
className={cn('talk-admin-nav-configure', styles.navLink)}
to="/admin/configure"
activeClassName={styles.active}>
{t('configure.configure')}
@@ -57,7 +54,8 @@ const CoralDrawer = ({handleLogout, auth}) => (
CoralDrawer.propTypes = {
handleLogout: PropTypes.func.isRequired,
restricted: PropTypes.bool // hide app elements from a logged out user
restricted: PropTypes.bool, // hide app elements from a logged out user
auth: PropTypes.object
};
export default CoralDrawer;
@@ -21,7 +21,6 @@
.callToAction {
position: fixed;
left: 10px;
bottom: 10px;
width: 280px;
height: 200px;
@@ -29,6 +28,7 @@
padding: 15px;
box-sizing: border-box;
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.15);
z-index: 10;
.ctaHeader {
font-size: 16px;
@@ -4,32 +4,38 @@ import Modal from 'components/Modal';
import styles from './ModerationKeysModal.css';
import t from 'coral-framework/services/i18n';
const shortcuts = [
{
title: 'modqueue.navigation',
shortcuts: {
'j': 'modqueue.next_comment',
'k': 'modqueue.prev_comment',
's': 'modqueue.singleview',
'?': 'modqueue.thismenu'
}
},
{
title: 'modqueue.actions',
shortcuts: {
'd': 'modqueue.approve',
'f': 'modqueue.reject'
}
}
];
export default class ModerationKeysModal extends React.Component {
static propTypes = {
open: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
hideShortcutsNote: PropTypes.func.isRequired,
shortcutsNoteVisible: PropTypes.string.isRequired
shortcutsNoteVisible: PropTypes.string.isRequired,
queueCount: PropTypes.number.isRequired
}
buildShortcuts = () => {
return [
{
title: 'modqueue.navigation',
shortcuts: {
'j': 'modqueue.next_comment',
'k': 'modqueue.prev_comment',
'ctrl+f': 'modqueue.toggle_search',
't': 'modqueue.next_queue',
[`1...${this.props.queueCount}`]: 'modqueue.jump_to_queue',
's': 'modqueue.singleview',
'?': 'modqueue.thismenu'
}
},
{
title: 'modqueue.actions',
shortcuts: {
'd': 'modqueue.approve',
'f': 'modqueue.reject'
}
}
];
}
render () {
@@ -49,7 +55,7 @@ export default class ModerationKeysModal extends React.Component {
<Modal open={open} onClose={onClose}>
<h3>{t('modqueue.shortcuts')}</h3>
<div className={styles.container}>
{shortcuts.map((shortcut, i) => (
{this.buildShortcuts().map((shortcut, i) => (
<table className={styles.table} key={i}>
<thead>
<tr>
@@ -7,11 +7,11 @@ import {Icon} from 'coral-ui';
import t from 'coral-framework/services/i18n';
const RejectButton = ({active, minimal, onClick}) => {
const RejectButton = ({active, minimal, onClick, className}) => {
const text = active ? t('modqueue.rejected') : t('modqueue.reject');
return (
<button
className={cn(styles.root, {[styles.minimal]: minimal, [styles.active]: active})}
className={cn(styles.root, {[styles.minimal]: minimal, [styles.active]: active}, className)}
onClick={onClick}
>
<Icon name={'close'} className={styles.icon} />
@@ -21,6 +21,7 @@ const RejectButton = ({active, minimal, onClick}) => {
};
RejectButton.propTypes = {
className: PropTypes.string,
active: PropTypes.bool,
minimal: PropTypes.bool,
onClick: PropTypes.func,
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import {Dialog} from 'coral-ui';
import {RadioGroup, Radio} from 'react-mdl';
import styles from './SuspendUserDialog.css';
import cn from 'classnames';
import Button from 'coral-ui/components/Button';
@@ -87,7 +88,7 @@ class SuspendUserDialog extends React.Component {
<Button cStyle="white" className={styles.cancel} onClick={onCancel} raised>
{t('suspenduser.cancel')}
</Button>
<Button cStyle="black" className={styles.perform} onClick={this.goToStep1} raised>
<Button cStyle="black" className={cn(styles.perform, 'talk-admin-suspend-user-dialog-confirm')} onClick={this.goToStep1} raised>
{t('suspenduser.suspend_user')}
</Button>
</div>
@@ -120,7 +121,7 @@ class SuspendUserDialog extends React.Component {
</Button>
<Button
cStyle="black"
className={styles.perform}
className={cn(styles.perform, 'talk-admin-suspend-user-dialog-send')}
onClick={this.handlePerform}
disabled={this.state.message.length === 0}
raised
@@ -137,7 +138,7 @@ class SuspendUserDialog extends React.Component {
const {step} = this.state;
return (
<Dialog
className={styles.dialog}
className={cn(styles.dialog, 'talk-admin-suspend-user-dialog')}
onCancel={onCancel}
open={open}
>
+18 -2
View File
@@ -2,17 +2,25 @@ import React from 'react';
import TagsInput from 'react-tagsinput';
import styles from './TagsInput.css';
import AutosizeInput from 'react-input-autosize';
import PropTypes from 'prop-types';
import cn from 'classnames';
const autosizingRenderInput = ({onChange, value, addTag: _, ...other}) =>
<AutosizeInput type='text' onChange={onChange} value={value} {...other} />;
export default (props) => {
autosizingRenderInput.propTypes = {
onChange: PropTypes.func,
value: PropTypes.string,
addTag: PropTypes.func,
};
const TagsInputComponent = ({className = '', ...props}) => {
return (
<TagsInput
addOnBlur={true}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
className={styles.root}
className={cn(styles.root, 'tags-input', className)}
focusedClassName={styles.rootFocus}
renderInput={autosizingRenderInput}
{...props}
@@ -29,3 +37,11 @@ export default (props) => {
/>
);
};
TagsInputComponent.propTypes = {
className: PropTypes.string,
inputProps: PropTypes.object,
tagProps: PropTypes.object,
};
export default TagsInputComponent;
@@ -39,7 +39,8 @@
margin-right: 0px;
}
.statItem, .statReportResult {
.statItem,
.statReportResult {
padding: 3px 5px;
background-color: #D8D8D8;
border-radius: 3px;
@@ -48,7 +49,7 @@
font-size: 0.9em;
line-height: normal;
letter-spacing: 0.4px;
min-width: 60px;
min-width: 60px;
}
.statResult {
@@ -94,12 +95,11 @@
}
.commentStatuses {
padding: 10px 0 0 0;
padding: 0 0 0 10px;
margin: 0;
height: 52px;
align-self: center;
list-style: none;
box-sizing: border-box;
li {
display: inline-block;
margin-right: 10px;
@@ -116,11 +116,11 @@
.bulkActionGroup {
height: 52px;
background-color: #efefef;
padding: 0 0 0 10px;
display: flex;
i {
margin-right: 0;
}
.bulkAction {
display: inline-block;
width: 48px;
@@ -128,17 +128,39 @@
transform: scale(.7);
min-width: 0;
}
.bulkAction:last-child {
margin-left: -10px;
}
}
.loadMore > button {
background-color: #696969;
.selectedCommentsInfo {
align-self: center;
font-weight: 500;
margin-left: 15px;
}
.loadMore>button {
background-color: #696969;
&:hover {
background-color: #404040;
color: white;
}
}
.toggleAll {
padding: 0 10px 0 0;
align-self: center;
}
.commentList {
clear: both;
}
.bulkActionHeader {
display: flex;
justify-content: space-between;
height: 52px;
&.selected {
background-color: #efefef;
}
}
+87 -55
View File
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import Comment from '../containers/UserDetailComment';
import styles from './UserDetail.css';
import {Icon, Button, Drawer, Spinner} from 'coral-ui';
import {Icon, Drawer, Spinner} from 'coral-ui';
import {Slot} from 'coral-framework/components';
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
import ClickOutside from 'coral-framework/components/ClickOutside';
@@ -10,6 +10,9 @@ import LoadMore from '../components/LoadMore';
import cn from 'classnames';
import capitalize from 'lodash/capitalize';
import {getReliability} from 'coral-framework/utils/user';
import ApproveButton from './ApproveButton';
import RejectButton from './RejectButton';
import {getErrorMessages} from 'coral-framework/utils';
export default class UserDetail extends React.Component {
@@ -17,14 +20,22 @@ export default class UserDetail extends React.Component {
userId: PropTypes.string.isRequired,
hideUserDetail: PropTypes.func.isRequired,
root: PropTypes.object.isRequired,
bannedWords: PropTypes.array.isRequired,
suspectWords: PropTypes.array.isRequired,
acceptComment: PropTypes.func.isRequired,
rejectComment: PropTypes.func.isRequired,
changeStatus: PropTypes.func.isRequired,
toggleSelect: PropTypes.func.isRequired,
bulkAccept: PropTypes.func.isRequired,
bulkReject: PropTypes.func.isRequired,
toggleSelectAll: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired,
data: PropTypes.shape({
refetch: PropTypes.func.isRequired,
}),
activeTab: PropTypes.string.isRequired,
selectedCommentIds: PropTypes.array.isRequired,
viewUserDetail: PropTypes.any.isRequired,
loadMore: PropTypes.any.isRequired,
notify: PropTypes.func.isRequired
}
rejectThenReload = async (info) => {
@@ -33,8 +44,8 @@ export default class UserDetail extends React.Component {
this.props.data.refetch();
} catch (err) {
// TODO: handle error.
console.error(err);
this.props.notify('error', getErrorMessages(err));
}
}
@@ -44,8 +55,30 @@ export default class UserDetail extends React.Component {
this.props.data.refetch();
} catch (err) {
// TODO: handle error.
console.error(err);
this.props.notify('error', getErrorMessages(err));
}
}
bulkAcceptThenReload = async () => {
try {
await this.props.bulkAccept();
this.props.data.refetch();
} catch (err) {
console.error(err);
this.props.notify('error', getErrorMessages(err));
}
}
bulkRejectThenReload = async () => {
try {
await this.props.bulkReject();
this.props.data.refetch();
} catch (err) {
console.error(err);
this.props.notify('error', getErrorMessages(err));
}
}
@@ -79,14 +112,11 @@ export default class UserDetail extends React.Component {
},
activeTab,
selectedCommentIds,
bannedWords,
suspectWords,
toggleSelect,
bulkAccept,
bulkReject,
hideUserDetail,
viewUserDetail,
loadMore,
toggleSelectAll
} = this.props;
let rejectedPercent = (rejectedComments / totalComments) * 100;
@@ -104,14 +134,14 @@ export default class UserDetail extends React.Component {
<div>
<ul className={styles.userDetailList}>
<li>
<Icon name="assignment_ind"/>
<Icon name="assignment_ind" />
<span className={styles.userDetailItem}>Member Since:</span>
{new Date(user.created_at).toLocaleString()}
</li>
{user.profiles.map(({id}) =>
<li key={id}>
<Icon name="email"/>
<Icon name="email" />
<span className={styles.userDetailItem}>Email:</span>
{id} <ButtonCopyToClipboard className={styles.copyButton} icon="content_copy" copyText={id} />
</li>
@@ -120,24 +150,22 @@ export default class UserDetail extends React.Component {
<ul className={styles.stats}>
<li className={styles.stat}>
<span className={styles.statItem}> Total Comments </span>
<spam className={styles.statResult}> {totalComments} </spam>
<span className={styles.statItem}>Total Comments</span>
<span className={styles.statResult}>{totalComments}</span>
</li>
<li className={styles.stat}>
<spam className={styles.statItem}> Reject Rate </spam>
<spam className={styles.statResult}> {`${(rejectedPercent).toFixed(1)}%`} </spam>
<span className={styles.statItem}>Reject Rate</span>
<span className={styles.statResult}>
{rejectedPercent.toFixed(1)}%
</span>
</li>
<li className={styles.stat}>
<spam className={styles.statItem}> Reports </spam>
<spam className={cn(styles.statReportResult, styles[getReliability(user.reliable.flagger)])}>
<span className={styles.statItem}>Reports</span>
<span className={cn(styles.statReportResult, styles[getReliability(user.reliable.flagger)])}>
{capitalize(getReliability(user.reliable.flagger))}
</spam>
</span>
</li>
</ul>
<p className={styles.small}>
Data represents the last six months of activity
</p>
</div>
<Slot
@@ -145,36 +173,42 @@ export default class UserDetail extends React.Component {
data={this.props.data}
queryData={{root, user}}
/>
<hr/>
{
selectedCommentIds.length === 0
? (
<ul className={styles.commentStatuses}>
<li className={activeTab === 'all' ? styles.active : ''} onClick={this.showAll}>All</li>
<li className={activeTab === 'rejected' ? styles.active : ''} onClick={this.showRejected}>Rejected</li>
</ul>
)
: (
<div className={styles.bulkActionGroup}>
<Button
onClick={bulkAccept}
className={styles.bulkAction}
cStyle='approve'
icon='done'>
</Button>
<Button
onClick={bulkReject}
className={styles.bulkAction}
cStyle='reject'
icon='close'>
</Button>
{`${selectedCommentIds.length} comments selected`}
</div>
)
}
<div>
<hr />
<div className={(selectedCommentIds.length > 0) ? cn(styles.bulkActionHeader, styles.selected) : styles.bulkActionHeader}>
{
selectedCommentIds.length === 0
? (
<ul className={styles.commentStatuses}>
<li className={activeTab === 'all' ? styles.active : ''} onClick={this.showAll}>All</li>
<li className={activeTab === 'rejected' ? styles.active : ''} onClick={this.showRejected}>Rejected</li>
</ul>
)
: (
<div className={styles.bulkActionGroup}>
<ApproveButton
onClick={this.bulkAcceptThenReload}
minimal
/>
<RejectButton
onClick={this.bulkRejectThenReload}
minimal
/>
<span className={styles.selectedCommentsInfo}> {selectedCommentIds.length} comments selected</span>
</div>
)
}
<div className={styles.toggleAll}>
<input
type='checkbox'
id='toogleAll'
checked={selectedCommentIds.length > 0 && selectedCommentIds.length === nodes.length}
onChange={(e) => {
toggleSelectAll(nodes.map((comment) => comment.id), e.target.checked);
}} />
<label htmlFor='toogleAll'>Select all</label>
</div>
</div>
<div className={styles.commentList}>
{
nodes.map((comment) => {
const selected = selectedCommentIds.indexOf(comment.id) !== -1;
@@ -184,8 +218,6 @@ export default class UserDetail extends React.Component {
root={root}
data={data}
comment={comment}
suspectWords={suspectWords}
bannedWords={bannedWords}
acceptComment={this.acceptThenReload}
rejectComment={this.rejectThenReload}
selected={selected}
@@ -205,7 +237,7 @@ export default class UserDetail extends React.Component {
);
}
render () {
render() {
if (this.props.loading) {
return this.renderLoading();
}
@@ -30,12 +30,11 @@ class UserDetailComment extends React.Component {
render() {
const {
comment,
suspectWords,
bannedWords,
selected,
toggleSelect,
className,
data,
root: {settings: {wordlist: {banned, suspect}}},
} = this.props;
return (
@@ -72,8 +71,8 @@ class UserDetailComment extends React.Component {
<div className={styles.bodyContainer}>
<div className={styles.body}>
<CommentBodyHighlighter
suspectWords={suspectWords}
bannedWords={bannedWords}
suspectWords={suspect}
bannedWords={banned}
body={comment.body}
/>
{' '}
@@ -123,9 +122,15 @@ UserDetailComment.propTypes = {
acceptComment: PropTypes.func.isRequired,
rejectComment: PropTypes.func.isRequired,
className: PropTypes.string,
suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired,
bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired,
toggleSelect: PropTypes.func,
root: PropTypes.shape({
settings: PropTypes.shape({
wordlist: PropTypes.shape({
suspect: PropTypes.arrayOf(PropTypes.string).isRequired,
banned: PropTypes.arrayOf(PropTypes.string).isRequired,
}),
}),
}),
comment: PropTypes.shape({
id: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
@@ -136,8 +141,8 @@ UserDetailComment.propTypes = {
title: PropTypes.string,
url: PropTypes.string,
id: PropTypes.string
})
})
}),
}),
};
export default UserDetailComment;
@@ -15,20 +15,25 @@
}
}
.headerWrapper {
background-color: #696969;
}
.header {
background-color: transparent;
box-shadow: none;
min-height: 58px;
display: block;
max-width: 1280px;
margin: 0 auto;
background-color: #696969;
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
}
.header > div {
background-color: #696969;
position: relative;
padding: 0;
min-width: 1280px;
max-width: 1280px;
margin: 0 auto;
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
height: 58px;
}
+80 -84
View File
@@ -1,4 +1,5 @@
import React from 'react';
import cn from 'classnames';
import PropTypes from 'prop-types';
import {Navigation, Header, IconButton, MenuItem, Menu} from 'react-mdl';
import {Link, IndexLink} from 'react-router';
@@ -15,93 +16,88 @@ const CoralHeader = ({
root
}) => {
return (
<Header className={styles.header}>
<Logo className={styles.logo} />
<div>
{
auth && auth.user && can(auth.user, 'ACCESS_ADMIN') ?
<Navigation className={styles.nav}>
<IndexLink
id='dashboardNav'
className={styles.navLink}
to="/admin/dashboard"
activeClassName={styles.active}>
{t('configure.dashboard')}
</IndexLink>
{
can(auth.user, 'MODERATE_COMMENTS') && (
<Link
id='moderateNav'
className={styles.navLink}
to="/admin/moderate"
activeClassName={styles.active}>
{t('configure.moderate')}
{(root.premodCount !== 0 || root.reportedCount !== 0) && <Indicator />}
</Link>
)
}
<Link
id='streamsNav'
className={styles.navLink}
to="/admin/stories"
activeClassName={styles.active}>
{t('configure.stories')}
</Link>
<div className={styles.headerWrapper}>
<Header className={styles.header}>
<Logo className={styles.logo} />
<div>
{
auth && auth.user && can(auth.user, 'ACCESS_ADMIN') ?
<Navigation className={styles.nav}>
{
can(auth.user, 'MODERATE_COMMENTS') && (
<IndexLink
id='moderateNav'
className={cn('talk-admin-nav-moderate', styles.navLink)}
to="/admin/moderate"
activeClassName={styles.active}>
{t('configure.moderate')}
{(root.premodCount !== 0 || root.reportedCount !== 0) && <Indicator />}
</IndexLink>
)
}
<Link
id='storiesNav'
className={cn('talk-admin-nav-stories', styles.navLink)}
to="/admin/stories"
activeClassName={styles.active}>
{t('configure.stories')}
</Link>
<Link
id='communityNav'
className={styles.navLink}
to="/admin/community"
activeClassName={styles.active}>
{t('configure.community')}
{root.flaggedUsernamesCount !== 0 && <Indicator />}
</Link>
<Link
id='communityNav'
className={cn('talk-admin-nav-community', styles.navLink)}
to="/admin/community"
activeClassName={styles.active}>
{t('configure.community')}
{root.flaggedUsernamesCount !== 0 && <Indicator />}
</Link>
{
can(auth.user, 'UPDATE_CONFIG') && (
<Link
id='configureNav'
className={styles.navLink}
to="/admin/configure"
activeClassName={styles.active}>
{t('configure.configure')}
</Link>
)
}
</Navigation>
:
null
}
<div className={styles.rightPanel}>
<ul>
<li className={styles.settings}>
<div>
<IconButton name="settings" id="menu-settings"/>
<Menu target="menu-settings" align="right">
<MenuItem onClick={() => showShortcuts(true)}>{t('configure.shortcuts')}</MenuItem>
<MenuItem>
<a href="https://github.com/coralproject/talk/releases" target="_blank" rel="noopener noreferrer">
View latest version
</a>
</MenuItem>
<MenuItem>
<a href="https://coralproject.net/contribute.html#other-ideas-and-bug-reports" target="_blank" rel="noopener noreferrer">
Report a bug or give feedback
</a>
</MenuItem>
<MenuItem onClick={handleLogout}>
{t('configure.sign_out')}
</MenuItem>
</Menu>
</div>
</li>
<li>
{`v${process.env.VERSION}`}
</li>
</ul>
{
can(auth.user, 'UPDATE_CONFIG') && (
<Link
id='configureNav'
className={cn('talk-admin-nav-configure', styles.navLink)}
to="/admin/configure"
activeClassName={styles.active}>
{t('configure.configure')}
</Link>
)
}
</Navigation>
:
null
}
<div className={styles.rightPanel}>
<ul>
<li className={cn(styles.settings, 'talk-admin-header-settings')}>
<div>
<IconButton name="settings" id="menu-settings" className="talk-admin-header-settings-button"/>
<Menu target="menu-settings" align="right">
<MenuItem onClick={() => showShortcuts(true)}>{t('configure.shortcuts')}</MenuItem>
<MenuItem>
<a href="https://github.com/coralproject/talk/releases" target="_blank" rel="noopener noreferrer">
View latest version
</a>
</MenuItem>
<MenuItem>
<a href="https://support.coralproject.net" target="_blank" rel="noopener noreferrer">
Report a bug or give feedback
</a>
</MenuItem>
<MenuItem onClick={handleLogout} className="talk-admin-header-sign-out">
{t('configure.sign_out')}
</MenuItem>
</Menu>
</div>
</li>
<li>
{`v${process.env.VERSION}`}
</li>
</ul>
</div>
</div>
</div>
</Header>
</Header>
</div>
);
};
@@ -1,5 +1,4 @@
.layout {
max-width: 1280px;
margin: 0 auto;
background-color: #FAFAFA;
margin: 0 auto;
background-color: #FAFAFA;
}
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import {Layout as LayoutMDL} from 'react-mdl';
import Header from '../../containers/Header';
import Drawer from './Drawer';
import Drawer from '../Drawer';
import styles from './Layout.css';
const Layout = ({
@@ -21,6 +21,7 @@ const Layout = ({
<Drawer
handleLogout={handleLogout}
restricted={restricted}
auth={auth}
/>
<div className={styles.layout}>
{children}
@@ -20,7 +20,6 @@
background: #696969;
height: 100%;
width: 128px;
z-index: 10;
border-right: 1px #757575 solid;
}
@@ -1,9 +0,0 @@
export const FETCH_ASSETS_REQUEST = 'FETCH_ASSETS_REQUEST';
export const FETCH_ASSETS_SUCCESS = 'FETCH_ASSETS_SUCCESS';
export const FETCH_ASSETS_FAILURE = 'FETCH_ASSETS_FAILURE';
export const UPDATE_ASSET_STATE_REQUEST = 'UPDATE_ASSET_STATE_REQUEST';
export const UPDATE_ASSET_STATE_SUCCESS = 'UPDATE_ASSET_STATE_SUCCESS';
export const UPDATE_ASSET_STATE_FAILURE = 'UPDATE_ASSET_STATE_FAILURE';
export const UPDATE_ASSETS = 'UPDATE_ASSETS';
+19 -14
View File
@@ -1,17 +1,22 @@
export const FETCH_COMMENTERS_REQUEST = 'FETCH_COMMENTERS_REQUEST';
export const FETCH_COMMENTERS_SUCCESS = 'FETCH_COMMENTERS_SUCCESS';
export const FETCH_COMMENTERS_FAILURE = 'FETCH_COMMENTERS_FAILURE';
export const SORT_UPDATE = 'SORT_UPDATE';
export const COMMENTERS_NEW_PAGE = 'COMMENTERS_NEW_PAGE';
export const SET_ROLE = 'SET_ROLE';
export const SET_COMMENTER_STATUS = 'SET_COMMENTER_STATUS';
const prefix = 'COMMUNITY';
export const FETCH_FLAGGED_COMMENTERS_REQUEST = 'FETCH_FLAGGED_COMMENTERS_REQUEST';
export const FETCH_FLAGGED_COMMENTERS_SUCCESS = 'FETCH_FLAGGED_COMMENTERS_SUCCESS';
export const FETCH_FLAGGED_COMMENTERS_FAILURE = 'FETCH_FLAGGED_COMMENTERS_FAILURE';
export const FETCH_USERS_REQUEST = `${prefix}_FETCH_USERS_REQUEST`;
export const FETCH_USERS_SUCCESS = `${prefix}_FETCH_USERS_SUCCESS`;
export const FETCH_USERS_FAILURE = `${prefix}_FETCH_USERS_FAILURE`;
export const SHOW_BANUSER_DIALOG = 'SHOW_BANUSER_DIALOG';
export const HIDE_BANUSER_DIALOG = 'HIDE_BANUSER_DIALOG';
export const SORT_UPDATE = `${prefix}_SORT_UPDATE`;
export const SET_PAGE = `${prefix}_SET_PAGE`;
export const SET_ROLE = `${prefix}_SET_ROLE`;
export const SET_COMMENTER_STATUS = `${prefix}_SET_COMMENTER_STATUS`;
export const SHOW_REJECT_USERNAME_DIALOG = 'SHOW_REJECT_USERNAME_DIALOG';
export const HIDE_REJECT_USERNAME_DIALOG = 'HIDE_REJECT_USERNAME_DIALOG';
export const FETCH_FLAGGED_COMMENTERS_REQUEST = `${prefix}_FETCH_FLAGGED_COMMENTERS_REQUEST`;
export const FETCH_FLAGGED_COMMENTERS_SUCCESS = `${prefix}_FETCH_FLAGGED_COMMENTERS_SUCCESS`;
export const FETCH_FLAGGED_COMMENTERS_FAILURE = `${prefix}_FETCH_FLAGGED_COMMENTERS_FAILURE`;
export const SHOW_BANUSER_DIALOG = `${prefix}_SHOW_BANUSER_DIALOG`;
export const HIDE_BANUSER_DIALOG = `${prefix}_HIDE_BANUSER_DIALOG`;
export const SHOW_REJECT_USERNAME_DIALOG = `${prefix}_SHOW_REJECT_USERNAME_DIALOG`;
export const HIDE_REJECT_USERNAME_DIALOG = `${prefix}_HIDE_REJECT_USERNAME_DIALOG`;
export const SET_SEARCH_VALUE = `${prefix}_SET_SEARCH_VALUE`;
@@ -0,0 +1,5 @@
const prefix = 'TALK_ADMIN_CONFIGURE';
export const UPDATE_PENDING = `${prefix}_UPDATE_PENDING`;
export const CLEAR_PENDING = `${prefix}_CLEAR_PENDING`;
export const SET_ACTIVE_SECTION = `${prefix}_SET_ACTIVE_SECTION`;
@@ -6,3 +6,4 @@ export const SHOW_STORY_SEARCH = 'SHOW_STORY_SEARCH';
export const HIDE_STORY_SEARCH = 'HIDE_STORY_SEARCH';
export const STORY_SEARCH_CHANGE_VALUE = 'STORY_SEARCH_CHANGE_VALUE';
export const MODERATION_CLEAR_STATE = 'MODERATION_CLEAR_STATE';
export const MODERATION_SELECT_COMMENT = 'MODERATION_SELECT_COMMENT';
@@ -0,0 +1,15 @@
const prefix = 'STORIES';
export const FETCH_ASSETS_REQUEST = `${prefix}_FETCH_ASSETS_REQUEST`;
export const FETCH_ASSETS_SUCCESS = `${prefix}_FETCH_ASSETS_SUCCESS`;
export const FETCH_ASSETS_FAILURE = `${prefix}_FETCH_ASSETS_FAILURE`;
export const UPDATE_ASSET_STATE_REQUEST = `${prefix}_UPDATE_ASSET_STATE_REQUEST`;
export const UPDATE_ASSET_STATE_SUCCESS = `${prefix}_UPDATE_ASSET_STATE_SUCCESS`;
export const UPDATE_ASSET_STATE_FAILURE = `${prefix}_UPDATE_ASSET_STATE_FAILURE`;
export const UPDATE_ASSETS = `${prefix}_UPDATE_ASSETS`;
export const SET_PAGE = `${prefix}_SET_PAGE`;
export const SET_SEARCH_VALUE = `${prefix}_SET_SEARCH_VALUE`;
export const SET_CRITERIA = `${prefix}_SET_CRITERIA`;
@@ -4,4 +4,4 @@ export const CHANGE_USER_DETAIL_STATUSES = 'CHANGE_USER_DETAIL_STATUSES';
export const SELECT_USER_DETAIL_COMMENT = 'SELECT_USER_DETAIL_COMMENT';
export const UNSELECT_USER_DETAIL_COMMENT = 'UNSELECT_USER_DETAIL_COMMENT';
export const CLEAR_USER_DETAIL_SELECTIONS = 'CLEAR_USER_DETAIL_SELECTIONS';
export const SELECT_ALL_USER_DETAIL_COMMENT = 'SELECT_ALL_USER_DETAIL_COMMENT';
@@ -25,6 +25,7 @@ export default withFragments({
}
user {
id
roles
}
}
${getSlotFragmentSpreads(slots, 'comment')}
+1 -1
View File
@@ -19,6 +19,6 @@ export default withQuery(gql`
}
`, {
options: {
pollInterval: 5000
pollInterval: 10000
}
})(Header);
@@ -1,4 +1,5 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import SuspendUserDialog from '../components/SuspendUserDialog';
@@ -44,6 +45,12 @@ class SuspendUserDialogContainer extends Component {
}
}
SuspendUserDialogContainer.propTypes = {
open: PropTypes.bool,
hideSuspendUserDialog: PropTypes.func,
username: PropTypes.string,
};
const withOrganizationName = withQuery(gql`
query CoralAdmin_SuspendUserDialog {
__typename
+15 -17
View File
@@ -11,13 +11,15 @@ import {
changeUserDetailStatuses,
clearUserDetailSelections,
toggleSelectCommentInUserDetail,
toggleSelectAllCommentInUserDetail
} from 'coral-admin/src/actions/userDetail';
import {withSetCommentStatus} from 'coral-framework/graphql/mutations';
import UserDetailComment from './UserDetailComment';
import update from 'immutability-helper';
import {notify} from 'coral-framework/actions/notification';
const commentConnectionFragment = gql`
fragment CoralAdmin_Moderation_CommentConnection on CommentConnection {
fragment CoralAdmin_UserDetail_CommentConnection on CommentConnection {
nodes {
...${getDefinitionName(UserDetailComment.fragments.comment)}
}
@@ -41,22 +43,16 @@ class UserDetailContainer extends React.Component {
return this.props.setCommentStatus({commentId, status});
});
try {
await Promise.all(changes);
this.props.clearUserDetailSelections(); // un-select everything
} catch (err) {
// TODO: handle error.
console.error(err);
}
await Promise.all(changes);
this.props.clearUserDetailSelections(); // un-select everything
}
bulkReject = () => {
this.bulkSetCommentStatus('REJECTED');
return this.bulkSetCommentStatus('REJECTED');
}
bulkAccept = () => {
this.bulkSetCommentStatus('ACCEPTED');
return this.bulkSetCommentStatus('ACCEPTED');
}
acceptComment = ({commentId}) => {
@@ -120,6 +116,7 @@ class UserDetailContainer extends React.Component {
bulkAccept={this.bulkAccept}
changeStatus={this.props.changeUserDetailStatuses}
toggleSelect={this.props.toggleSelectCommentInUserDetail}
toggleSelectAll={this.props.toggleSelectAllCommentInUserDetail}
acceptComment={this.acceptComment}
rejectComment={this.rejectComment}
loading={loading}
@@ -131,7 +128,7 @@ class UserDetailContainer extends React.Component {
const LOAD_MORE_QUERY = gql`
query CoralAdmin_Moderation_LoadMore($limit: Int = 10, $cursor: Cursor, $author_id: ID!, $statuses: [COMMENT_STATUS!]) {
comments(query: {limit: $limit, cursor: $cursor, author_id: $author_id, statuses: $statuses}) {
...CoralAdmin_Moderation_CommentConnection
...CoralAdmin_UserDetail_CommentConnection
}
}
${commentConnectionFragment}
@@ -152,13 +149,13 @@ export const withUserDetailQuery = withQuery(gql`
}
${getSlotFragmentSpreads(slots, 'user')}
}
totalComments: commentCount(query: {author_id: $author_id})
totalComments: commentCount(query: {author_id: $author_id, statuses: []})
rejectedComments: commentCount(query: {author_id: $author_id, statuses: [REJECTED]})
comments: comments(query: {
author_id: $author_id,
statuses: $statuses
}) {
...CoralAdmin_Moderation_CommentConnection
...CoralAdmin_UserDetail_CommentConnection
}
...${getDefinitionName(UserDetailComment.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
@@ -168,7 +165,8 @@ export const withUserDetailQuery = withQuery(gql`
`, {
options: ({userId, statuses}) => {
return {
variables: {author_id: userId, statuses}
variables: {author_id: userId, statuses},
fetchPolicy: 'network-only',
};
},
skip: (ownProps) => !ownProps.userId,
@@ -179,8 +177,6 @@ const mapStateToProps = (state) => ({
selectedCommentIds: state.userDetail.selectedCommentIds,
statuses: state.userDetail.statuses,
activeTab: state.userDetail.activeTab,
bannedWords: state.settings.wordlist.banned,
suspectWords: state.settings.wordlist.suspect,
});
const mapDispatchToProps = (dispatch) => ({
@@ -190,6 +186,8 @@ const mapDispatchToProps = (dispatch) => ({
toggleSelectCommentInUserDetail,
viewUserDetail,
hideUserDetail,
toggleSelectAllCommentInUserDetail,
notify
}, dispatch)
});
@@ -8,7 +8,12 @@ import CommentDetails from './CommentDetails';
export default withFragments({
root: gql`
fragment CoralAdmin_UserDetailComment_root on RootQuery {
__typename
settings {
wordlist {
banned
suspect
}
}
...${getDefinitionName(CommentLabels.fragments.root)}
...${getDefinitionName(CommentDetails.fragments.root)}
}
+11
View File
@@ -1,4 +1,5 @@
import update from 'immutability-helper';
import {mapLeaves} from 'coral-framework/utils';
export default {
mutations: {
@@ -29,6 +30,16 @@ export default {
}
}
}),
UpdateSettings: ({variables: {input}}) => ({
updateQueries: {
TalkAdmin_Configure: (prev) => {
const updated = update(prev, {
settings: mapLeaves(input, (leaf) => ({$set: leaf})),
});
return updated;
}
}
}),
},
};
+1
View File
@@ -23,6 +23,7 @@ function init({store, storage}) {
async function main() {
const notification = createNotificationService(toast);
const context = await createContext({reducers, graphqlExtension, pluginsConfig, notification, init});
render(
<TalkProvider {...context}>
<App />
-40
View File
@@ -1,40 +0,0 @@
import * as actions from '../constants/assets';
import update from 'immutability-helper';
const initialState = {
byId: {},
ids: [],
assets: []
};
export default function assets (state = initialState, action) {
switch (action.type) {
case actions.FETCH_ASSETS_SUCCESS: {
const assets = action.assets.reduce((prev, curr) => {
prev[curr.id] = curr;
return prev;
}, {});
return update(state, {
byId: {$set: assets},
count: {$set: action.count},
ids: {$set: Object.keys(assets)},
});
}
case actions.UPDATE_ASSET_STATE_REQUEST:
return update(state, {
byId: {
[action.id]: {
closedAt: {$set: action.closedAt},
},
},
});
case actions.UPDATE_ASSETS:
return update(state, {
assets: {$set: action.assets},
});
default:
return state;
}
}
+26 -13
View File
@@ -1,8 +1,10 @@
import {
FETCH_COMMENTERS_REQUEST,
FETCH_COMMENTERS_FAILURE,
FETCH_COMMENTERS_SUCCESS,
FETCH_USERS_REQUEST,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE,
SORT_UPDATE,
SET_PAGE,
SET_SEARCH_VALUE,
SET_ROLE,
SET_COMMENTER_STATUS,
SHOW_BANUSER_DIALOG,
@@ -15,7 +17,8 @@ const initialState = {
community: {},
isFetchingPeople: false,
errorPeople: '',
accounts: [],
users: [],
searchValue: '',
fieldPeople: 'created_at',
ascPeople: false,
totalPagesPeople: 0,
@@ -27,19 +30,19 @@ const initialState = {
export default function community (state = initialState, action) {
switch (action.type) {
case FETCH_COMMENTERS_REQUEST :
case FETCH_USERS_REQUEST :
return {
...state,
isFetchingPeople: true,
};
case FETCH_COMMENTERS_FAILURE :
case FETCH_USERS_FAILURE :
return {
...state,
isFetchingPeople: false,
errorPeople: action.error,
};
case FETCH_COMMENTERS_SUCCESS : {
const {accounts, type, page, count, limit, totalPages, ...rest} = action; // eslint-disable-line
case FETCH_USERS_SUCCESS : {
const {users, type, page, count, limit, totalPages, ...rest} = action; // eslint-disable-line
return {
...state,
isFetchingPeople: false,
@@ -49,27 +52,32 @@ export default function community (state = initialState, action) {
limitPeople: limit,
totalPagesPeople: totalPages,
...rest,
accounts, // Sets to normal array
users, // Sets to normal array
};
}
case SET_PAGE:
return {
...state,
pagePeople: action.page,
};
case SET_ROLE : {
const commenters = state.accounts;
const commenters = state.users;
const idx = commenters.findIndex((el) => el.id === action.id);
commenters[idx].roles[0] = action.role;
return {
...state,
accounts: commenters.map((id) => id),
users: commenters.map((id) => id),
};
}
case SET_COMMENTER_STATUS: {
const commenters = state.accounts;
const commenters = state.users;
const idx = commenters.findIndex((el) => el.id === action.id);
commenters[idx].status = action.status;
return {
...state,
accounts: commenters.map((id) => id),
users: commenters.map((id) => id),
};
}
@@ -101,6 +109,11 @@ export default function community (state = initialState, action) {
user: action.user,
rejectUsernameDialog: true
};
case SET_SEARCH_VALUE:
return {
...state,
searchValue: action.value,
};
default :
return state;
}
@@ -0,0 +1,47 @@
import * as actions from '../constants/configure';
import isEmpty from 'lodash/isEmpty';
import update from 'immutability-helper';
const initialState = {
canSave: false,
pending: {},
errors: {},
activeSection: 'stream',
};
export default function configure(state = initialState, action) {
switch (action.type) {
case actions.UPDATE_PENDING: {
let next = state;
if (action.updater) {
next = update(next, {
pending: action.updater,
});
}
if (action.errorUpdater) {
next = update(next, {
errors: action.errorUpdater,
});
}
const noErrors = Object.keys(next.errors).reduce((res, error) => res && !next.errors[error], true);
const canSave = !isEmpty(next.pending) && noErrors;
next = update(next, {
canSave: {$set: canSave},
});
return next;
}
case actions.CLEAR_PENDING:
return {
...state,
pending: {},
canSave: false,
};
case actions.SET_ACTIVE_SECTION:
return {
...state,
activeSection: action.section,
};
}
return state;
}
+4 -4
View File
@@ -1,6 +1,6 @@
import auth from './auth';
import assets from './assets';
import settings from './settings';
import stories from './stories';
import configure from './configure';
import community from './community';
import moderation from './moderation';
import install from './install';
@@ -12,10 +12,10 @@ import userDetail from './userDetail';
export default {
auth,
banUserDialog,
configure,
suspendUserDialog,
userDetail,
assets,
settings,
stories,
community,
moderation,
install,
@@ -7,6 +7,7 @@ const initialState = {
storySearchString: '',
shortcutsNoteVisible: 'show',
sortOrder: 'DESC',
selectedCommentId: '',
};
export default function moderation (state = initialState, action) {
@@ -51,6 +52,11 @@ export default function moderation (state = initialState, action) {
...state,
sortOrder: action.order,
};
case actions.MODERATION_SELECT_COMMENT:
return {
...state,
selectedCommentId: action.id,
};
default:
return state;
}
@@ -1,92 +0,0 @@
import * as actions from '../actions/settings';
import update from 'immutability-helper';
// this is initialized here because
// currently you have to reload the dashboard to get new stats
// cleaner updates are planned in the future.
// TODO: if there are more than two fields for the dashboard being created here,
// please create a new reducer specifically for the Dashboard.
const DASHBOARD_WINDOW_MINUTES = 5;
let then = new Date();
then.setMinutes(then.getMinutes() - DASHBOARD_WINDOW_MINUTES);
const initialState = {
wordlist: {
banned: [],
suspect: []
},
dashboardWindowStart: then.toISOString(),
dashboardWindowEnd: new Date().toISOString(),
domains: {
whitelist: []
},
saveSettingsError: null,
fetchSettingsError: null,
fetchingSettings: false
};
export default function settings (state = initialState, action) {
switch (action.type) {
case actions.SETTINGS_LOADING:
return {
...state,
fetchingSettings: true,
fetchSettingsError: null,
};
case actions.SETTINGS_RECEIVED:
return {
...state,
fetchingSettings: false,
fetchSettingsError: null,
...action.settings
};
case actions.SETTINGS_FETCH_ERROR:
return {
...state,
fetchingSettings: false,
fetchSettingsError: action.error,
};
case actions.SETTINGS_UPDATED:
return {
...state,
fetchingSettings: false,
fetchSettingsError: null,
...action.settings
};
case actions.SAVE_SETTINGS_LOADING:
return {
...state,
fetchingSettings: true,
saveSettingsError: null,
};
case actions.SAVE_SETTINGS_SUCCESS:
return {
...state,
fetchingSettings: false,
fetchSettingsError: null,
...action.settings
};
case actions.SAVE_SETTINGS_FAILED:
return {
...state,
fetchingSettings: false,
fetchSettingsError: action.error,
};
case actions.WORDLIST_UPDATED:
return update(state, {
wordlist: {
[action.listName]: {
$set: action.list
}
}
});
case actions.DOMAINLIST_UPDATED:
return update(state, {
domains: {
[action.listName]: {$set: action.list},
}
});
default:
return state;
}
}
@@ -0,0 +1,73 @@
import * as actions from '../constants/stories';
import update from 'immutability-helper';
const initialState = {
assets: {
byId: {},
ids: [],
assets: []
},
searchValue: '',
criteria: {
asc: 'false',
filter: 'all',
},
};
export default function assets (state = initialState, action) {
switch (action.type) {
case actions.FETCH_ASSETS_SUCCESS: {
const assets = action.assets.reduce((prev, curr) => {
prev[curr.id] = curr;
return prev;
}, {});
return update(state, {
assets: {
totalPages: {$set: action.totalPages},
page: {$set: action.page},
byId: {$set: assets},
count: {$set: action.count},
ids: {$set: Object.keys(assets)},
},
});
}
case actions.UPDATE_ASSET_STATE_REQUEST:
return update(state, {
assets: {
byId: {
[action.id]: {
closedAt: {$set: action.closedAt},
},
},
},
});
case actions.UPDATE_ASSETS:
return update(state, {
assets: {
assets: {$set: action.assets},
},
});
case actions.SET_PAGE:
return {
...state,
page: action.page,
};
case actions.SET_SEARCH_VALUE:
return {
...state,
searchValue: action.value,
};
case actions.SET_CRITERIA:
return {
...state,
criteria: {
...state.criteria,
...action.criteria,
},
};
default:
return state;
}
}
@@ -41,6 +41,11 @@ export default function banUserDialog(state = initialState, action) {
...state,
selectedCommentIds: state.selectedCommentIds.filter((id) => id !== action.id),
};
case actions.SELECT_ALL_USER_DETAIL_COMMENT:
return {
...state,
selectedCommentIds: action.ids
};
default:
return state;
}
@@ -0,0 +1,4 @@
.container {
max-width: 1280px;
margin: 0 auto;
}
@@ -1,78 +1,18 @@
import React, {Component} from 'react';
import CommunityMenu from './CommunityMenu';
import People from './People';
import FlaggedAccounts from '../containers/FlaggedAccounts';
import RejectUsernameDialog from './RejectUsernameDialog';
import PropTypes from 'prop-types';
import styles from './Community.css';
import People from '../containers/People';
import CommunityMenu from './CommunityMenu';
import RejectUsernameDialog from './RejectUsernameDialog';
import FlaggedAccounts from '../containers/FlaggedAccounts';
export default class Community extends Component {
state = {
searchValue: '',
timer: null
};
onKeyDownHandler = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
this.search();
}
}
onSearchChange = (e) => {
const value = e.target.value;
this.setState((prevState) => {
prevState.searchValue = value;
clearTimeout(prevState.timer);
const fetchAccounts = this.props.fetchAccounts;
prevState.timer = setTimeout(() => {
fetchAccounts({value});
}, 350);
return prevState;
});
}
onHeaderClickHandler = (sort) => {
this.props.updateSorting(sort);
this.search();
}
onNewPageHandler = (page) => {
this.props.newPage(page);
this.search({page});
}
search(query = {}) {
const {community} = this.props;
this.props.fetchAccounts({
value: this.state.searchValue,
field: community.fieldPeople,
asc: community.ascPeople,
...query
});
}
getTabContent(searchValue, props) {
const {community} = props;
const activeTab = props.route.path === ':id' ? 'flagged' : props.route.path;
class Community extends Component {
renderTab() {
const {route, community, ...props} = this.props;
const activeTab = route.path === ':id' ? 'flagged' : route.path;
if (activeTab === 'people') {
return (
<People
isFetching={community.isFetchingPeople}
commenters={community.accounts}
searchValue={searchValue}
onSearchChange={this.onSearchChange}
error={community.errorPeople}
totalPages={community.totalPagesPeople}
page={community.pagePeople}
onKeyDown={this.onKeyDownHandler}
onHeaderClickHandler={this.onHeaderClickHandler}
onNewPageHandler={this.onNewPageHandler}
/>
);
return <People community={community} />;
}
return (
@@ -82,37 +22,36 @@ export default class Community extends Component {
root={this.props.root}
/>
<RejectUsernameDialog
open={community.rejectUsernameDialog}
handleClose={props.hideRejectUsernameDialog}
user={community.user}
open={community.rejectUsernameDialog}
rejectUsername={props.rejectUsername}
handleClose={props.hideRejectUsernameDialog}
/>
</div>
);
}
render() {
const {searchValue} = this.state;
const tab = this.getTabContent(searchValue, this.props);
const {root: {flaggedUsernamesCount}} = this.props;
return (
<div>
<div className="talk-admin-community">
<CommunityMenu flaggedUsernamesCount={flaggedUsernamesCount} />
<div>{tab}</div>
<div className={styles.container}>
{this.renderTab()}
</div>
</div>
);
}
}
Community.propTypes = {
community: PropTypes.object,
fetchAccounts: PropTypes.func,
hideRejectUsernameDialog: PropTypes.func,
updateSorting: PropTypes.func,
newPage: PropTypes.func,
route: PropTypes.object,
rejectUsername: PropTypes.func,
community: PropTypes.object,
rejectUsername: PropTypes.func.isRequired,
hideRejectUsernameDialog: PropTypes.func.isRequired,
data: PropTypes.object,
root: PropTypes.object
root: PropTypes.object,
};
export default Community;
@@ -13,11 +13,11 @@ const CommunityMenu = ({flaggedUsernamesCount = 0}) => {
<div className='mdl-tabs'>
<div className={`mdl-tabs__tab-bar ${styles.tabBar}`}>
<div>
<Link to={flaggedPath} className={`mdl-tabs__tab ${styles.tab}`} activeClassName={styles.active}>
<Link to={flaggedPath} className={`mdl-tabs__tab ${styles.tab} talk-admin-nav-flagged-accounts`} activeClassName={styles.active}>
{t('community.flaggedaccounts')}
<CountBadge count={flaggedUsernamesCount} />
</Link>
<Link to={peoplePath} className={`mdl-tabs__tab ${styles.tab}`} activeClassName={styles.active}>
<Link to={peoplePath} className={`mdl-tabs__tab ${styles.tab} talk-admin-nav-people`} activeClassName={styles.active}>
{t('community.people')}
</Link>
</div>
@@ -2,6 +2,8 @@
padding: 10px;
display: flex;
padding-bottom: 200px;
max-width: 1280px;
margin: 0 auto;
}
.mainFlaggedContent {
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import t from 'coral-framework/services/i18n';
import EmptyCard from 'coral-admin/src/components/EmptyCard';
import LoadMore from '../../../components/LoadMore';
@@ -23,7 +24,7 @@ class FlaggedAccounts extends React.Component {
const hasResults = users.nodes && !!users.nodes.length;
return (
<div className={styles.container}>
<div className={cn('talk-adnin-community-flagged-accounts', styles.container)}>
<div className={styles.mainFlaggedContent}>
{
hasResults
@@ -70,4 +71,15 @@ class FlaggedAccounts extends React.Component {
}
}
FlaggedAccounts.propTypes = {
users: PropTypes.object,
loadMore: PropTypes.func,
showBanUserDialog: PropTypes.func,
showSuspendUserDialog: PropTypes.func,
showRejectUsernameDialog: PropTypes.func,
approveUser: PropTypes.func,
me: PropTypes.object,
viewUserDetail: PropTypes.func,
};
export default FlaggedAccounts;
@@ -1,18 +1,14 @@
import React from 'react';
import styles from './FlaggedUser.css';
// TODO: Should not rely on plugin.
import PropTypes from 'prop-types';
import cn from 'classnames';
import t from 'coral-framework/services/i18n';
import {username} from 'talk-plugin-flags/helpers/flagReasons';
import ActionsMenu from 'coral-admin/src/components/ActionsMenu';
import ActionsMenuItem from 'coral-admin/src/components/ActionsMenuItem';
import ApproveButton from 'coral-admin/src/components/ApproveButton';
import RejectButton from 'coral-admin/src/components/RejectButton';
import cn from 'classnames';
import t from 'coral-framework/services/i18n';
// TODO: Should work with custom flags too.
const shortReasons = {
[username.other]: t('community.other'),
[username.spam]: t('community.spam_ads'),
@@ -21,7 +17,6 @@ const shortReasons = {
[username.impersonating]: t('community.impersonating'),
};
// Render a single user for the list
class User extends React.Component {
showSuspenUserDialog = () => this.props.showSuspendUserDialog({
@@ -50,12 +45,10 @@ class User extends React.Component {
} = this.props;
return (
<li
tabIndex={0}
className={cn(className, styles.root, {[styles.rootSelected]: selected})}
>
<div className={styles.container}>
<div className={styles.header}>
<li tabIndex={0}
className={cn(className, styles.root, {[styles.rootSelected]: selected})} >
<div className={cn('talk-admin-community-flagged-user', styles.container)}>
<div className={cn('talk-admin-community-flagged-user-header', styles.header)}>
<div className={styles.author}>
<button
onClick={this.viewAuthorDetail}
@@ -78,8 +71,7 @@ class User extends React.Component {
}
</div>
</div>
<div className={styles.body}>
<div className={cn('talk-admin-community-flagged-user-body', styles.body)}>
<div className={styles.flagged}>
<div className={styles.flaggedByCount}>
<i className={cn('material-icons', styles.flagIcon)}>flag</i>
@@ -127,9 +119,11 @@ class User extends React.Component {
<div className={styles.sideActions}>
<div className={styles.actions}>
<ApproveButton
className="talk-admin-flagged-user-approve-button"
onClick={this.approveUser}
/>
<RejectButton
className="talk-admin-flagged-user-reject-button"
onClick={this.showRejectUsernameDialog}
/>
</div>
@@ -141,4 +135,16 @@ class User extends React.Component {
}
}
User.propTypes = {
showSuspendUserDialog: PropTypes.func,
showBanUserDialog: PropTypes.func,
viewUserDetail: PropTypes.func,
showRejectUsernameDialog: PropTypes.func,
approveUser: PropTypes.func,
user: PropTypes.object,
className: PropTypes.string,
selected: PropTypes.bool,
me: PropTypes.object,
};
export default User;
@@ -1,34 +1,31 @@
import React from 'react';
import cn from 'classnames';
import styles from './styles.css';
import Table from '../containers/Table';
import {Pager, Icon} from 'coral-ui';
import Table from './Table';
import {Icon} from 'coral-ui';
import EmptyCard from '../../../components/EmptyCard';
import t from 'coral-framework/services/i18n';
const tableHeaders = [
{
title: t('community.username_and_email'),
field: 'username'
},
{
title: t('community.account_creation_date'),
field: 'created_at'
},
{
title: t('community.status'),
field: 'status'
},
{
title: t('community.newsroom_role'),
field: 'role'
}
];
import PropTypes from 'prop-types';
const People = (props) => {
const {
users = [],
searchValue,
onSearchChange,
onHeaderClickHandler,
onPageChange,
totalPages,
page,
setRole,
setCommenterStatus,
viewUserDetail,
} = props;
const hasResults = !!users.length;
const People = ({commenters, searchValue, onSearchChange, ...props}) => {
const hasResults = !!commenters.length;
return (
<div className={styles.container}>
<div className={cn(styles.container, 'talk-admin-community-people-container')}>
<div className={styles.leftColumn}>
<div className={styles.searchBox}>
<Icon name='search' className={styles.searchIcon}/>
@@ -46,20 +43,33 @@ const People = ({commenters, searchValue, onSearchChange, ...props}) => {
{
hasResults
? <Table
headers={tableHeaders}
commenters={commenters}
onHeaderClickHandler={props.onHeaderClickHandler}
users={users}
setRole={setRole}
viewUserDetail={viewUserDetail}
setCommenterStatus={setCommenterStatus}
onHeaderClickHandler={onHeaderClickHandler}
pageCount={totalPages}
onPageChange={onPageChange}
page={page}
/>
: <EmptyCard>{t('community.no_results')}</EmptyCard>
}
<Pager
totalPages={props.totalPages}
page={props.page}
onNewPageHandler={props.onNewPageHandler}
/>
</div>
</div>
);
};
People.propTypes = {
onHeaderClickHandler: PropTypes.func,
users: PropTypes.array,
page: PropTypes.number.isRequired,
searchValue: PropTypes.string,
onSearchChange: PropTypes.func,
totalPages: PropTypes.number,
onPageChange: PropTypes.func,
setCommenterStatus: PropTypes.func.isRequired,
setRole: PropTypes.func.isRequired,
viewUserDetail: PropTypes.func.isRequired,
};
export default People;
@@ -1,6 +1,6 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import {Dialog, Button} from 'coral-ui';
import styles from './RejectUsernameDialog.css';
@@ -29,12 +29,6 @@ class RejectUsernameDialog extends Component {
state = {email: '', stage: 0}
static propTypes = {
stage: PropTypes.number,
handleClose: PropTypes.func.isRequired,
rejectUsername: PropTypes.func.isRequired
}
componentDidMount() {
this.setState({email: t('reject_username.email_message_reject'), about: t('reject_username.username')});
}
@@ -76,7 +70,7 @@ class RejectUsernameDialog extends Component {
const {stage} = this.state;
return <Dialog
className={styles.suspendDialog}
className={cn(styles.suspendDialog, 'talk-reject-username-dialog')}
id="rejectUsernameDialog"
open={open}
onClose={handleClose}
@@ -96,15 +90,18 @@ class RejectUsernameDialog extends Component {
<div className={styles.emailContainer}>
<textarea
rows={5}
className={styles.emailInput}
className={cn(styles.emailInput, 'talk-reject-username-dialog-suspension-message')}
value={this.state.email}
onChange={this.onEmailChange}/>
</div>
</div>
}
<div className={styles.modalButtons}>
<div className={cn(styles.modalButtons, 'talk-reject-username-dialog-buttons')}>
{Object.keys(stages[stage].options).map((key, i) => (
<Button key={i} onClick={this.onActionClick(stage, i)}>
<Button
key={i}
className={cn('talk-reject-username-dialog-button', `talk-reject-username-dialog-button-${key}`)}
onClick={this.onActionClick(stage, i)} >
{t(stages[stage].options[key], t('reject_username.username'))}
</Button>
))}
@@ -114,4 +111,12 @@ class RejectUsernameDialog extends Component {
}
}
RejectUsernameDialog.propTypes = {
stage: PropTypes.number,
handleClose: PropTypes.func.isRequired,
rejectUsername: PropTypes.func.isRequired,
user: PropTypes.object,
open: PropTypes.bool,
};
export default RejectUsernameDialog;
@@ -2,14 +2,18 @@
width: 100%;
border-left: none;
border-right: none;
}
th {
font-size: 1.1em;
}
th.header {
font-size: 1.1em;
}
th:nth-child(2), th:nth-child(3) {
width: 100px;
}
th.header:hover {
cursor: pointer;
}
th.header:nth-child(2), th.header:nth-child(3) {
width: 100px;
}
.button {
@@ -19,6 +23,13 @@
}
}
.username, .email {
max-width: 215px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.email {
display: block;
}
@@ -1,56 +1,98 @@
import React from 'react';
import {SelectField, Option} from 'react-mdl-selectfield';
import styles from '../components/Table.css';
import styles from './Table.css';
import t from 'coral-framework/services/i18n';
import PropTypes from 'prop-types';
import {Paginate, Dropdown, Option} from 'coral-ui';
import cn from 'classnames';
export default ({headers, commenters, onHeaderClickHandler, onRoleChange, onCommenterStatusChange, viewUserDetail}) => (
<table className={`mdl-data-table ${styles.dataTable}`}>
<thead>
<tr>
{headers.map((header, i) =>(
<th
key={i}
className="mdl-data-table__cell--non-numeric"
onClick={() => onHeaderClickHandler({field: header.field})}>
{header.title}
</th>
))}
</tr>
</thead>
<tbody>
{commenters.map((row, i)=> (
<tr key={i}>
<td className="mdl-data-table__cell--non-numeric">
<button onClick={() => {viewUserDetail(row.id);}} className={styles.button}>{row.username}</button>
<span className={styles.email}>{row.profiles.map(({id}) => id)}</span>
</td>
<td className="mdl-data-table__cell--non-numeric">
{row.created_at}
</td>
<td className="mdl-data-table__cell--non-numeric">
<SelectField
value={row.status || ''}
className={styles.selectField}
label={t('community.status')}
onChange={(status) => onCommenterStatusChange(row.id, status)}>
<Option value={'ACTIVE'}>{t('community.active')}</Option>
<Option value={'BANNED'}>{t('community.banned')}</Option>
</SelectField>
</td>
<td className="mdl-data-table__cell--non-numeric">
<SelectField
value={row.roles[0] || ''}
className={styles.selectField}
label={t('community.role')}
onChange={(role) => onRoleChange(row.id, role)}>
<Option value={''}>.</Option>
<Option value={'STAFF'}>{t('community.staff')}</Option>
<Option value={'MODERATOR'}>{t('community.moderator')}</Option>
<Option value={'ADMIN'}>{t('community.admin')}</Option>
</SelectField>
</td>
const headers = [
{
title: t('community.username_and_email'),
field: 'username'
},
{
title: t('community.account_creation_date'),
field: 'created_at'
},
{
title: t('community.status'),
field: 'status'
},
{
title: t('community.newsroom_role'),
field: 'role'
}
];
const Table = ({users, setRole, onHeaderClickHandler, setCommenterStatus, viewUserDetail, pageCount, page, onPageChange}) => (
<div>
<table className={`mdl-data-table ${styles.dataTable}`}>
<thead>
<tr>
{headers.map((header, i) =>(
<th
key={i}
className={cn('mdl-data-table__cell--non-numeric', styles.header)}
scope="col"
onClick={() => onHeaderClickHandler({field: header.field})}>
{header.title}
</th>
))}
</tr>
))}
</tbody>
</table>
</thead>
<tbody>
{users.map((row, i)=> (
<tr key={i} className="talk-admin-community-people-row">
<td className="mdl-data-table__cell--non-numeric">
<button onClick={() => {viewUserDetail(row.id);}} className={cn(styles.username, styles.button)}>{row.username}</button>
<span className={styles.email}>{row.profiles.map(({id}) => id)}</span>
</td>
<td className="mdl-data-table__cell--non-numeric">
{row.created_at}
</td>
<td className="mdl-data-table__cell--non-numeric">
<Dropdown
containerClassName="talk-admin-community-people-dd-status"
value={row.status}
placeholder={t('community.status')}
onChange={(status) => setCommenterStatus(row.id, status)}>
<Option value={'ACTIVE'} label={t('community.active')} />
<Option value={'BANNED'} label={t('community.banned')} />
</Dropdown>
</td>
<td className="mdl-data-table__cell--non-numeric">
<Dropdown
containerClassName="talk-admin-community-people-dd-role"
value={row.roles[0] || ''}
placeholder={t('community.role')}
onChange={(role) => setRole(row.id, role)}>
<Option value={''} label={t('community.none')} />
<Option value={'STAFF'} label={t('community.staff')} />
<Option value={'MODERATOR'} label={t('community.moderator')} />
<Option value={'ADMIN'} label={t('community.admin')} />
</Dropdown>
</td>
</tr>
))}
</tbody>
</table>
<Paginate
pageCount={pageCount}
page={page - 1}
onPageChange={onPageChange}
/>
</div>
);
Table.propTypes = {
users: PropTypes.array,
onHeaderClickHandler: PropTypes.func.isRequired,
setRole: PropTypes.func.isRequired,
setCommenterStatus: PropTypes.func.isRequired,
viewUserDetail: PropTypes.func.isRequired,
pageCount: PropTypes.number.isRequired,
page: PropTypes.number.isRequired,
onPageChange: PropTypes.func.isRequired,
};
export default Table;
@@ -1,65 +1,21 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import PropTypes from 'prop-types';
import {compose, gql} from 'react-apollo';
import withQuery from 'coral-framework/hocs/withQuery';
import {getDefinitionName} from 'coral-framework/utils';
import {withSetUserStatus, withRejectUsername} from 'coral-framework/graphql/mutations';
import FlaggedAccounts from '../containers/FlaggedAccounts';
import FlaggedUser from '../containers/FlaggedUser';
import {
fetchAccounts,
updateSorting,
newPage,
hideRejectUsernameDialog
} from '../../../actions/community';
import {hideRejectUsernameDialog} from '../../../actions/community';
import Community from '../components/Community';
class CommunityContainer extends Component {
componentWillMount() {
this.props.fetchAccounts({});
}
render() {
return <Community
fetchAccounts={this.props.fetchAccounts}
community={this.props.community}
hideRejectUsernameDialog={this.props.hideRejectUsernameDialog}
updateSorting={this.props.updateSorting}
newPage={this.props.newPage}
route={this.props.route}
rejectUsername={this.props.rejectUsername}
data={this.props.data}
root={this.props.root}
/>;
}
}
const mapStateToProps = (state) => ({
community: state.community,
});
CommunityContainer.propTypes = {
community: PropTypes.object,
fetchAccounts: PropTypes.func,
hideRejectUsernameDialog: PropTypes.func,
updateSorting: PropTypes.func,
newPage: PropTypes.func,
route: PropTypes.object,
rejectUsername: PropTypes.func,
data: PropTypes.object,
root: PropTypes.object
};
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
fetchAccounts,
hideRejectUsernameDialog,
updateSorting,
newPage,
}, dispatch);
const withData = withQuery(gql`
@@ -89,4 +45,4 @@ export default compose(
withSetUserStatus,
withRejectUsername,
withData
)(CommunityContainer);
)(Community);
@@ -0,0 +1,104 @@
import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import People from '../components/People';
import PropTypes from 'prop-types';
import {viewUserDetail} from '../../../actions/userDetail';
import {
fetchUsers,
updateSorting,
setPage,
hideRejectUsernameDialog,
setCommenterStatus,
setRole,
setSearchValue,
} from '../../../actions/community';
class PeopleContainer extends React.Component {
timer=null;
fetchUsers = (query = {}) => {
const {community} = this.props;
this.props.fetchUsers({
value: community.searchValue,
field: community.fieldPeople,
asc: community.ascPeople,
...query
});
}
componentWillMount() {
this.fetchUsers();
}
onKeyDownHandler = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
this.fetchUsers();
}
}
onSearchChange = (e) => {
const value = e.target.value;
this.props.setSearchValue(value);
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.fetchUsers({value});
}, 350);
}
onHeaderClickHandler = (sort) => {
this.props.updateSorting(sort);
this.fetchUsers();
}
onPageChange = ({selected}) => {
const page = selected + 1;
this.props.setPage(page);
this.fetchUsers({page});
}
render() {
return <People
users={this.props.community.users}
searchValue={this.props.community.searchValue}
onSearchChange={this.onSearchChange}
onHeaderClickHandler={this.onHeaderClickHandler}
onPageChange={this.onPageChange}
totalPages={this.props.community.totalPagesPeople}
setCommenterStatus={this.props.setCommenterStatus}
setRole={this.props.setRole}
page={this.props.community.pagePeople}
viewUserDetail={this.props.viewUserDetail}
/>;
}
}
PeopleContainer.propTypes = {
setPage: PropTypes.func,
fetchUsers: PropTypes.func,
updateSorting: PropTypes.func,
setRole: PropTypes.func.isRequired,
setCommenterStatus: PropTypes.func.isRequired,
setSearchValue: PropTypes.func.isRequired,
viewUserDetail: PropTypes.func.isRequired,
community: PropTypes.object,
};
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
setPage,
fetchUsers,
updateSorting,
hideRejectUsernameDialog,
setCommenterStatus,
setRole,
viewUserDetail,
setSearchValue,
}, dispatch);
export default connect(null, mapDispatchToProps)(PeopleContainer);
@@ -1,39 +0,0 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose} from 'react-apollo';
import {setRole, setCommenterStatus} from '../../../actions/community';
import Table from '../components/Table';
import {viewUserDetail} from '../../../actions/userDetail';
class TableContainer extends Component {
constructor (props) {
super(props);
}
render () {
return <Table
{...this.props}
onRoleChange={this.props.setRole}
onCommenterStatusChange={this.props.setCommenterStatus}
commenters={this.props.commenters}
/>;
}
}
const mapStateToProps = (state) => ({
commenters: state.community.accounts,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
setCommenterStatus,
setRole,
viewUserDetail,
}, dispatch);
export default compose(
connect(mapStateToProps, mapDispatchToProps),
)(TableContainer);
@@ -1,15 +1,7 @@
/**
* @TODO: deprecated as this file contains styles from multiple components. Please refactor.
*/
.container {
max-width: 1280px;
margin: 0 auto;
display: flex;
h3 {
color: black;
font-size: 1.26em;
font-weight: 500;
}
}
.leftColumn {
@@ -17,108 +9,8 @@
width: 234px;
}
.mainContent {
width: calc(100% - 300px);
padding: 10px 14px;
box-sizing: border-box;
max-width: 718px;
}
.configSetting {
margin-bottom: 20px;
align-items: flex-start;
min-height: 100px;
max-width: 600px;
h3 {
margin: 0;
}
.actions {
display: inline-block;
width: 100%;
.copiedText {
display: inline-block;
color: #00796b;
padding: 12px;
font-size: 14px;
float: right;
}
.copyButton {
display: inline-block;
width: 200px;
float: right;
}
}
}
.settingsError {
color: #d50000;
}
.settingsError i {
font-size: 14px;
margin-right: 3px;
}
.settingsHeader {
margin-top: 3px;
margin-bottom: 7px;
font-size: 18px;
font-weight: 500;
}
.disabledSettingText {
color: #ccc;
}
.configSettingInfoBox {
min-height: 100px;
margin-bottom: 20px;
width: auto;
height: auto;
text-align: left;
overflow: visible;
}
.configSettingEmbed {
border: 1px solid #ccc;
border-radius: 4px;
margin-bottom: 10px;
display: block;
}
.configTimeoutSelect {
display: inline-block;
margin-left: 20px;
i { /* fix for firefox and react-mdl-selectfield@0.2.0 */
padding: 20px 0;
vertical-align: top;
}
}
.inlineTextfield {
border-color: #ccc;
border-style: solid;
border-width: 0px 0px 1px 0px;
text-align: center;
font-size: inherit;
}
.inlineTextfield:focus {
outline: none;
}
.charCountTexfield, .editCommentTimeframeTextfield {
width: 4em;
padding: 0px;
}
.charCountTexfieldEnabled {
border-color: #00796b;
.saveBox {
margin-top: 38px;
}
.changedSave {
@@ -126,81 +18,10 @@
color: white;
}
.embedInput {
width: 100%;
display: block;
outline: none;
border: 1px solid rgba(0,0,0,.12);
padding: 6px;
.mainContent {
width: calc(100% - 300px);
padding: 10px 14px 80px 14px;
box-sizing: border-box;
border-radius: 2px;
margin: 5px auto;
min-height: 175px;
font-size: 14px;
resize: none;
max-width: 718px;
}
.customCSSInput {
width: 100%;
font-size: 14px;
padding: 14px;
letter-spacing: 0.03em;
color: #555;
box-sizing: border-box;
}
.enabledSetting {
border-left-color: #00796b;
border-left-style: solid;
border-left-width: 7px;
}
.disabledSetting {
padding-left: 22px;
}
.hidden {
display: none;
}
.saveBox {
margin-top: 38px;
}
.settingsSection {
padding-bottom: 200px;
.action {
display: inline-block;
position: absolute;
top: 0;
left: 0;
padding: 20px;
}
.content {
display: inline-block;
padding: 0px 30px;
box-sizing: border-box;
width: 100%;
}
}
.Configure {
p {
line-height: 1.2;
max-width: 550px;
}
.wrapper {
width: 100%;
}
.descriptionBox {
margin-top: 15px;
input {
height: 150px;
}
}
}
@@ -1,119 +1,40 @@
import React, {Component} from 'react';
import {Button, List, Item, Card, Spinner} from 'coral-ui';
import {Button, List, Item} from 'coral-ui';
import styles from './Configure.css';
import StreamSettings from './StreamSettings';
import ModerationSettings from './ModerationSettings';
import TechSettings from './TechSettings';
import StreamSettings from '../containers/StreamSettings';
import ModerationSettings from '../containers/ModerationSettings';
import TechSettings from '../containers/TechSettings';
import t from 'coral-framework/services/i18n';
import {can} from 'coral-framework/services/perms';
import PropTypes from 'prop-types';
export default class Configure extends Component {
state = {
activeSection: 'stream',
changed: false,
errors: {}
};
saveSettings = () => {
this.props.saveSettingsToServer();
this.setState({changed: false});
}
changeSection = (activeSection) => {
this.setState({activeSection});
}
onChangeWordlist = (listName, list) => {
this.setState({changed: true});
this.props.updateWordlist(listName, list);
}
onChangeDomainlist = (listName, list) => {
this.setState({changed: true});
this.props.updateDomainlist(listName, list);
}
onSettingUpdate = (setting) => {
this.setState({changed: true});
this.props.updateSettings(setting);
}
// Sets an arbitrary error string and a boolean state.
// This allows the system to track multiple errors.
onSettingError = (error, state) => {
this.setState((prevState) => {
prevState.errors[error] = state;
return prevState;
});
}
getSection (section) {
const pageTitle = this.getPageTitle(section);
let sectionComponent;
getSectionComponent(section) {
switch(section){
case 'stream':
sectionComponent = <StreamSettings
settings={this.props.settings}
updateSettings={this.onSettingUpdate}
errors={this.state.errors}
settingsError={this.onSettingError}/>;
break;
return StreamSettings;
case 'moderation':
sectionComponent = <ModerationSettings
onChangeWordlist={this.onChangeWordlist}
settings={this.props.settings}
updateSettings={this.onSettingUpdate} />;
break;
return ModerationSettings;
case 'tech':
sectionComponent = <TechSettings
onChangeDomainlist={this.onChangeDomainlist}
settings={this.props.settings}
updateSettings={this.onSettingUpdate} />;
}
if (this.props.settings.fetchingSettings) {
return <Card shadow="4"><Spinner/>Loading settings...</Card>;
}
return (
<div className={styles.settingsSection}>
<h3>{pageTitle}</h3>
{sectionComponent}
</div>
);
}
getPageTitle (section) {
switch(section) {
case 'stream':
return t('configure.stream_settings');
case 'moderation':
return t('configure.moderation_settings');
case 'tech':
return t('configure.tech_settings');
default:
return '';
return TechSettings;
}
throw new Error(`Unknown section ${section}`);
}
render () {
const {activeSection} = this.state;
const section = this.getSection(activeSection);
const {auth: {user}} = this.props;
const {auth: {user}, canSave, savePending, setActiveSection, activeSection} = this.props;
const SectionComponent = this.getSectionComponent(activeSection);
if (!can(user, 'UPDATE_CONFIG')) {
return <p>You must be an administrator to access config settings. Please find the nearest Admin and ask them to level you up!</p>;
}
const showSave = Object.keys(this.state.errors).reduce(
(bool, error) => this.state.errors[error] ? false : bool, this.state.changed);
return (
<div className={styles.container}>
<div className={styles.leftColumn}>
<List onChange={this.changeSection} activeItem={activeSection}>
<List onChange={setActiveSection} activeItem={activeSection}>
<Item itemId='stream' icon='speaker_notes'>
{t('configure.stream_settings')}
</Item>
@@ -126,10 +47,10 @@ export default class Configure extends Component {
</List>
<div className={styles.saveBox}>
{
showSave ?
canSave ?
<Button
raised
onClick={this.saveSettings}
onClick={savePending}
className={styles.changedSave}
icon='check'
full
@@ -150,11 +71,25 @@ export default class Configure extends Component {
</div>
<div className={styles.mainContent}>
{ this.props.saveFetchingError }
{ this.props.fetchSettingsError }
{ section }
<SectionComponent
data={this.props.data}
root={this.props.root}
settings={this.props.settings}
/>
</div>
</div>
);
}
}
Configure.propTypes = {
notify: PropTypes.func.isRequired,
savePending: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
canSave: PropTypes.bool.isRequired,
setActiveSection: PropTypes.func.isRequired,
activeSection: PropTypes.string.isRequired,
};
@@ -0,0 +1,5 @@
.title {
color: black;
font-size: 1.26em;
font-weight: 500;
}
@@ -0,0 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './ConfigurePage.css';
const ConfigurePage = ({title, children, ...rest}) => (
<div {...rest}>
<h3 className={styles.title}>{title}</h3>
{children}
</div>
);
ConfigurePage.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node,
};
export default ConfigurePage;
@@ -1,25 +1,25 @@
import React from 'react';
import {Card} from 'coral-ui';
import styles from './Configure.css';
import PropTypes from 'prop-types';
import TagsInput from 'coral-admin/src/components/TagsInput';
import t from 'coral-framework/services/i18n';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
const Domainlist = ({domains, onChangeDomainlist}) => {
return (
<Card id={styles.domainlist} className={styles.configSetting}>
<div className={styles.wrapper}>
<div className={styles.settingsHeader}>{t('configure.domain_list_title')}</div>
<p className={styles.domainlistDesc}>{t('configure.domain_list_text')}</p>
<div className={styles.wrapper}>
<TagsInput
value={domains}
inputProps={{placeholder: 'URL'}}
onChange={(tags) => onChangeDomainlist('whitelist', tags)}
/>
</div>
</div>
</Card>
<ConfigureCard title={t('configure.domain_list_title')}>
<p>{t('configure.domain_list_text')}</p>
<TagsInput
value={domains}
inputProps={{placeholder: 'URL'}}
onChange={(tags) => onChangeDomainlist('whitelist', tags)}
/>
</ConfigureCard>
);
};
Domainlist.propTypes = {
domains: PropTypes.array.isRequired,
onChangeDomainlist: PropTypes.func.isRequired,
};
export default Domainlist;
@@ -0,0 +1,32 @@
.embedInput {
width: 100%;
display: block;
outline: none;
border: 1px solid rgba(0,0,0,.12);
padding: 6px;
box-sizing: border-box;
border-radius: 2px;
margin: 5px auto;
min-height: 175px;
font-size: 14px;
resize: none;
}
.copiedText {
display: inline-block;
color: #00796b;
padding: 12px;
font-size: 14px;
float: right;
}
.copyButton {
display: inline-block;
width: 200px;
float: right;
}
.actions {
display: inline-block;
width: 100%;
}
@@ -1,17 +1,14 @@
import React, {Component} from 'react';
import t from 'coral-framework/services/i18n';
import join from 'url-join';
import styles from './Configure.css';
import {Button, Card} from 'coral-ui';
import styles from './EmbedLink.css';
import {Button} from 'coral-ui';
import {BASE_URL} from 'coral-framework/constants/url';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
class EmbedLink extends Component {
constructor (props) {
super(props);
this.state = {copied: false};
}
state = {copied: false};
copyToClipBoard = () => {
const copyTextarea = document.querySelector(`.${styles.embedInput}`);
@@ -38,21 +35,18 @@ class EmbedLink extends Component {
"></script>
`.trim();
return (
<Card shadow="2" className={styles.configSetting}>
<div className={styles.wrapper}>
<div className={styles.settingsHeader}>Embed Comment Stream</div>
<p>{t('configure.copy_and_paste')}</p>
<textarea rows={5} type='text' className={styles.embedInput} value={embedText} readOnly={true}/>
<div className={styles.actions}>
<Button raised className={styles.copyButton} onClick={this.copyToClipBoard} cStyle="black">
{t('embedlink.copy')}
</Button>
<div className={styles.copiedText}>
{this.state.copied && 'Copied!'}
</div>
<ConfigureCard title={'Embed Comment Stream'}>
<p>{t('configure.copy_and_paste')}</p>
<textarea rows={5} type='text' className={styles.embedInput} value={embedText} readOnly={true}/>
<div className={styles.actions}>
<Button raised className={styles.copyButton} onClick={this.copyToClipBoard} cStyle="black">
{t('embedlink.copy')}
</Button>
<div className={styles.copiedText}>
{this.state.copied && 'Copied!'}
</div>
</div>
</Card>
</ConfigureCard>
);
}
}
@@ -1,90 +1,93 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './Configure.css';
import {Card} from 'coral-ui';
import {Checkbox} from 'react-mdl';
import Wordlist from './Wordlist';
import Slot from 'coral-framework/components/Slot';
import t from 'coral-framework/services/i18n';
import ConfigurePage from './ConfigurePage';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
const updateModeration = (updateSettings, mod) => () => {
const moderation = mod === 'PRE' ? 'POST' : 'PRE';
updateSettings({moderation});
};
class ModerationSettings extends React.Component {
const updateEmailConfirmation = (updateSettings, verify) => () => {
updateSettings({requireEmailConfirmation: !verify});
};
updateModeration = () => {
const updater = {moderation: {$set: this.props.settings.moderation === 'PRE' ? 'POST' : 'PRE'}};
this.props.updatePending({updater});
};
const updatePremodLinksEnable = (updateSettings, premodLinks) => () => {
const premodLinksEnable = !premodLinks;
updateSettings({premodLinksEnable});
};
updateEmailConfirmation = () => {
const updater = {requireEmailConfirmation: {$set: !this.props.settings.requireEmailConfirmation}};
this.props.updatePending({updater});
};
const ModerationSettings = ({settings, updateSettings, onChangeWordlist}) => {
updatePremodLinksEnable = () => {
const updater = {premodLinksEnable: {$set: !this.props.settings.premodLinksEnable}};
this.props.updatePending({updater});
};
// just putting this here for shorthand below
const on = styles.enabledSetting;
const off = styles.disabledSetting;
updateWordlist = (listName, list) => {
this.props.updatePending({updater: {
wordlist: {$apply: (wordlist) => {
const changeSet = {[listName]: list};
if (!wordlist) {
return changeSet;
}
return {
...wordlist,
...changeSet,
};
}},
}});
};
return (
<div className={styles.Configure}>
<Card className={`${styles.configSetting} ${settings.requireEmailConfirmation ? on : off}`}>
<div className={styles.action}>
<Checkbox
onChange={updateEmailConfirmation(updateSettings, settings.requireEmailConfirmation)}
checked={settings.requireEmailConfirmation} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>{t('configure.require_email_verification')}</div>
<p className={settings.requireEmailConfirmation ? '' : styles.disabledSettingText}>
{t('configure.require_email_verification_text')}
</p>
</div>
</Card>
<Card className={`${styles.configSetting} ${settings.moderation === 'PRE' ? on : off}`}>
<div className={styles.action}>
<Checkbox
onChange={updateModeration(updateSettings, settings.moderation)}
checked={settings.moderation === 'PRE'} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>{t('configure.enable_pre_moderation')}</div>
<p className={settings.moderation === 'PRE' ? '' : styles.disabledSettingText}>
{t('configure.enable_pre_moderation_text')}
</p>
</div>
</Card>
<Card className={`${styles.configSetting} ${settings.premodLinksEnable ? on : off}`}>
<div className={styles.action}>
<Checkbox
onChange={updatePremodLinksEnable(updateSettings, settings.premodLinksEnable)}
checked={settings.premodLinksEnable} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>{t('configure.enable_premod_links')}</div>
<p>
{t('configure.enable_premod_links_text')}
</p>
</div>
</Card>
<Wordlist
bannedWords={settings.wordlist.banned}
suspectWords={settings.wordlist.suspect}
onChangeWordlist={onChangeWordlist} />
</div>
);
};
render() {
const {settings, data, root, updatePending, errors} = this.props;
return (
<ConfigurePage
title={t('configure.moderation_settings')}
>
<ConfigureCard
checked={settings.requireEmailConfirmation}
onCheckbox={this.updateEmailConfirmation}
title={t('configure.require_email_verification')}
>
{t('configure.require_email_verification_text')}
</ConfigureCard>
<ConfigureCard
checked={settings.moderation === 'PRE'}
onCheckbox={this.updateModeration}
title={t('configure.enable_pre_moderation')}
>
{t('configure.enable_pre_moderation_text')}
</ConfigureCard>
<ConfigureCard
checked={settings.premodLinksEnable}
onCheckbox={this.updatePremodLinksEnable}
title={t('configure.enable_premod_links')}
>
{t('configure.enable_premod_links_text')}
</ConfigureCard>
<Wordlist
bannedWords={settings.wordlist.banned}
suspectWords={settings.wordlist.suspect}
onChangeWordlist={this.updateWordlist} />
<Slot
fill="adminModerationSettings"
data={data}
queryData={{root, settings}}
updatePending={updatePending}
errors={errors}
/>
</ConfigurePage>
);
}
}
ModerationSettings.propTypes = {
onChangeWordlist: PropTypes.func.isRequired,
settings: PropTypes.shape({
moderation: PropTypes.string.isRequired,
wordlist: PropTypes.shape({
banned: PropTypes.array.isRequired,
suspect: PropTypes.array.isRequired
})
}).isRequired,
updateSettings: PropTypes.func.isRequired
updatePending: PropTypes.func.isRequired,
errors: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
};
export default ModerationSettings;
@@ -0,0 +1,58 @@
.configSettingInfoBox {
min-height: 100px;
margin-bottom: 20px;
width: auto;
height: auto;
text-align: left;
overflow: visible;
}
.descriptionBox {
margin-top: 15px;
input {
height: 150px;
}
}
.configTimeoutSelect {
display: inline-block;
margin-left: 20px;
i { /* fix for firefox and react-mdl-selectfield@0.2.0 */
padding: 20px 0;
vertical-align: top;
}
}
.hidden {
display: none;
}
.inlineTextfield {
border-color: #ccc;
border-style: solid;
border-width: 0px 0px 1px 0px;
text-align: center;
font-size: inherit;
}
.inlineTextfield:focus {
outline: none;
}
.charCountTexfield, .editCommentTimeframeTextfield {
width: 4em;
padding: 0px;
}
.charCountTexfieldEnabled {
border-color: #00796b;
}
.autoCloseWrapper {
display: flex;
}
@@ -1,10 +1,15 @@
import React from 'react';
import {SelectField, Option} from 'react-mdl-selectfield';
import t from 'coral-framework/services/i18n';
import styles from './Configure.css';
import {Checkbox, Textfield} from 'react-mdl';
import {Card, Icon, TextArea} from 'coral-ui';
import styles from './StreamSettings.css';
import {Textfield} from 'react-mdl';
import {Icon, TextArea} from 'coral-ui';
import PropTypes from 'prop-types';
import Slot from 'coral-framework/components/Slot';
import MarkdownEditor from 'coral-framework/components/MarkdownEditor';
import cn from 'classnames';
import ConfigurePage from './ConfigurePage';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
const TIMESTAMPS = {
weeks: 60 * 60 * 24 * 7,
@@ -12,187 +17,6 @@ const TIMESTAMPS = {
hours: 60 * 60
};
const updateCharCountEnable = (updateSettings, charCountChecked) => () => {
const charCountEnable = !charCountChecked;
updateSettings({charCountEnable});
};
const updateCharCount = (updateSettings, settingsError) => (event) => {
const charCount = event.target.value;
if (charCount.match(/[^0-9]/) || charCount.length === 0) {
settingsError('charCount', true);
} else {
settingsError('charCount', false);
}
updateSettings({charCount: charCount});
};
const updateInfoBoxEnable = (updateSettings, infoBox) => () => {
const infoBoxEnable = !infoBox;
updateSettings({infoBoxEnable});
};
const updateInfoBoxContent = (updateSettings) => (value) => {
const infoBoxContent = value;
updateSettings({infoBoxContent});
};
const updateAutoClose = (updateSettings, autoCloseStream) => () => {
updateSettings({autoCloseStream});
};
const updateClosedMessage = (updateSettings) => (event) => {
const closedMessage = event.target.value;
updateSettings({closedMessage});
};
// If we are changing the measure we need to recalculate using the old amount
// Same thing if we are just changing the amount
const updateClosedTimeout = (updateSettings, ts, isMeasure) => (event) => {
if (isMeasure) {
const amount = getTimeoutAmount(ts);
const closedTimeout = amount * TIMESTAMPS[event];
updateSettings({closedTimeout});
} else {
const val = event.target.value;
const measure = getTimeoutMeasure(ts);
const closedTimeout = val * TIMESTAMPS[measure];
updateSettings({closedTimeout});
}
};
const updateEditCommentWindowLength = (updateSettings) => (e) => {
const value = e.target.value;
const valueAsNumber = parseFloat(value);
const milliseconds = (!isNaN(valueAsNumber)) && (valueAsNumber * 1000);
updateSettings({editCommentWindowLength: milliseconds || value});
};
const StreamSettings = ({updateSettings, settingsError, settings, errors}) => {
// just putting this here for shorthand below
const on = styles.enabledSetting;
const off = styles.disabledSetting;
return (
<div className={styles.Configure}>
<Card className={`${styles.configSetting} ${settings.charCountEnable ? on : off}`}>
<div className={styles.action}>
<Checkbox
onChange={updateCharCountEnable(updateSettings, settings.charCountEnable)}
checked={settings.charCountEnable} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>{t('configure.comment_count_header')}</div>
<p className={settings.charCountEnable ? '' : styles.disabledSettingText}>
<span>{t('configure.comment_count_text_pre')}</span>
<input type='text'
className={`${styles.inlineTextfield} ${styles.charCountTexfield} ${settings.charCountEnable && styles.charCountTexfieldEnabled}`}
htmlFor='charCount'
onChange={updateCharCount(updateSettings, settingsError)}
value={settings.charCount}
disabled={settings.charCountEnable ? '' : 'disabled'}
/>
<span>{t('configure.comment_count_text_post')}</span>
{
errors.charCount &&
<span className={styles.settingsError}>
<br/>
<Icon name="error_outline"/>
{t('configure.comment_count_error')}
</span>
}
</p>
</div>
</Card>
<Card className={`${styles.configSetting} ${styles.configSettingInfoBox} ${settings.infoBoxEnable ? on : off}`}>
<div className={styles.action}>
<Checkbox
onChange={updateInfoBoxEnable(updateSettings, settings.infoBoxEnable)}
checked={settings.infoBoxEnable} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>
{t('configure.include_comment_stream')}
</div>
<p className={settings.infoBoxEnable ? '' : styles.disabledSettingText}>
{t('configure.include_comment_stream_desc')}
</p>
<div className={`${styles.configSettingInfoBox} ${settings.infoBoxEnable ? null : styles.hidden}`} >
<MarkdownEditor
className={styles.descriptionBox}
onChange={updateInfoBoxContent(updateSettings)}
value={settings.infoBoxContent}
/>
</div>
</div>
</Card>
<Card className={`${styles.configSetting} ${styles.configSettingInfoBox}`}>
<div className={styles.wrapper}>
<div className={styles.settingsHeader}>{t('configure.closed_stream_settings')}</div>
<p>{t('configure.closed_comments_desc')}</p>
<div>
<TextArea className={styles.descriptionBox}
onChange={updateClosedMessage(updateSettings)}
value={settings.closedMessage}
/>
</div>
</div>
</Card>
{/* Edit Comment Timeframe */}
<Card className={styles.configSetting}>
<div className={styles.settingsHeader}>{t('configure.edit_comment_timeframe_heading')}</div>
<p>
{t('configure.edit_comment_timeframe_text_pre')}
&nbsp;
<input
className={`${styles.inlineTextfield} ${styles.editCommentTimeframeTextfield}`}
type="number"
min="0"
onChange={updateEditCommentWindowLength(updateSettings)}
placeholder="30"
defaultValue={(settings.editCommentWindowLength / 1000) /* saved as ms, rendered as seconds */}
pattern='[0-9]+([\.][0-9]*)?'
/>
&nbsp;
{t('configure.edit_comment_timeframe_text_post')}
</p>
</Card>
<Card className={`${styles.configSetting} ${styles.configSettingInfoBox}`}>
<div className={styles.action}>
<Checkbox
onChange={updateAutoClose(updateSettings, !settings.autoCloseStream)}
checked={settings.autoCloseStream} />
</div>
<div className={styles.content}>
<div className={styles.settingsHeader}>{t('configure.close_after')}</div>
<br />
<Textfield
type='number'
pattern='[0-9]+'
style={{width: 50}}
onChange={updateClosedTimeout(updateSettings, settings.closedTimeout)}
value={getTimeoutAmount(settings.closedTimeout)}
label={t('configure.closed_comments_label')} />
<div className={styles.configTimeoutSelect}>
<SelectField
label="comments closed time window"
value={getTimeoutMeasure(settings.closedTimeout)}
onChange={updateClosedTimeout(updateSettings, settings.closedTimeout, true)}>
<Option value={'hours'}>{t('configure.hours')}</Option>
<Option value={'days'}>{t('configure.days')}</Option>
<Option value={'weeks'}>{t('configure.weeks')}</Option>
</SelectField>
</div>
</div>
</Card>
{/* the above card should be the last one if at all possible because of z-index issues with the selects */}
</div>
);
};
export default StreamSettings;
// To see if we are talking about weeks, days or hours
// We talk the remainder of the division and see if it's 0
const getTimeoutMeasure = (ts) => {
@@ -208,3 +32,194 @@ const getTimeoutMeasure = (ts) => {
// Dividing the amount by it's measure (hours, days, weeks) we
// obtain the amount of time
const getTimeoutAmount = (ts) => ts / TIMESTAMPS[getTimeoutMeasure(ts)];
class StreamSettings extends React.Component {
updateCharCountEnable = () => {
const updater = {charCountEnable: {$set: !this.props.settings.charCountEnable}};
this.props.updatePending({updater});
};
updateCharCount = (event) => {
let error = null;
const charCount = event.target.value;
if (charCount.match(/[^0-9]/) || charCount.length === 0) {
error = true;
}
const updater = {charCount: {$set: charCount}};
const errorUpdater = {charCount: {$set: error}};
this.props.updatePending({updater, errorUpdater});
};
updateInfoBoxEnable = () => {
const updater = {infoBoxEnable: {$set: !this.props.settings.infoBoxEnable}};
this.props.updatePending({updater});
};
updateInfoBoxContent = (value) => {
const updater = {infoBoxContent: {$set: value}};
this.props.updatePending({updater});
};
updateClosedMessage = (event) => {
const updater = {closedMessage: {$set: event.target.value}};
this.props.updatePending({updater});
};
updateEditCommentWindowLength = (e) => {
const value = e.target.value;
const valueAsNumber = parseFloat(value);
const milliseconds = (!isNaN(valueAsNumber)) && (valueAsNumber * 1000);
const updater = {editCommentWindowLength: {$set: milliseconds || value}};
this.props.updatePending({updater});
};
updateAutoClose = () => {
const updater = {autoCloseStream: {$set: !this.props.settings.autoCloseStream}};
this.props.updatePending({updater});
};
updateClosedTimeout = (event) => {
const val = event.target.value;
const measure = getTimeoutMeasure(this.props.settings.closedTimeout);
const updater = {closedTimeout: {$set: val * TIMESTAMPS[measure]}};
this.props.updatePending({updater});
};
// If we are changing the measure we need to recalculate using the old amount
// Same thing if we are just changing the amount
updateClosedTimeoutMeasure = (event) => {
const amount = getTimeoutAmount(this.props.settings.closedTimeout);
const updater = {closedTimeout: {$set: amount * TIMESTAMPS[event]}};
this.props.updatePending({updater});
};
render() {
const {settings, data, root, errors, updatePending} = this.props;
return (
<ConfigurePage
title={t('configure.stream_settings')}
>
<ConfigureCard
checked={settings.charCountEnable}
onCheckbox={this.updateCharCountEnable}
title={t('configure.comment_count_header')}
>
<span>{t('configure.comment_count_text_pre')}</span>
<input type='text'
className={cn(styles.inlineTextfield, styles.charCountTexfield, settings.charCountEnable && styles.charCountTexfieldEnable)}
htmlFor='charCount'
onChange={this.updateCharCount}
value={settings.charCount}
disabled={settings.charCountEnable ? '' : 'disabled'}
/>
<span>{t('configure.comment_count_text_post')}</span>
{
errors.charCount &&
<span className={styles.settingsError}>
<br/>
<Icon name="error_outline"/>
{t('configure.comment_count_error')}
</span>
}
</ConfigureCard>
<ConfigureCard
checked={settings.infoBoxEnable}
onCheckbox={this.updateInfoBoxEnable}
title={t('configure.include_comment_stream')}
>
<p>
{t('configure.include_comment_stream_desc')}
</p>
<div className={cn(styles.configSettingInfoBox, settings.infoBoxEnable ? null : styles.hidden)} >
<MarkdownEditor
className={styles.descriptionBox}
onChange={this.updateInfoBoxContent}
value={settings.infoBoxContent}
/>
</div>
</ConfigureCard>
<ConfigureCard
checked={settings.configSettingInfoBox}
onCheckbox={this.updateClosedMessage}
title={t('configure.closed_stream_settings')}
>
<p>{t('configure.closed_comments_desc')}</p>
<div>
<TextArea className={styles.descriptionBox}
onChange={this.updateClosedMessage}
value={settings.closedMessage}
/>
</div>
</ConfigureCard>
<ConfigureCard
title={t('configure.edit_comment_timeframe_heading')}
>
{t('configure.edit_comment_timeframe_text_pre')}
&nbsp;
<input
className={cn(styles.inlineTextfield, styles.editCommentTimeframeTextfield)}
type="number"
min="0"
onChange={this.updateEditCommentWindowLength}
placeholder="30"
defaultValue={(settings.editCommentWindowLength / 1000) /* saved as ms, rendered as seconds */}
pattern='[0-9]+([\.][0-9]*)?'
/>
&nbsp;
{t('configure.edit_comment_timeframe_text_post')}
</ConfigureCard>
<ConfigureCard
checked={settings.autoCloseStream}
onCheckbox={this.updateAutoClose}
title={t('configure.close_after')}
>
<div className={styles.autoCloseWrapper}>
<Textfield
type='number'
pattern='[0-9]+'
style={{width: 50}}
onChange={this.updateClosedTimeout}
value={getTimeoutAmount(settings.closedTimeout)}
label={t('configure.closed_comments_label')} />
<div className={styles.configTimeoutSelect}>
<SelectField
label="comments closed time window"
value={getTimeoutMeasure(settings.closedTimeout)}
onChange={this.updateClosedTimeoutMeasure}>
<Option value={'hours'}>{t('configure.hours')}</Option>
<Option value={'days'}>{t('configure.days')}</Option>
<Option value={'weeks'}>{t('configure.weeks')}</Option>
</SelectField>
</div>
</div>
</ConfigureCard>
{/* the above card should be the last one if at all possible because of z-index issues with the selects */}
<Slot
fill="adminStreamSettings"
data={data}
queryData={{root, settings}}
updatePending={updatePending}
errors={errors}
/>
</ConfigurePage>
);
}
}
StreamSettings.propTypes = {
updatePending: PropTypes.func.isRequired,
errors: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
};
export default StreamSettings;
@@ -0,0 +1,10 @@
.customCSSInput {
width: 100%;
font-size: 14px;
padding: 14px;
letter-spacing: 0.03em;
color: #555;
box-sizing: border-box;
}
@@ -1,44 +1,70 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Card} from 'coral-ui';
import Domainlist from './Domainlist';
import EmbedLink from './EmbedLink';
import styles from './Configure.css';
import styles from './TechSettings.css';
import Slot from 'coral-framework/components/Slot';
import t from 'coral-framework/services/i18n';
import ConfigurePage from './ConfigurePage';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
const updateCustomCssUrl = (updateSettings) => (event) => {
const customCssUrl = event.target.value;
updateSettings({customCssUrl});
};
class TechSettings extends React.Component {
const TechSettings = ({settings, onChangeDomainlist, updateSettings}) => {
return (
<div className={styles.Configure}>
<Domainlist
domains={settings.domains.whitelist}
onChangeDomainlist={onChangeDomainlist} />
<EmbedLink />
<Card className={styles.configSetting}>
<div className={styles.wrapper}>
<div className={styles.settingsHeader}>{t('configure.custom_css_url')}</div>
updateCustomCssUrl = (event) => {
const updater = {customCssUrl: {$set: event.target.value}};
this.props.updatePending({updater});
};
updateDomainlist = (listName, list) => {
this.props.updatePending({updater: {
domains: {$apply: (domains) => {
const changeSet = {[listName]: list};
if (!domains) {
return changeSet;
}
return {
...domains,
...changeSet,
};
}},
}});
};
render() {
const {settings, data, root, errors, updatePending} = this.props;
return (
<ConfigurePage
title={t('configure.tech_settings')}
>
<Domainlist
domains={settings.domains.whitelist}
onChangeDomainlist={this.updateDomainlist} />
<EmbedLink />
<ConfigureCard title={t('configure.custom_css_url')}>
<p>{t('configure.custom_css_url_desc')}</p>
<input
className={styles.customCSSInput}
value={settings.customCssUrl}
onChange={updateCustomCssUrl(updateSettings)} />
</div>
</Card>
</div>
);
};
onChange={this.updateCustomCssUrl} />
</ConfigureCard>
<Slot
fill="adminTechSettings"
data={data}
queryData={{root, settings}}
updatePending={updatePending}
errors={errors}
/>
</ConfigurePage>
);
}
}
TechSettings.propTypes = {
settings: PropTypes.shape({
domains: PropTypes.shape({
whitelist: PropTypes.array.isRequired
})
}).isRequired,
updateSettings: PropTypes.func.isRequired
updatePending: PropTypes.func.isRequired,
errors: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
};
export default TechSettings;
@@ -1,33 +1,33 @@
import React from 'react';
import t from 'coral-framework/services/i18n';
import TagsInput from 'coral-admin/src/components/TagsInput';
import styles from './Configure.css';
import {Card} from 'coral-ui';
import PropTypes from 'prop-types';
import ConfigureCard from 'coral-framework/components/ConfigureCard';
const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => (
<div>
<Card id={styles.bannedWordlist} className={styles.configSetting}>
<div className={styles.settingsHeader}>{t('configure.banned_words_title')}</div>
<p className={styles.wordlistDesc}>{t('configure.banned_word_text')}</p>
<div className={styles.wrapper}>
<TagsInput
value={bannedWords}
inputProps={{placeholder: 'word or phrase'}}
onChange={(tags) => onChangeWordlist('banned', tags)}
/>
</div>
</Card>
<Card id={styles.suspectWordlist} className={styles.configSetting}>
<div className={styles.settingsHeader}>{t('configure.suspect_word_title')}</div>
<p className={styles.wordlistDesc}>{t('configure.suspect_word_text')}</p>
<div className={styles.wrapper}>
<TagsInput
value={suspectWords}
inputProps={{placeholder: 'word or phrase'}}
onChange={(tags) => onChangeWordlist('suspect', tags)} />
</div>
</Card>
<ConfigureCard title={t('configure.banned_words_title')}>
<p>{t('configure.banned_word_text')}</p>
<TagsInput
value={bannedWords}
inputProps={{placeholder: 'word or phrase'}}
onChange={(tags) => onChangeWordlist('banned', tags)}
/>
</ConfigureCard>
<ConfigureCard title={t('configure.suspect_word_title')}>
<p>{t('configure.suspect_word_text')}</p>
<TagsInput
value={suspectWords}
inputProps={{placeholder: 'word or phrase'}}
onChange={(tags) => onChangeWordlist('suspect', tags)} />
</ConfigureCard>
</div>
);
Wordlist.propTypes = {
suspectWords: PropTypes.array.isRequired,
bannedWords: PropTypes.array.isRequired,
onChangeWordlist: PropTypes.func.isRequired,
};
export default Wordlist;
@@ -1,42 +1,104 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose} from 'react-apollo';
import {
fetchSettings,
updateSettings,
saveSettingsToServer,
updateWordlist,
updateDomainlist
} from '../../../actions/settings';
import {compose, gql} from 'react-apollo';
import {withQuery, withMergedSettings} from 'coral-framework/hocs';
import {Spinner} from 'coral-ui';
import {notify} from 'coral-framework/actions/notification';
import PropTypes from 'prop-types';
import {withUpdateSettings} from 'coral-framework/graphql/mutations';
import {getErrorMessages, getDefinitionName} from 'coral-framework/utils';
import StreamSettings from './StreamSettings';
import TechSettings from './TechSettings';
import ModerationSettings from './ModerationSettings';
import {clearPending, setActiveSection} from '../../../actions/configure';
import Configure from '../components/Configure';
class ConfigureContainer extends Component {
componentWillMount = () => {
this.props.fetchSettings();
}
savePending = async () => {
try {
await this.props.updateSettings(this.props.pending);
this.props.clearPending();
}
catch(err) {
this.props.notify('error', getErrorMessages(err));
}
};
render () {
return <Configure {...this.props} />;
if(this.props.data.loading) {
return <Spinner/>;
}
return <Configure
notify={this.props.notify}
auth={this.props.auth}
data={this.props.data}
root={this.props.root}
settings={this.props.mergedSettings}
canSave={this.props.canSave}
savePending={this.savePending}
setActiveSection={this.props.setActiveSection}
activeSection={this.props.activeSection}
/>;
}
}
const withConfigureQuery = withQuery(gql`
query TalkAdmin_Configure {
settings {
...${getDefinitionName(StreamSettings.fragments.settings)}
...${getDefinitionName(TechSettings.fragments.settings)}
...${getDefinitionName(ModerationSettings.fragments.settings)}
}
...${getDefinitionName(StreamSettings.fragments.root)}
...${getDefinitionName(TechSettings.fragments.root)}
...${getDefinitionName(ModerationSettings.fragments.root)}
}
${StreamSettings.fragments.root}
${StreamSettings.fragments.settings}
${TechSettings.fragments.root}
${TechSettings.fragments.settings}
${ModerationSettings.fragments.root}
${ModerationSettings.fragments.settings}
`, {
options: () => ({
variables: {},
}),
});
const mapStateToProps = (state) => ({
auth: state.auth,
settings: state.settings
pending: state.configure.pending,
canSave: state.configure.canSave,
activeSection: state.configure.activeSection,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
fetchSettings,
updateSettings,
saveSettingsToServer,
updateWordlist,
updateDomainlist
notify,
clearPending,
setActiveSection,
}, dispatch);
export default compose(
withUpdateSettings,
withConfigureQuery,
connect(mapStateToProps, mapDispatchToProps),
withMergedSettings('root.settings', 'pending', 'mergedSettings'),
)(ConfigureContainer);
ConfigureContainer.propTypes = {
updateSettings: PropTypes.func.isRequired,
clearPending: PropTypes.func.isRequired,
setActiveSection: PropTypes.func.isRequired,
notify: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
canSave: PropTypes.bool.isRequired,
pending: PropTypes.object.isRequired,
mergedSettings: PropTypes.object.isRequired,
activeSection: PropTypes.string.isRequired,
};
@@ -0,0 +1,44 @@
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose, gql} from 'react-apollo';
import ModerationSettings from '../components/ModerationSettings';
import withFragments from 'coral-framework/hocs/withFragments';
import {getSlotFragmentSpreads} from 'coral-framework/utils';
import {updatePending} from '../../../actions/configure';
const slots = [
'adminModerationSettings',
];
const mapStateToProps = (state) => ({
errors: state.configure.errors,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
updatePending,
}, dispatch);
export default compose(
withFragments({
root: gql`
fragment TalkAdmin_ModerationSettings_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}
`,
settings: gql`
fragment TalkAdmin_ModerationSettings_settings on Settings {
requireEmailConfirmation
moderation
premodLinksEnable
wordlist {
suspect
banned
}
${getSlotFragmentSpreads(slots, 'settings')}
}
`
}),
connect(mapStateToProps, mapDispatchToProps),
)(ModerationSettings);
@@ -0,0 +1,45 @@
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose, gql} from 'react-apollo';
import StreamSettings from '../components/StreamSettings';
import withFragments from 'coral-framework/hocs/withFragments';
import {getSlotFragmentSpreads} from 'coral-framework/utils';
import {updatePending} from '../../../actions/configure';
const slots = [
'adminStreamSettings',
];
const mapStateToProps = (state) => ({
errors: state.configure.errors,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
updatePending,
}, dispatch);
export default compose(
withFragments({
root: gql`
fragment TalkAdmin_StreamSettings_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}
`,
settings: gql`
fragment TalkAdmin_StreamSettings_settings on Settings {
infoBoxEnable
charCount
charCountEnable
infoBoxContent
editCommentWindowLength
autoCloseStream
closedTimeout
closedMessage
${getSlotFragmentSpreads(slots, 'settings')}
}
`
}),
connect(mapStateToProps, mapDispatchToProps),
)(StreamSettings);
@@ -0,0 +1,41 @@
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose, gql} from 'react-apollo';
import TechSettings from '../components/TechSettings';
import withFragments from 'coral-framework/hocs/withFragments';
import {getSlotFragmentSpreads} from 'coral-framework/utils';
import {updatePending} from '../../../actions/configure';
const slots = [
'adminTechSettings',
];
const mapStateToProps = (state) => ({
errors: state.configure.errors,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
updatePending,
}, dispatch);
export default compose(
withFragments({
root: gql`
fragment TalkAdmin_TechSettings_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}
`,
settings: gql`
fragment TalkAdmin_TechSettings_settings on Settings {
customCssUrl
domains {
whitelist
}
${getSlotFragmentSpreads(slots, 'settings')}
}
`
}),
connect(mapStateToProps, mapDispatchToProps),
)(TechSettings);
@@ -1,47 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router';
import styles from './Widget.css';
import t from 'coral-framework/services/i18n';
const ActivityWidget = ({assets}) => {
return (
<div className={styles.widget}>
<h2 className={styles.heading}>{t('dashboard.most_conversations')}</h2>
<div className={styles.widgetHead}>
<p>{t('streams.article')}</p>
<p>{t('dashboard.comment_count')}</p>
</div>
<div className={styles.widgetTable}>
{
assets.length
? assets.map((asset) => {
return (
<div className={styles.rowLinkify} key={asset.id}>
<Link className={styles.linkToModerate} to={`/admin/moderate/${asset.id}`}>Moderate</Link>
<p className={styles.widgetCount}>{asset.commentCount}</p>
<a className={styles.linkToAsset} href={`${asset.url}`} target="_blank">
<p className={styles.assetTitle}>{asset.title}</p>
</a>
<p className={styles.lede}>{asset.author} Published: {new Date(asset.created_at).toLocaleDateString()}</p>
</div>
);
})
: <div className={styles.rowLinkify}>{t('dashboard.no_activity')}</div>
}
</div>
</div>
);
};
ActivityWidget.propTypes = {
assets: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
url: PropTypes.string,
commentCount: PropTypes.number,
author: PropTypes.string,
created_at: PropTypes.string
})).isRequired
};
export default ActivityWidget;
@@ -1,93 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './Dashboard.css';
import {Icon} from 'coral-ui';
import t from 'coral-framework/services/i18n';
const refreshIntervalSeconds = 60 * 5;
// TODO: refactor out storage code into redux.
class CountdownTimer extends React.Component {
static contextTypes = {
storage: PropTypes.object,
};
static propTypes = {
handleTimeout: PropTypes.func.isRequired
}
constructor (props, context) {
super(props, context);
const {storage} = context;
try {
if (storage && storage.getItem('coral:dashboardNote') === null) {
storage.setItem('coral:dashboardNote', 'show');
}
} catch (e) {
// above will fail in Private Mode in some browsers.
}
this.state = {
secondsUntilRefresh: refreshIntervalSeconds,
dashboardNote: (storage && storage.getItem('coral:dashboardNote')) || 'show'
};
}
componentWillMount () {
this.interval = setInterval(() => { // the countdown timer
let nextCount = this.state.secondsUntilRefresh - 1;
if (nextCount < 0) {
nextCount = refreshIntervalSeconds;
return this.props.handleTimeout();
}
this.setState({secondsUntilRefresh: nextCount});
}, 1000);
}
componentWillUnmount () {
window.clearInterval(this.interval);
}
formatTime = () => {
const minutes = Math.floor(this.state.secondsUntilRefresh / 60);
let seconds = (this.state.secondsUntilRefresh % 60).toString();
if (seconds.length < 2) {
seconds = `0${seconds}`;
}
return `${minutes}:${seconds}`;
}
dismissNote = () => {
const {storage} = this.context;
try {
if (storage) {
storage.setItem('coral:dashboardNote', 'hide');
}
} catch (e) {
// when setItem fails in Safari Private mode
this.setState({dashboardNote: 'hide'});
}
}
render () {
const {storage} = this.context;
const hideReloadNote = (storage && storage.getItem('coral:dashboardNote') === 'hide') ||
this.state.dashboardNote === 'hide'; // for Safari Incognito
return (
<p
style={{display: hideReloadNote ? 'none' : 'block'}}
className={styles.autoUpdate}
onClick={this.dismissNote}>
<b>×</b>
<Icon name='timer' /> <strong>{t('dashboard.next_update', this.formatTime())}</strong> {t('dashboard.auto_update')}
</p>
);
}
}
export default CountdownTimer;
@@ -1,38 +0,0 @@
/**
* @TODO: deprecated as this file contains styles from multiple components. Please refactor.
*/
.Dashboard {
display: flex;
}
.heading {
margin: 0;
font-size: 1.5rem;
font-weight: bold;
}
.autoUpdate {
background-color: #d5d5d5;
padding: 3px 10px 10px 10px;
margin-bottom: 0;
i {
position: relative;
top: 7px;
}
b {
float: right;
border-radius: 20px;
cursor: pointer;
background-color: #c0c0c0;
width: 30px;
height: 30px;
text-align: center;
top: 4px;
position: relative;
line-height: 1.7em;
font-size: 1.3em;
}
}
@@ -1,15 +0,0 @@
import React from 'react';
import FlagWidget from './FlagWidget';
import ActivityWidget from './ActivityWidget';
import CountdownTimer from './CountdownTimer';
import styles from './Dashboard.css';
export default ({root: {assetsByActivity, assetsByFlag}, reloadData}) => (
<div>
<CountdownTimer handleTimeout={reloadData} />
<div className={styles.Dashboard}>
<FlagWidget assets={assetsByFlag} />
<ActivityWidget assets={assetsByActivity} />
</div>
</div>
);
@@ -1,54 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router';
import styles from './Widget.css';
import t from 'coral-framework/services/i18n';
const FlagWidget = ({assets}) => {
return (
<div className={styles.widget}>
<h2 className={styles.heading}>{t('dashboard.most_flags')}</h2>
<div className={styles.widgetHead}>
<p>{t('streams.article')}</p>
<p>{t('dashboard.flags')}</p>
</div>
<div className={styles.widgetTable}>
{
assets.length
? assets.map((asset) => {
let flagSummary = null;
if (asset.action_summaries) {
flagSummary = asset.action_summaries.find((s) => s.__typename === 'FlagAssetActionSummary');
}
return (
<div className={styles.rowLinkify} key={asset.id}>
<Link className={styles.linkToModerate} to={`/admin/moderate/reported/${asset.id}`}>Moderate</Link>
<p className={styles.widgetCount}>{flagSummary ? flagSummary.actionCount : 0}</p>
<a className={styles.linkToAsset} href={`${asset.url}`} target="_blank">
<p className={styles.assetTitle}>{asset.title}</p>
</a>
<p className={styles.lede}>{asset.author} Published: {new Date(asset.created_at).toLocaleDateString()}</p>
</div>
);
})
: <div className={styles.rowLinkify}>{t('dashboard.no_flags')}</div>
}
</div>
</div>
);
};
FlagWidget.propTypes = {
assets: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
url: PropTypes.string,
action_summaries: PropTypes.array,
author: PropTypes.string,
created_at: PropTypes.string
})).isRequired
};
export default FlagWidget;
@@ -1,49 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router';
import styles from './Widget.css';
import t from 'coral-framework/services/i18n';
const LikeWidget = ({assets}) => {
return (
<div className={styles.widget}>
<h2 className={styles.heading}>Articles with the most likes</h2>
<div className={styles.widgetHead}>
<p>{t('streams.article')}</p>
<p>{t('modqueue.likes')}</p>
</div>
<div className={styles.widgetTable}>
{
assets.length
? assets.map((asset) => {
const likeSummary = asset.action_summaries.find((s) => s.type === 'LikeAssetActionSummary');
return (
<div className={styles.rowLinkify} key={asset.id}>
<Link className={styles.linkToModerate} to={`/admin/moderate/${asset.id}`}>Moderate</Link>
<p className={styles.widgetCount}>{likeSummary ? likeSummary.actionCount : 0}</p>
<a className={styles.linkToAsset} href={`${asset.url}`} target="_blank">
<p className={styles.assetTitle}>{asset.title}</p>
</a>
<p className={styles.lede}>{asset.author} Published: {new Date(asset.created_at).toLocaleDateString()}</p>
</div>
);
})
: <div className={styles.rowLinkify}>{t('dashboard.no_likes')}</div>
}
</div>
</div>
);
};
LikeWidget.propTypes = {
assets: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
url: PropTypes.string,
action_summaries: PropTypes.array,
author: PropTypes.string,
created_at: PropTypes.string
})).isRequired
};
export default LikeWidget;

Some files were not shown because too many files have changed in this diff Show More