Compare commits

...

584 Commits

Author SHA1 Message Date
Julian Lam
4a11307b24 0.2.0 2013-12-26 16:04:06 -05:00
Julian Lam
d8183c056c added cache buster to require.js files - fixes #687 2013-12-26 15:58:46 -05:00
Julian Lam
6ad28dadd4 Merge pull request #685 from akhoury/master
can i haz header-icons pls, merry xmas
2013-12-26 12:21:35 -08:00
Baris Soner Usakli
2c489c600c closes #675 2013-12-24 13:12:25 -05:00
akhoury
abc782f5e6 can i haz header-icons pls, merry xmas 2013-12-24 13:00:04 -05:00
Baris Soner Usakli
a18e366493 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-23 22:07:21 -05:00
Baris Soner Usakli
12e95df068 removed console.log 2013-12-23 22:07:13 -05:00
Julian Lam
a078f73e84 omg I don't know what I am doing 2013-12-23 22:06:53 -05:00
Julian Lam
8f879cd3eb topics will no longer show up in /recent if user cannot access them 2013-12-23 21:50:47 -05:00
Julian Lam
8385ceef79 topics in private categories can no longer be accessed via ajaxify or by
direct link
2013-12-23 21:42:34 -05:00
Baris Soner Usakli
83cc8f3ba8 fixed header template value too 2013-12-23 21:03:45 -05:00
Baris Soner Usakli
cab6ab8e17 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-23 21:00:02 -05:00
Baris Soner Usakli
e9fbed71ae closes #613, fixed allowRegistration incase its undefined 2013-12-23 20:59:55 -05:00
Julian Lam
b4121f262d removing serializeUser console.log -- how long has this ben here? haha 2013-12-23 20:51:17 -05:00
Julian Lam
256a2fa9c6 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-23 20:12:43 -05:00
Julian Lam
0f362b7fac updated bootstrap - because why not 2013-12-23 20:07:00 -05:00
Baris Soner Usakli
b504e2cd11 closes #658 2013-12-23 19:17:03 -05:00
Baris Soner Usakli
ea84fd70af Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-23 15:40:24 -05:00
Baris Soner Usakli
09efb83ef3 make sure relativeTime doesn't display negative values 2013-12-23 15:40:16 -05:00
Julian Lam
b2aeb14094 upping vanilla minver 2013-12-23 15:28:39 -05:00
Julian Lam
0ed8fd6cbd Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-23 15:23:45 -05:00
Julian Lam
2f1a3b9789 enabled touch events for composer resizing -- composer is now ipad
supported!
2013-12-23 15:23:08 -05:00
Baris Soner Usakli
d068139d81 changed header links to icons 2013-12-23 14:40:58 -05:00
Baris Soner Usakli
764e937c43 removed inline style 2013-12-23 14:21:28 -05:00
Baris Soner Usakli
f72cf35348 closes #680 2013-12-23 13:59:12 -05:00
Baris Soner Usakli
fe1a75d1fd paginator starts hidden 2013-12-23 13:49:24 -05:00
Baris Soner Usakli
3dc9e2f4fa added the success alert 2013-12-23 13:31:13 -05:00
Baris Soner Usakli
3bd8cf69a1 admins can create users from admin/users panel 2013-12-23 13:27:26 -05:00
Baris Soner Usakli
2c8725558e added allowRegistration to install 2013-12-23 12:31:51 -05:00
Baris Soner Usakli
f68f02d346 closes #679 2013-12-23 12:22:50 -05:00
Barış Soner Uşaklı
8fd78199e2 Merge pull request #678 from aonz1982/install_mongo_username
Installation problem when selecting MongoDB
2013-12-23 08:23:56 -08:00
Pongsan Sayampol
1bde86a33f MongoDB username is not saved to the config file during the installation. 2013-12-23 23:07:18 +07:00
Baris Soner Usakli
b6d4ae2732 removed mobile menu 2013-12-22 15:20:11 -05:00
Baris Soner Usakli
680dbf138a closes #669 2013-12-22 15:15:59 -05:00
Baris Soner Usakli
3752a1c691 small fixes 2013-12-21 19:42:21 -05:00
Baris Soner Usakli
3a00c177d3 closes #150 2013-12-21 19:42:07 -05:00
Baris Soner Usakli
845e5e7986 no need to store taskbar 2013-12-21 00:18:11 -05:00
Baris Soner Usakli
57d2db36e6 if not term just use empty string 2013-12-21 00:07:00 -05:00
Baris Soner Usakli
8bfea656c4 Merge branch 'master' of https://github.com/akhoury/NodeBB into akhoury-master 2013-12-20 23:53:53 -05:00
Baris Soner Usakli
ea2c03e28b closes #670 2013-12-20 23:35:40 -05:00
Baris Soner Usakli
f29b375ed4 refactored composer so that it uses a different div for each instance, closes #575 2013-12-20 18:41:56 -05:00
Julian Lam
07f1e0bcb5 ninjafix -- if you don't have a saved composer width, it doesn't set a
width (default ot 50%)
2013-12-20 12:34:26 -05:00
Julian Lam
0b94297c64 Merge remote-tracking branch 'origin/master' into composer-revamp 2013-12-19 18:36:20 -05:00
Baris Soner Usakli
8655c2d2a6 removed console.log 2013-12-19 15:43:15 -05:00
Baris Usakli
da9c673ec4 closes #651 2013-12-19 14:57:59 -05:00
Julian Lam
1e6863ee19 adjusting snap guide sensitivity 2013-12-19 00:08:47 -05:00
Julian Lam
00eb6b4efc responsive fixes for new composer 2013-12-19 00:02:14 -05:00
Julian Lam
002826d84f resizing the post composer now saves the size for future windows 2013-12-18 23:56:59 -05:00
Julian Lam
289e081e2e fixed new composer posting (woot) 2013-12-18 23:18:12 -05:00
Baris Soner Usakli
a717e9626e closes #666, the issue of the beast 2013-12-18 19:23:11 -05:00
Julian Lam
83f20c1cdb OMG SNAPS 2013-12-18 18:48:42 -05:00
Baris Soner Usakli
bc8adff70a fixed plugin deactivation 2013-12-18 15:32:38 -05:00
Julian Lam
c4623e2447 Merge remote-tracking branch 'origin/master' into composer-revamp 2013-12-18 15:12:30 -05:00
Julian Lam
99fba3b83a fixing issue where composer pushing didn't wait for the template to
properly render :P
2013-12-18 10:03:49 -05:00
Baris Soner Usakli
2580caf864 fixing #591 again looks like it got overwritter by merge 2013-12-18 05:35:06 -05:00
Julian Lam
f2d631e42d new composer window template (WIP!) 2013-12-17 23:42:02 -05:00
Julian Lam
d86aefb518 removing defunct "template" argument in ajaxify.go 2013-12-17 21:53:50 -05:00
psychobunny
3782ae1647 don't show profile fields if they are hidden. closes #660. also added missing language keys to EN 2013-12-17 18:05:58 -05:00
psychobunny
36e1a121ed removing some console.log's 2013-12-17 17:48:51 -05:00
psychobunny
2e52dd59ee Merge pull request #664 from ifuyivara/master
Adding support for restricting category read access based on user groups
2013-12-17 14:47:25 -08:00
psychobunny
d7a444d9ab dynamically update post count in post footer on new post 2013-12-17 16:10:32 -05:00
psychobunny
f9e2b50826 dynamically update user rep in post footer if reputation is increased 2013-12-17 16:01:08 -05:00
psychobunny
32a32fcf5c match login.tpl button to look like register.tpl 2013-12-17 15:42:01 -05:00
psychobunny
9435acfa71 skip debug messages for supervisor 2013-12-17 15:37:42 -05:00
root
35ad3be969 Adding support for restricting category read access based on user groups 2013-12-17 20:34:21 +00:00
Baris Soner Usakli
9cb20c3886 added callback to api categories.get 2013-12-16 19:12:26 -05:00
psychobunny
a2c9867902 plugins - woops, wrong namespace for admin api calls 2013-12-16 15:45:52 -05:00
psychobunny
58a3f33200 plugins - added api routes to filter:admin.create_routes 2013-12-16 15:40:59 -05:00
psychobunny
25bac03bab fixed facebook + gplus authentication - callbackURL was invalid 2013-12-15 14:12:36 -05:00
Baris Soner Usakli
770cea9329 added more error first to some functions 2013-12-14 16:29:33 -05:00
Baris Soner Usakli
30c11a8b42 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-13 16:36:38 -05:00
Baris Soner Usakli
27a01f6c61 closes #657 2013-12-13 16:36:29 -05:00
psychobunny
bf27ade251 admin - added ability to remove icon from categories 2013-12-13 16:26:32 -05:00
psychobunny
9d88b9eed3 default motd now shows @NodeBB, and not @dcplabs 2013-12-13 15:55:24 -05:00
akhoury
04ea573caa removed jQuery from iife, the $ is global 2013-12-12 22:52:44 -05:00
akhoury
d9eefd667c fixed potential guestSearch config bug 2013-12-12 22:51:17 -05:00
akhoury
3ad98f3783 remove uncessary checks in guest config upgrade 2013-12-12 22:50:49 -05:00
akhoury
b89cf6f480 Merge remote-tracking branch 'upstream/master' 2013-12-12 22:40:25 -05:00
psychobunny
4397da144f fixes crash introduced @1021615848e49da3434f00cfdb6fb79ab5990b47 2013-12-12 16:07:15 -05:00
psychobunny
cf8f0ca225 cleanup 2013-12-12 16:02:12 -05:00
Baris Soner Usakli
885242018f one more 2013-12-12 12:19:03 -05:00
Baris Soner Usakli
1abfe5de63 added err to addUserInfoToPost 2013-12-12 12:17:58 -05:00
akhoury
04dd1f9dac Merge remote-tracking branch 'upstream/master' 2013-12-11 22:51:04 -05:00
akhoury
114294e24a allowGuestSearching config .. second attempt 2013-12-11 22:50:36 -05:00
Baris Soner Usakli
dfa4cd4ae3 closes #653 2013-12-11 21:40:55 -05:00
Julian Lam
65d5a6cb81 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-11 16:10:22 -05:00
Julian Lam
64e87b761f closed #652 2013-12-11 16:10:08 -05:00
Baris Soner Usakli
1021615848 added err first to some calls 2013-12-11 16:08:20 -05:00
Julian Lam
69c1ec97c9 re: issue #652, this took longer than expected... 2013-12-11 16:02:29 -05:00
Julian Lam
45e7d64aeb fixing extra padding around 'in' that jshinter added for no goddamn reason 2013-12-11 12:29:35 -05:00
Julian Lam
b86a01ded1 moving cache buster to production builds only (*facepalm* I'm bad at this) 2013-12-10 22:20:11 -05:00
Julian Lam
e67af67180 fixing derped plugin css files due to cache buster 2013-12-10 22:16:43 -05:00
Julian Lam
9d03147f4e upping mentions minver 2013-12-10 22:07:10 -05:00
Julian Lam
c313c4501b pushNotifCount method for real-time updating of notification bell + favicon for multiple tabs (closes #219) 2013-12-10 22:05:37 -05:00
Julian Lam
538356846d fixed regression introduced by #643. Non-logo favicon is now properly
referenced (absolute url, not relative)
2013-12-10 21:20:54 -05:00
Baris Usakli
55d008d71f added err to callbacks 2013-12-10 15:39:53 -05:00
Baris Usakli
401a30e02c fixed categories.getRecentReplies so it only returns count posts instead of getting 10, posts are added and removed from sorted set when they are deleted restored 2013-12-10 15:33:35 -05:00
Baris Usakli
9816272b7b if there are more than 50 results only return 50, issue #648 2013-12-10 15:02:22 -05:00
Julian Lam
d72d2decd5 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-09 14:50:59 -05:00
Julian Lam
43c05d1d85 adding cache busters to client side files (closed #586) 2013-12-09 14:50:40 -05:00
Barış Soner Uşaklı
14f35a8c6b Update README.md 2013-12-09 14:49:57 -05:00
Barış Soner Uşaklı
ffe1549cad Update README.md 2013-12-09 14:49:03 -05:00
Barış Soner Uşaklı
3ca58a438d Update README.md 2013-12-09 14:44:26 -05:00
Baris Usakli
5da4cead67 closes #631 2013-12-09 14:37:13 -05:00
Baris Usakli
0000a7f0b9 #631 2013-12-09 14:16:04 -05:00
Baris Usakli
27ac24b1e3 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-09 13:56:18 -05:00
Baris Usakli
95495926fc some fixes to composer image upload 2013-12-09 13:56:09 -05:00
psychobunny
0f254c0b6c moved theme.css to top 2013-12-09 13:36:48 -05:00
psychobunny
b27478876e moved favicon link to top of header 2013-12-09 13:36:47 -05:00
psychobunny
a3734f2e15 completed custom favicon upload, closes #643 2013-12-09 13:36:47 -05:00
psychobunny
1b843fba9c added admin route to upload favicon 2013-12-09 13:36:46 -05:00
psychobunny
35f17db141 added button in admin to upload favicon + show current favicon image 2013-12-09 13:36:45 -05:00
Barış Soner Uşaklı
bcb364c4d4 Merge pull request #644 from designcreateplay/dbal
Dbal
2013-12-09 09:47:24 -08:00
Baris Usakli
6e16cb4b30 fixed conflicts 2013-12-09 12:46:27 -05:00
Baris Usakli
40e71299a1 closes #642 2013-12-09 12:39:36 -05:00
Julian Lam
0148cf06d0 replaced all instances of missing config.relative_path to RELATIVE_PATH 2013-12-09 10:02:34 -05:00
Julian Lam
ffa31ca0e7 upping markdown minver 2013-12-08 16:59:21 -05:00
Barış Soner Uşaklı
ba3b8a21ae Merge pull request #640 from akhoury/master
issue#635
2013-12-08 12:26:24 -08:00
akhoury
05209b01b9 setting initialValues for 'global' object closes #635 2013-12-08 15:18:00 -05:00
akhoury
4e0d0c2c20 adding error.log .gitignore, winston is that you? 2013-12-08 15:16:37 -05:00
Baris Soner Usakli
225284073f Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-08 14:50:11 -05:00
psychobunny
ccef51095a fix typo 2013-12-08 14:49:47 -05:00
Baris Soner Usakli
cd77a1a457 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-08 14:42:54 -05:00
Baris Soner Usakli
6aeca98cd4 closes #633 2013-12-08 14:42:47 -05:00
psychobunny
07a3b3f00b added delete button to category image uploader in case you wanted to revert to bgColor 2013-12-08 14:37:44 -05:00
Barış Soner Uşaklı
77e0cdcc3e Merge pull request #637 from akhoury/master
Auto install fix
2013-12-08 11:22:17 -08:00
psychobunny
e316dd3330 fixed a bug in create category 2013-12-08 14:20:57 -05:00
psychobunny
b511653e74 fixes #622 2013-12-08 14:15:03 -05:00
psychobunny
b5e37a6ce8 fixes #123, parse object properties in template outside of namespace 2013-12-08 13:50:11 -05:00
psychobunny
a34ed92fac console.log 2013-12-08 13:27:41 -05:00
psychobunny
4ff8509a0e clean up from the last admin/categories refactor 2013-12-08 13:19:20 -05:00
psychobunny
e76936abfc added ability to upload category images. closes #638, closes #532 2013-12-08 13:13:13 -05:00
Baris Soner Usakli
9471fd8e46 closes #635 2013-12-08 13:04:38 -05:00
akhoury
2d4ceb8f9f should close #634 2013-12-08 11:59:48 -05:00
psychobunny
4c40ee8e6e fixed missing language key on image uploader modal 2013-12-08 11:31:57 -05:00
psychobunny
ddcf46fc73 uploading picture didn't update profile image until refreshed - fixed 2013-12-08 11:30:29 -05:00
psychobunny
7db234f958 added setting to convert profile iamges to png in control panel 2013-12-08 11:26:55 -05:00
psychobunny
f6f7959d28 convert profile images to static png if setting is checked in control panel, closes #562 2013-12-08 11:25:15 -05:00
psychobunny
7fa2f474fe fixes bug introduced in c0721e105f 2013-12-08 10:55:34 -05:00
psychobunny
d5e8044575 ability to disable privilege threshold system, closes #528 2013-12-08 10:49:42 -05:00
psychobunny
c0721e105f added setting to disable privilege threshold system 2013-12-08 10:47:05 -05:00
psychobunny
a475e38078 if app is not focused and chat message comes in, activate alternatingTitle. closes #620 2013-12-08 10:40:02 -05:00
psychobunny
932b960aa9 app.isFocused; app.js cleanup 2013-12-08 10:38:09 -05:00
psychobunny
24b12e23ea fixes #636, conditionals broken from f1ad469861 2013-12-08 10:31:18 -05:00
psychobunny
2a5d6e04fc fixes #583 (aka. "son, we heard you like containers so we put containers inside your containers") -- duly fixed 2013-12-08 10:23:47 -05:00
psychobunny
4459d9d4e0 closes #551 2013-12-07 19:18:57 -05:00
psychobunny
2be3158aff added semver dep, pls run npm install semver 2013-12-07 19:11:50 -05:00
psychobunny
f1ad469861 templates - don't clean up selector conditionals; fixes topic posting bug introduced at 090d35f306 2013-12-07 19:07:51 -05:00
psychobunny
0c05ee82b1 #621, moved everything out of parallel - poster doesn't need to wait for these functions to happen
also renamed topics.markUnRead to topics.markAsUnreadForAll
2013-12-07 18:58:27 -05:00
psychobunny
4f97275d24 closes #621 2013-12-07 18:45:26 -05:00
psychobunny
4b9bfca767 français, deutsche, and español support for 202a4c4105 2013-12-07 18:22:31 -05:00
psychobunny
202a4c4105 added rep + post count metrics to post body, closes #443 2013-12-07 18:19:06 -05:00
psychobunny
090bc2ad10 403 all guests on /search & /search/term regardless of mobile/desktop - closes #612 2013-12-07 17:45:51 -05:00
psychobunny
000c7efb1a Merge pull request #623 from tedr56/master
French language files
2013-12-07 14:29:10 -08:00
psychobunny
90ad08a00d fixes #616 2013-12-07 17:17:47 -05:00
psychobunny
90e1e2436c closes #539 2013-12-07 17:03:16 -05:00
Baris Soner Usakli
21f5dad1d2 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-07 17:03:14 -05:00
Baris Soner Usakli
bc8bb352a8 added stdout check to exec 2013-12-07 17:03:07 -05:00
psychobunny
274310e35a removed notification count in title, removed api calls to it (left method intact) so hopefully title building is faster too. closes #625 2013-12-07 16:57:49 -05:00
Baris Soner Usakli
0bcc1642c7 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-07 16:51:57 -05:00
Baris Soner Usakli
d1d6605dcf closes #501 2013-12-07 16:51:47 -05:00
psychobunny
da94d6214b when new notification comes in, refresh notification page - closes #608 2013-12-07 16:42:17 -05:00
psychobunny
67e49db797 ajaxify.refresh(); removed console.log 2013-12-07 16:40:14 -05:00
psychobunny
de9100c489 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-07 16:33:56 -05:00
psychobunny
4348e1efa4 use ajaxify.currentPage to find the user's location easily 2013-12-07 16:33:42 -05:00
Julian Lam
6de3dba239 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-07 16:33:41 -05:00
Julian Lam
021cf9b8f6 fixes to language template usage 2013-12-07 16:33:37 -05:00
psychobunny
ca087e6fa7 fixes #576 2013-12-07 16:27:22 -05:00
psychobunny
6c9e28232f added translation method to recent's infinite loader 2013-12-07 16:21:12 -05:00
psychobunny
ceac8e2dc9 added translation to unread infinite loader 2013-12-07 16:20:31 -05:00
psychobunny
98cf6eec71 shift clicking now opens links in a new window, closes #630 2013-12-07 16:18:07 -05:00
Baris Soner Usakli
5a00767370 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-07 16:15:15 -05:00
Baris Soner Usakli
4c90d22e43 closes #619 2013-12-07 16:15:07 -05:00
psychobunny
e0e153eafb added translation to category infinite loader method 2013-12-07 16:14:51 -05:00
psychobunny
5c3c2623f2 added translation to new post creation, closes #627 2013-12-07 16:14:51 -05:00
Baris Soner Usakli
34fc326a37 closes #618 2013-12-07 15:59:44 -05:00
psychobunny
36745608bf removed console.log 2013-12-07 15:49:48 -05:00
psychobunny
090d35f306 clean up conditional comments in the DOM; conditionals now treat undefined variables as false; closes #617 2013-12-07 15:48:35 -05:00
Julian Lam
347f5c132e updates to language files, capitalizing some values across languages 2013-12-07 15:47:00 -05:00
Julian Lam
d6f8162f17 upping markdown minver again? 2013-12-07 15:02:00 -05:00
Julian Lam
b0b0f3640c closed #629 2013-12-07 15:00:12 -05:00
Julian Lam
4fd08332cc Merge branch 'dbal' of github.com:designcreateplay/NodeBB into dbal 2013-12-07 13:12:07 -05:00
Julian Lam
aaaffb823f upgrading markdown minver 2013-12-07 13:11:59 -05:00
Baris Soner Usakli
76636b64db small fixes 2013-12-06 21:08:21 -05:00
Baris Soner Usakli
be6ed43223 removed the setName from sorted sets and stored them with _key like everything else 2013-12-06 18:58:22 -05:00
Barış Soner Uşaklı
9f2196abfb Merge pull request #626 from designcreateplay/dbal
Dbal
2013-12-06 15:08:32 -08:00
Baris Soner Usakli
90a75ee045 added check for unknown db 2013-12-06 17:51:16 -05:00
Baris Soner Usakli
2a21b4855e fixed instruction in database.js 2013-12-06 17:47:48 -05:00
Baris Soner Usakli
8f769d53a3 fixed missing winston 2013-12-06 17:46:03 -05:00
Baris Usakli
9ee250b597 fixes humanreadable numbers in infinite scrolling 2013-12-06 16:26:07 -05:00
Baris Usakli
074d7e7c8d Merge remote-tracking branch 'origin/master' into dbal 2013-12-06 15:58:58 -05:00
Barış Soner Uşaklı
870d48dc81 Merge pull request #603 from Joopmicroop/master
added account class for account template pages for easy styling
2013-12-06 12:38:32 -08:00
Baris Usakli
9ca10c25d4 fixed return in posts.create 2013-12-06 15:23:48 -05:00
tedr56
8e2cc1c883 Correct english language file 2013-12-06 21:06:07 +01:00
tedr56
af09f4aca8 added french language files 2013-12-06 21:04:57 +01:00
Baris Usakli
ab63ca6d92 store strings in sorted sets and lists to mimic redis 2013-12-06 14:53:03 -05:00
Baris Usakli
400845ce6c cleanup mongo init 2013-12-06 14:34:25 -05:00
Baris Usakli
351b07bb34 added authentication to mongo 2013-12-06 14:31:11 -05:00
Baris Usakli
f861d44d55 updated upgrade script to use mongo or redis 2013-12-06 14:22:31 -05:00
Baris Usakli
2b7e4cbdf4 moved tests from debug to tests folder 2013-12-06 13:46:12 -05:00
Baris Usakli
df10bde2db added 1 more parseInt 2013-12-06 13:30:44 -05:00
Baris Usakli
0da141e7bc removed redismock, added database mocked, fixed tests to work with dbal 2013-12-06 13:21:21 -05:00
Baris Usakli
6313a5eeb1 Merge remote-tracking branch 'origin/master' into dbal 2013-12-06 12:59:32 -05:00
Pablo Macaluso
26de85c1de updated es translations with new strings added from #607 2013-12-06 12:21:34 -05:00
Julian Lam
a54f464a13 updating language files with missing files for es 2013-12-06 11:57:03 -05:00
Julian Lam
bfbc596348 fixing extra comma in es language file 2013-12-06 11:38:33 -05:00
Julian Lam
7508bd216e new executable 2013-12-06 11:27:34 -05:00
Pablo Macaluso
8cfc5dda37 added spanish language files (courtesy of Pablo Macaluso) 2013-12-06 10:51:20 -05:00
Julian Lam
b81737bc0f moved refreshTitle into app.js, messaging someone now invokes an alternating title, hehe 2013-12-05 23:24:47 -05:00
Baris Soner Usakli
1c23be8911 removed console.log 2013-12-05 21:53:24 -05:00
Baris Soner Usakli
5f86e31d1e fixed favouriting 2013-12-05 21:51:05 -05:00
Baris Soner Usakli
746119bd45 remove dataFileVersion it breaks templates 2013-12-05 21:45:21 -05:00
Julian Lam
385aa6df92 fixed last couple tweaks, ready t'merge 2013-12-05 21:36:21 -05:00
Baris Soner Usakli
097810a057 parseInt fixes getObjects fix 2013-12-05 21:29:51 -05:00
Baris Soner Usakli
3a7fcc2d3d search in mongo 2013-12-05 21:07:35 -05:00
Baris Soner Usakli
95bb838699 Merge remote-tracking branch 'origin/master' into dbal 2013-12-05 21:04:00 -05:00
Baris Soner Usakli
81055523a0 fixed bracket 2013-12-05 20:24:25 -05:00
Baris Soner Usakli
e9fbab0f26 need mongo 2.4+ for text search' 2013-12-05 20:11:05 -05:00
Baris Soner Usakli
53ca7a1143 added search functions to database files, removed reds from nodebb moved it to redis 2013-12-05 20:06:36 -05:00
Baris Soner Usakli
6c70d37f1c removed reds from app.js 2013-12-05 18:32:45 -05:00
Baris Soner Usakli
447073560f moved reds into redis, fixed notifications prune param 2013-12-05 18:31:15 -05:00
Julian Lam
2c131f172a fixing up some translations - WIP 2013-12-05 18:27:37 -05:00
Baris Soner Usakli
1564e3d530 tons of fixes to mongo and redis, to make returns the same 2013-12-05 18:26:26 -05:00
Julian Lam
3d9a732c4a Merge branch 'master' of github.com:BudickDa/NodeBB into BudickDa-master
Conflicts:
	public/language/en/global.json
2013-12-05 18:05:26 -05:00
Julian Lam
4819bea378 more tweaks to the chat dropdown -- handling null case -- issue #615 2013-12-05 17:41:51 -05:00
Julian Lam
030ce95dea closed #615 - added "active chats" dropdown to header
- some minor tweaks also, to make taskbar work a little better with chats
2013-12-05 17:35:44 -05:00
Julian Lam
2a1671ba9b whoops 2013-12-05 16:40:30 -05:00
Julian Lam
a65c79cb02 minimized the reconnect spinner to icon only, added bootstrap tooltip 2013-12-05 16:08:35 -05:00
Baris Usakli
dcbe4ffd4a more notif.prune cleanup 2013-12-05 15:32:36 -05:00
Baris Usakli
215b919362 added db function 2013-12-05 15:29:27 -05:00
Baris Usakli
58df656c65 removed temp vars 2013-12-05 15:27:14 -05:00
Baris Usakli
a8c91e2452 more 2013-12-05 15:26:30 -05:00
Baris Usakli
806a454b05 fixing notifications.prune 2013-12-05 15:25:58 -05:00
Baris Usakli
705754e823 merged master 2013-12-05 14:57:18 -05:00
Baris Usakli
fe527ff2a9 removed RedisStoreLib from websockets.js it moved into redis.js 2013-12-05 14:48:58 -05:00
Julian Lam
041e77f688 fixing replying (whoops) 2013-12-05 14:48:27 -05:00
Baris Usakli
b927f6ce29 added raw info 2013-12-05 14:30:18 -05:00
Baris Usakli
519d376071 added mongo info function, change admin redis template to database template 2013-12-05 14:24:18 -05:00
Julian Lam
d9ee9bf5e3 revamped handling of unread messages, so that a socket call is made to all socket clients whenever a new unread message is available. Prior behaviour had the unread count updated via ajax call on ajaxify (which was clumsy at best and didn't update automagically) 2013-12-05 13:59:16 -05:00
Baris Usakli
67d5ea83e7 replace . with \uff0e in mongo 2013-12-05 13:33:01 -05:00
Baris Usakli
7875138c08 added parseInt 2013-12-05 13:11:27 -05:00
Julian Lam
43b012b32e defactored getUnreadTopics into separate getUnreadTids method -- for no reason, mind you 2013-12-05 12:20:56 -05:00
Baris Usakli
c096656eff merged master fixed conflicts 2013-12-05 12:17:01 -05:00
Baris Usakli
2dd295118c setRemove converts to string too 2013-12-05 12:04:09 -05:00
Baris Soner Usakli
567997ef3c changed mongo sets to store just strings, fixes worlds problems 2013-12-04 23:51:57 -05:00
Baris Soner Usakli
c698af17ae added error checking to collection index creation 2013-12-04 23:36:52 -05:00
Baris Soner Usakli
39b70a9e09 derp 2013-12-04 22:55:31 -05:00
Baris Soner Usakli
9b557cafd8 better sets in mongo, should change sorted sets too using sort 2013-12-04 22:19:11 -05:00
Julian Lam
fe4aee177d lots of tweaks to chat and taskbar 2013-12-04 21:44:36 -05:00
Baris Soner Usakli
7c4347736c added index on _key 2013-12-04 21:35:38 -05:00
Julian Lam
16e07d475f pushing FA icon for chat taskbar title 2013-12-04 21:05:44 -05:00
Julian Lam
2125bb2223 only minimizing CSS files on non-development 2013-12-04 20:37:13 -05:00
Baris Soner Usakli
72a3ab1d6c derp 2013-12-04 19:06:36 -05:00
Baris Soner Usakli
639247a8b0 fixed notifications 2013-12-04 18:58:20 -05:00
Baris Soner Usakli
f0caac242c fixed incr in topic post 2013-12-04 18:34:58 -05:00
Baris Soner Usakli
e066fbf36a sets are storing numbers in mongo as opposed to redis which stores strings, causes tons of problems 2013-12-04 18:26:26 -05:00
Baris Soner Usakli
b215dbde19 updated install 2013-12-04 17:57:51 -05:00
Baris Soner Usakli
1325e4c501 commented out reds in install 2013-12-04 17:08:49 -05:00
Baris Soner Usakli
2e2938616d more mongo and redis stuff 2013-12-04 16:58:06 -05:00
Baris Soner Usakli
53a7eab3e8 removed couple RDB.multis 2013-12-04 16:31:05 -05:00
Julian Lam
6bd4a34e69 fixed favicon sometimes updating with a string 0, should always be an int 2013-12-04 16:28:18 -05:00
Julian Lam
d27f2eb214 fixed #604 2013-12-04 16:25:42 -05:00
Baris Soner Usakli
b547d3577b removed a multi from categories.js 2013-12-04 15:13:43 -05:00
Baris Soner Usakli
4b5988c269 isSetMember returns true or false 2013-12-04 15:11:17 -05:00
Baris Soner Usakli
cfd3a7d126 added flushdb command to both dbs 2013-12-04 14:51:50 -05:00
Baris Soner Usakli
0471a192ab more mongo stuff 2013-12-04 14:25:14 -05:00
Baris Soner Usakli
5c6a7d4b94 added regex keys to mongo 2013-12-04 12:36:22 -05:00
Baris Soner Usakli
ca01fb9f7d added key methods to mongo 2013-12-04 12:25:53 -05:00
Julian Lam
b176629b44 integrated Tinycon lib and actually fixed notification counts... heh.
closed #610
2013-12-04 12:15:27 -05:00
Baris Soner Usakli
113cb85c46 added lists to mongo 2013-12-04 12:10:53 -05:00
Julian Lam
5b6f5ebf9d added tinycon lib and changed notif icon to be in CSS instead of in
template
2013-12-04 11:40:57 -05:00
Baris Soner Usakli
21bbe68c97 added sortedSetRemove to mongo 2013-12-03 22:30:36 -05:00
Baris Soner Usakli
28c75e09a9 can haz sorted sets? 2013-12-03 22:16:44 -05:00
Julian Lam
69f453c73c Merge pull request #601 from cnvo/patch-1
Replace notifications icons from fa-circle to fa-bell
2013-12-03 18:20:50 -08:00
Julian Lam
dab0435d9b Merge pull request #600 from cnvo/patch-2
Replace notifications icons from fa-circle to fa-bell
2013-12-03 18:20:35 -08:00
Baris Soner Usakli
b5770be71f whitespace 2013-12-03 18:19:27 -05:00
Baris Soner Usakli
bf3822e8a5 incr wil create key if it doesnt exist 2013-12-03 18:11:35 -05:00
Baris Soner Usakli
cb6c42ea44 user stuff 2013-12-03 18:03:50 -05:00
Baris Soner Usakli
3dc3769088 fixed redis.keys 2013-12-03 17:48:18 -05:00
Baris Soner Usakli
3d18c4015a cleanup 2013-12-03 17:43:12 -05:00
Baris Soner Usakli
610d45bb32 completed hashes in mongodb I hope :) 2013-12-03 17:29:10 -05:00
Baris Soner Usakli
66bc4184d8 deleteObjectField, isObjectField in mongo 2013-12-03 17:13:59 -05:00
Baris Soner Usakli
b024d10185 implemented getObjectValues in mongo 2013-12-03 16:50:06 -05:00
Julian Lam
e847c015a5 linting notifications.js 2013-12-03 16:12:59 -05:00
Baris Usakli
10474f8e2a more mongo work 2013-12-03 15:17:42 -05:00
BudickDa
8a99eef4fb Update global.json 2013-12-03 20:40:45 +01:00
Julian Lam
da66efe7a5 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-03 14:23:31 -05:00
Julian Lam
1bd94b4e41 closed #605 2013-12-03 14:23:16 -05:00
Baris Usakli
e862a1c4cc added init method to database, progress made 2013-12-03 14:21:08 -05:00
psychobunny
8b55920acf plugins - filter:posts.custom_profile_info pass in pid as well 2013-12-03 14:19:11 -05:00
BudickDa
32df811765 i18n for all templates completed, jsons for german added 2013-12-03 19:53:16 +01:00
Baris Usakli
91d6f83de4 more mongo work 2013-12-03 13:36:44 -05:00
psychobunny
7c8f857aaf plugins - filter:server.create_routes allows you to define API routes as well now 2013-12-03 13:10:46 -05:00
psychobunny
1f970c3bdb incorrect url was being passed for callback - twitter and g+ 2013-12-03 11:28:55 -05:00
Joopmicroop
700cab686b Update following.tpl 2013-12-03 15:49:10 +01:00
Joopmicroop
af06e0335a Update followers.tpl 2013-12-03 15:48:28 +01:00
Joopmicroop
4a8dc82bd2 Update accountedit.tpl 2013-12-03 15:45:15 +01:00
Joopmicroop
8a4e2b1ea0 Update accountsettings.tpl 2013-12-03 15:42:33 +01:00
Baris Soner Usakli
1f52717f1e fixed indent 2013-12-02 22:50:39 -05:00
Baris Soner Usakli
304285e874 some mongo stuff 2013-12-02 22:48:32 -05:00
Baris Soner Usakli
d4eddc6e2c lcased groups 2013-12-02 22:36:26 -05:00
Baris Soner Usakli
6d79521922 moved connect-redis to the redis.db file, expose the sessionStore from redis.js db file, do the same for mongo db with mongo-connect 2013-12-02 22:33:55 -05:00
Baris Soner Usakli
95db5f93cb remvoed console.logs 2013-12-02 22:01:29 -05:00
Baris Soner Usakli
b900bc9cce more fixes 2013-12-02 21:58:37 -05:00
Baris Soner Usakli
fc066c21bf added upgrade for global keys 2013-12-02 21:33:35 -05:00
Baris Soner Usakli
32d5118266 tons more changes 2013-12-02 21:20:55 -05:00
Baris Soner Usakli
3775c8e50a tons more changes 2013-12-02 19:40:11 -05:00
Barış Soner Uşaklı
99fbc0dfd5 Update account.js
removed extra s
2013-12-02 19:23:52 -05:00
Baris Soner Usakli
e32d230974 format 2013-12-02 17:48:21 -05:00
Baris Usakli
c9308efbec more work 2013-12-02 17:10:26 -05:00
Baris Usakli
636551d2e9 plugins.js uses db, added some set methods to redis.js 2013-12-02 16:35:32 -05:00
Baris Usakli
347d6c2768 moved filename function into redis 2013-12-02 16:23:14 -05:00
Baris Usakli
4f654fb489 more work 2013-12-02 16:19:30 -05:00
Baris Usakli
80e7fd93c6 added redis 2013-12-02 15:46:25 -05:00
Baris Usakli
95efb2ae5e started dbal 2013-12-02 15:45:15 -05:00
Baris Usakli
8d3a647d16 fixed hardcoded userslug 2013-12-02 14:53:33 -05:00
Baris Usakli
53afe6cb68 closes #591 2013-12-02 14:40:34 -05:00
Barış Soner Uşaklı
391b8098a3 Merge pull request #588 from akhoury/master
websockets to follow same pattern, added hook action:user.create
2013-12-02 11:25:51 -08:00
Baris Usakli
190948336a closes #590 2013-12-02 13:28:46 -05:00
Julian Lam
fcda27e251 allowing plugins with no hooks to not cause NodeBB to hang on app start 2013-12-02 11:36:46 -05:00
Trvr
a48a07603c Replace notifications icons from fa-circle to fa-bell
We should change this icon to utilize the icons better.
2013-12-02 04:40:20 -05:00
Trvr
d930e2a1be Replace notifications icons from fa-circle to fa-bell
We should change this icon to utilize the icons better.
2013-12-02 04:40:19 -05:00
Baris Soner Usakli
7e2166903f Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-12-01 21:12:13 -05:00
Baris Soner Usakli
d5c0ca4a9d closes #595 2013-12-01 21:12:05 -05:00
Julian Lam
7695e76494 removed buildFooter filter 2013-12-01 21:04:10 -05:00
Julian Lam
78af47362c Merge pull request #597 from draco2003/patch-4
Cleanup console.log calls
2013-12-01 17:30:07 -08:00
Dan Rowe
18a890ed51 Cleanup console.log calls
Can't see my debugging inbetween all your debugging ;)
2013-12-01 20:28:16 -05:00
Julian Lam
5f731dd1f6 Merge pull request #596 from draco2003/patch-3
Missed one lcasing
2013-12-01 17:17:05 -08:00
Julian Lam
51990142d5 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-12-01 20:13:56 -05:00
Julian Lam
b840169a8c upping markdown minver 2013-12-01 20:13:43 -05:00
Dan Rowe
94fdeb2378 Missed one lcasing
Also anyone else nervous about arbitrary hook execution here?
2013-12-01 20:11:27 -05:00
Julian Lam
68e7ee7f07 signature parsing now calls its own postTools method (with associated plugin hook 2013-12-01 20:07:30 -05:00
Julian Lam
77d5ecc82a added post.buildFooter and post.parseSignature hooks 2013-12-01 19:59:17 -05:00
Baris Soner Usakli
437379413e closes #592 2013-12-01 18:06:01 -05:00
Baris Soner Usakli
ddb7896df1 fixed post count in paginator and post bar when infinite loader kicked in 2013-12-01 17:42:26 -05:00
Baris Soner Usakli
66cdb9a067 just send err 2013-12-01 16:25:57 -05:00
Baris Soner Usakli
f5741fd48b fixed conflict 2013-12-01 16:21:50 -05:00
Baris Soner Usakli
f405dec4e9 #589 2013-12-01 16:21:19 -05:00
Julian Lam
cc242ca667 fixed #589 2013-12-01 16:19:12 -05:00
akhoury
2733198f9e oops 2013-12-01 11:05:10 -05:00
akhoury
52700fbe16 websockets.js to 'use strict'; 2013-12-01 10:56:29 -05:00
akhoury
0f53749e70 websockets.js to follow same pattern to avoid circular dependencies 2013-12-01 10:53:59 -05:00
akhoury
1aa1ddb4ec added plugin hook > action:user.create on user creation 2013-12-01 10:52:50 -05:00
akhoury
71125fd1e2 adding webstorm's .idea folder to .gitignore 2013-12-01 10:43:48 -05:00
Julian Lam
5621fb8622 switching back to version numbers for vanilla, testing prereleases 2013-11-30 21:38:35 -05:00
Julian Lam
b9f1176ec1 moved paginator progress bar into paginator block, better mobile handling, and hiding it on page load 2013-11-30 21:36:35 -05:00
Julian Lam
b3b4d3c37d Merge pull request #585 from akhoury/master
During 11k users migration, was hitting too many open files errors
2013-11-30 11:13:18 -08:00
Baris Soner Usakli
cdbca7d262 more cleanup in routes/user.js 2013-11-30 13:54:52 -05:00
Baris Soner Usakli
140f90f7f3 cleaned up requires 2013-11-30 13:35:42 -05:00
Aziz Khoury
a905c6a084 During 11k users migration, was hitting too many open files errors 2013-11-30 13:13:18 -05:00
Baris Soner Usakli
bfe081f672 added err to PostTools.isMain 2013-11-29 23:14:28 -05:00
Baris Soner Usakli
46a14715e3 fixed logout in admin site, cleaned up topics.post, anon users can post topics now if allowed 2013-11-29 23:08:42 -05:00
Baris Soner Usakli
c1da56ce45 added auto mention if u click post reply 2013-11-29 18:00:52 -05:00
Baris Usakli
ee63fae803 closes #584 2013-11-29 16:10:41 -05:00
Baris Usakli
720711756f show bottom post bar after new post, fixed the insertion of new posts 2013-11-29 14:42:58 -05:00
Baris Usakli
90a12c3253 fixed index to int 2013-11-29 14:28:15 -05:00
Baris Usakli
6a00ab3782 removed btn-large from post topic button 2013-11-29 14:22:02 -05:00
Baris Usakli
9ccfa3f18c fixed js error 2013-11-29 14:19:39 -05:00
Baris Usakli
1660d75205 stricter selector for human readable numbers 2013-11-29 14:18:06 -05:00
Baris Usakli
f6d57a241d fixed human readable view post counts 2013-11-29 14:12:19 -05:00
Julian Lam
bcfb4ca0e4 off by one error 2013-11-29 14:01:09 -05:00
Julian Lam
0159a43a20 Merge branch 'master' of github.com:designcreateplay/NodeBB
Conflicts:
	public/src/forum/topic.js
2013-11-29 13:31:07 -05:00
Julian Lam
86b019ec89 paginator progress bar 2013-11-29 13:30:01 -05:00
psychobunny
98a12cd1e1 clearing first blocks from dynamically inserted templates - made regex less greedy 2013-11-29 13:18:20 -05:00
Baris Usakli
e6452cbd4d removed unusued uploadedImages property 2013-11-29 13:14:38 -05:00
Baris Usakli
cd44ead595 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-29 13:12:59 -05:00
Baris Usakli
652fda1a6f fixed conditional in posts.js 2013-11-29 13:12:50 -05:00
psychobunny
30a7f1a816 removed .main-post from follow class (now using conditionals to show/hide) 2013-11-29 13:09:56 -05:00
Baris Usakli
6ca3d0c4af Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-29 13:09:35 -05:00
Baris Usakli
b2074c6dda fixes to infinite load and paginator 2013-11-29 13:09:26 -05:00
Julian Lam
d7c0e1c62e Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-29 12:35:58 -05:00
Julian Lam
56ef05a0bf putting category options behind a dropdown, and fixing category enable/disable 2013-11-29 12:35:36 -05:00
Baris Usakli
dd36cce329 closes #582 2013-11-29 12:02:06 -05:00
Baris Usakli
2b2799dae9 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-29 11:50:16 -05:00
Baris Usakli
293c176053 added first to follow button in topic.tpl 2013-11-29 11:50:07 -05:00
Julian Lam
3cef5fce2b Merge pull request #580 from Joopmicroop/patch-1
Allow same origin framing
2013-11-29 08:42:46 -08:00
Joopmicroop
7d0f160c4c Allow same origin framing
Allow people to frame there own server setup
2013-11-29 11:04:46 +01:00
Baris Soner Usakli
c5f9f896b2 make all admin routes only accesible to admins 2013-11-28 22:29:32 -05:00
Baris Soner Usakli
db98b3db55 removed the fields again, gitsucks 2013-11-28 18:55:10 -05:00
Baris Soner Usakli
dba47e4bef removed console.log 2013-11-28 18:45:36 -05:00
Baris Soner Usakli
2a46ead29f removed container div, removed second if first, it breaks templates 2013-11-28 18:44:02 -05:00
Julian Lam
707179edf3 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-28 17:51:02 -05:00
Julian Lam
53164e96ab removed non-functional save button from category whitelist modal 2013-11-28 17:50:40 -05:00
Baris Soner Usakli
9702e28a07 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-28 17:45:17 -05:00
Baris Soner Usakli
fa56eca962 fixed fave stars, removed the watch button from normal posts 2013-11-28 17:45:04 -05:00
Julian Lam
684839f04a Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-28 17:37:41 -05:00
Julian Lam
0188ea9a3b setting cache headers to 0 on development mode 2013-11-28 17:37:17 -05:00
psychobunny
85aa587749 merge conflicts 2013-11-28 17:16:27 -05:00
psychobunny
48e36e3c31 templates bugfix - now supports multiple conditionals of the same variable; added data-favourited button and deprecated reliance on BS3 2013-11-28 17:14:04 -05:00
Baris Usakli
0b6d018f8d oops removed by mistage 2013-11-28 16:20:05 -05:00
Baris Usakli
f2bf65252d removed the fields 2013-11-28 16:15:18 -05:00
Baris Usakli
4335f8c5c6 fixed date in upgrade 2013-11-28 15:57:00 -05:00
Baris Usakli
ae82f57c67 added upgrade script to delete removed keys from posts 2013-11-28 15:55:40 -05:00
Baris Usakli
168052bf45 added back feeds, removed duplicate post var in feed 2013-11-28 15:33:26 -05:00
Baris Usakli
a87ebb64d8 clean up of posts and some template additions 2013-11-28 15:18:19 -05:00
Julian Lam
38da65ee58 tweaks to category permission modal 2013-11-28 14:27:19 -05:00
Julian Lam
e3e1a556cd groups pruning method 2013-11-28 12:55:05 -05:00
Baris Usakli
56b618c915 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-28 11:17:01 -05:00
Baris Usakli
7198110b57 closes #573 2013-11-28 11:16:52 -05:00
psychobunny
b7aea63c53 create auth routes only after plugin system is enabled and auth.init hook is fired 2013-11-28 11:13:08 -05:00
Baris Usakli
78b65c0b12 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-28 10:58:24 -05:00
Baris Usakli
0742590c0c added pid to share links, removed unused vars 2013-11-28 10:58:14 -05:00
psychobunny
c16f04bbcf plugins - filter:admin.header.build (pre-existing hook) now allows you to add menu items to the social authentication panel as well 2013-11-28 10:42:25 -05:00
psychobunny
51b38c4c55 plugins - added filter:auth.init hook to add additional login strategies; fixed callbackURL 2013-11-28 10:30:43 -05:00
Julian Lam
79eddc9b06 Merge pull request #570 from draco2003/patch-2
Minify socket.io js
2013-11-27 20:07:36 -08:00
Baris Soner Usakli
21f63ac17f Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-27 22:02:57 -05:00
Baris Soner Usakli
fdf5227c35 closes #572 2013-11-27 22:02:50 -05:00
Julian Lam
98f03a723e upping mentions minver 2013-11-27 21:30:26 -05:00
Julian Lam
69427fa10e tweaks to make the ACP work better on tablets, some work on hidden groups 2013-11-27 20:20:08 -05:00
Julian Lam
670986f7ef Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-27 20:07:37 -05:00
Julian Lam
8b62041d28 refactored groups and categories, groups no longer explodes when
attempting to add members to a whitelist that doesn't exist, isEmpty
checks (new methods!) and such...
2013-11-27 20:07:04 -05:00
psychobunny
89c5d01efa modularized SSO, paving the way for potential plugins. cleaned up associated templates/js 2013-11-27 16:47:54 -05:00
Julian Lam
0a06f1ac7d Merge remote-tracking branch 'origin/master' into category-whitelisting 2013-11-27 16:23:48 -05:00
Julian Lam
df2e9b4b47 admin panel integration for category whitelisting 2013-11-27 16:23:30 -05:00
Dan Rowe
aed4e2792d Minify socket.io js
potential solution for issues/569
2013-11-27 15:57:29 -05:00
Baris Soner Usakli
c860df7975 more #559 2013-11-27 15:03:36 -05:00
Baris Soner Usakli
2148f6ff95 closes #559 2013-11-27 15:02:09 -05:00
Baris Soner Usakli
2d05a06e37 fixed template var, oops 2013-11-27 14:25:58 -05:00
Baris Soner Usakli
e3da005780 grouped the social buttons 2013-11-27 14:25:01 -05:00
Julian Lam
f0e8633dcc category whitelisting for posting messages, isAdmin now error-first 2013-11-27 12:47:00 -05:00
Baris Usakli
590208f0c7 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-27 12:39:15 -05:00
Baris Usakli
7d7ead3f47 fixed js error in recent.js, remove content assignment 2013-11-27 12:39:07 -05:00
Julian Lam
974629ce85 hahah, bad paste, missing a bunch of line endings 2013-11-27 11:48:18 -05:00
Julian Lam
72ef8c839f Merge remote-tracking branch 'origin/master' into category-whitelisting
Conflicts:
	src/groups.js
2013-11-27 11:34:52 -05:00
Julian Lam
5ee5c8179a category whitelist for replying to posts, lots of refactoring, too 2013-11-27 11:27:20 -05:00
psychobunny
46d6d7637e potentially fixes ubbmigrator issue https://github.com/akhoury/nodebb-plugin-ubbmigrator/issues/2 2013-11-27 11:21:16 -05:00
psychobunny
62e2aa67d7 topics - added back social sharing buttons to OP 2013-11-27 10:58:37 -05:00
Julian Lam
182659d0e1 removing extra .js suffix from required files and physically separating
nodebb libs from deps
2013-11-27 08:55:02 -05:00
Julian Lam
4855131652 category read restrictions 2013-11-27 08:49:23 -05:00
Julian Lam
4d2469b4ce tweaks to whitelist (interim commit) 2013-11-27 08:34:25 -05:00
Julian Lam
4e2326fc84 Merge remote-tracking branch 'origin' into category-whitelisting 2013-11-27 08:17:23 -05:00
Baris Soner Usakli
3a8dca6fb9 closes #560 2013-11-26 23:55:55 -05:00
Baris Soner Usakli
31635b92f3 closes #561 2013-11-26 23:19:21 -05:00
Baris Soner Usakli
a0c3de0273 display signature block only if user has signature 2013-11-26 19:22:02 -05:00
Baris Soner Usakli
32b191fa62 removed global.io 2013-11-26 19:09:32 -05:00
Baris Usakli
f616125d02 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-26 16:30:19 -05:00
Baris Usakli
e1f6e064a9 removed io from user.js, figure out why notifications are breaking when websockets.js is required from it 2013-11-26 16:30:10 -05:00
Julian Lam
633be7ff3c Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-26 15:50:37 -05:00
Julian Lam
6b3863bfbf updated category manager in admin panel 2013-11-26 15:50:33 -05:00
Baris Usakli
b66ca703b8 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-26 15:28:55 -05:00
Baris Usakli
48a7f9058f closes #558 2013-11-26 15:28:45 -05:00
psychobunny
8f80733563 fixing #552 overflows properly 2013-11-26 15:19:30 -05:00
Baris Usakli
aa1451cfbc Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-26 15:15:31 -05:00
Baris Usakli
13ef28118d closes #557 2013-11-26 15:15:23 -05:00
Julian Lam
34459e7cf1 fixing category admin panel integration 2013-11-26 15:14:12 -05:00
Baris Usakli
798e17a954 change loading text to inline 2013-11-26 14:48:55 -05:00
Julian Lam
5ad80218a2 upping cerulean minver 2013-11-26 14:45:12 -05:00
Baris Usakli
e90e54cec1 fixed icons in topic move 2013-11-26 14:37:27 -05:00
Baris Usakli
bca1fde69c updated schema date 2013-11-26 14:33:18 -05:00
Baris Usakli
d70c688b65 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-26 14:26:01 -05:00
Baris Usakli
541993c80a fontawesome 4 migration, closes #473 2013-11-26 14:25:46 -05:00
psychobunny
529c8acf6c app.js: added --install alias for --setup 2013-11-26 14:15:40 -05:00
psychobunny
e98d05b1a5 closes #556, also removes the newline that was previously inserted 2013-11-26 13:18:41 -05:00
Julian Lam
0afc7c9761 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-26 12:25:24 -05:00
Julian Lam
e5c1edd5f5 using ajaxifying class for content and footer instead of jquery fadein/out 2013-11-26 12:25:19 -05:00
Baris Usakli
a5e78aab08 closes #554 2013-11-26 11:59:54 -05:00
Baris Usakli
cec69c2be0 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-26 11:43:35 -05:00
Baris Usakli
bc8815cb94 closes #555 2013-11-26 11:43:25 -05:00
Julian Lam
efac6272bb default link tag (apple-touch-icon) added 2013-11-26 11:34:38 -05:00
Julian Lam
bdb30976b5 adding maxAge headers for statically served files (eep!) - issue #552 2013-11-26 11:17:34 -05:00
Baris Soner Usakli
1d4ae8fe4d changed the paginator icons to chevron 2013-11-25 21:38:04 -05:00
Julian Lam
abdb4c34ef tweaks to topic locking 2013-11-25 17:49:17 -05:00
Julian Lam
08d130893c fixing dropdown support in Settings.prepare 2013-11-25 17:48:55 -05:00
Julian Lam
b2fb9aa99f refactored topic locking pinning and deleting (and its inverses) so that the privilege check is done not in the method, but in the socket call 2013-11-25 17:20:44 -05:00
psychobunny
561ee9e4f1 closes #519 2013-11-25 17:00:42 -05:00
Julian Lam
3f70d45f3d Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-25 17:00:06 -05:00
Julian Lam
c07783fa2c ... 2013-11-25 17:00:01 -05:00
psychobunny
d4d0e8cd9b set unreplied flag to new topics sent via websocket 2013-11-25 16:51:52 -05:00
psychobunny
4be5ac2c23 removed mobile overlay for topics - will reimplement as a plugin 2013-11-25 16:47:06 -05:00
psychobunny
070c95d8de fixed regression from main_posts deprecation - bottom post bar restored 2013-11-25 16:38:45 -05:00
psychobunny
8d12ecb758 moved pagination into header 2013-11-25 16:37:28 -05:00
Baris Soner Usakli
81560c4698 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-25 16:29:37 -05:00
Baris Soner Usakli
390937a20b added err to getAllTopics 2013-11-25 16:29:28 -05:00
Julian Lam
2a8a38b742 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-25 16:28:14 -05:00
Julian Lam
5a5c3c8c60 added app.load action hook 2013-11-25 16:28:07 -05:00
psychobunny
905e451455 closes #549 2013-11-25 16:16:18 -05:00
psychobunny
69b8b47b15 updated cerulean dep to 0.0.9 2013-11-25 15:57:18 -05:00
Julian Lam
b16e1a0113 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-25 15:56:22 -05:00
Julian Lam
0b39968a9c fixing back button behaviour and playing nice with History API 2013-11-25 15:56:16 -05:00
psychobunny
d8b3abb611 updating cerulean dep to 0.0.8 2013-11-25 15:48:56 -05:00
psychobunny
7fb0a616a1 refactored topic.tpl and merged main_posts and sub_posts 2013-11-25 15:48:55 -05:00
psychobunny
d987e51a8b removed references to main_posts in forum/topic.js 2013-11-25 15:48:55 -05:00
psychobunny
0f7f6cd0a3 templates.js added IF !value 2013-11-25 15:48:54 -05:00
psychobunny
0e8b33aa79 templates.js added @first and @last conditionals 2013-11-25 15:48:54 -05:00
psychobunny
353b3047cd pulling meta info from OP not main_posts 2013-11-25 15:48:53 -05:00
psychobunny
377de06eeb removed main_posts from topics core, returning OP in posts array now 2013-11-25 15:48:53 -05:00
psychobunny
4013e27a8b removed main_posts from feed.j 2013-11-25 15:48:52 -05:00
psychobunny
181c6eb2e6 removed main_posts from noscript 2013-11-25 15:48:52 -05:00
Julian Lam
7955a5d53a 0.1.1 2013-11-25 15:08:49 -05:00
psychobunny
c261babf17 minify client scripts only after plugin system is activated 2013-11-25 12:35:54 -05:00
psychobunny
b90eef6d19 use icon-search instead of icon-circle-blank on /users/search 2013-11-25 01:21:26 -05:00
psychobunny
5c597ca218 expand regex for templates, allowing the syntax to be less strict re: whitespace 2013-11-25 01:14:31 -05:00
psychobunny
3dbcf8112d fixes navigation - back button 2013-11-25 00:59:21 -05:00
psychobunny
5357ad61db plugins - filter:scripts.get hook lets a plugin add client-side JS to the header and queue up for minification on production 2013-11-25 00:53:27 -05:00
Baris Soner Usakli
ff50917c29 show no replies in recent and unread 2013-11-24 22:48:58 -05:00
Baris Soner Usakli
48835d8c44 used ELSE in template 2013-11-24 22:29:36 -05:00
Baris Soner Usakli
e9c66bb35a removed console.log 2013-11-24 22:12:36 -05:00
Baris Soner Usakli
23eb7824ac closes #513 2013-11-24 22:08:37 -05:00
Baris Soner Usakli
494b9d23ac Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-24 13:58:14 -05:00
Baris Soner Usakli
64ae9ac033 cant delete or restore posts twice, post count goes up or down when posts are deleted or restored in a topic, fixed the post insertion when there is only 1 post in topic 2013-11-24 13:58:06 -05:00
Julian Lam
a72fc69997 added link to RSS for /recent, fixed RSS generation error for /recent 2013-11-24 11:15:40 -05:00
Baris Soner Usakli
a16f93cbd5 loading indicator starts off hidden 2013-11-23 18:05:19 -05:00
Baris Soner Usakli
81e5cf0cf3 fixed posts not appearing immediately 2013-11-23 17:56:03 -05:00
Baris Soner Usakli
01102d5982 added responsive class to images in users recent posts 2013-11-23 17:18:26 -05:00
Baris Soner Usakli
2174aec0e1 closes #542 and other refactors on client side 2013-11-23 17:07:31 -05:00
psychobunny
46bad118de if a thread is unreplied, don't show the OP as the last person to reply 2013-11-23 15:28:00 -05:00
psychobunny
2d7228fa40 added if / else logic to templates 2013-11-23 15:15:33 -05:00
psychobunny
a1839d90fd prevent admin group from being deleted, closes #530 2013-11-23 14:53:06 -05:00
psychobunny
0cc136c3f6 simplifying conditional logic in templates + fixed it so that it takes namespace into account 2013-11-23 14:53:05 -05:00
Julian Lam
cd1e26418d making the loading indicator less obtrusive (and smaller, to boot) 2013-11-22 21:30:34 -05:00
Baris Soner Usakli
dab4f07258 fixed indents 2013-11-22 17:39:53 -05:00
Baris Usakli
501dc56fd3 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-22 16:26:33 -05:00
Baris Usakli
253271127d infinite loader will insert posts in correct order 2013-11-22 16:26:19 -05:00
Julian Lam
f2da892b38 removed extra console log 2013-11-22 16:21:26 -05:00
Julian Lam
6dd72f480c Merge pull request #538 from draco2003/add_fav_context
add breadcrumb like context to favorites
2013-11-22 13:15:10 -08:00
Julian Lam
3caf8b4a67 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-22 15:48:14 -05:00
Julian Lam
39f2efbef8 closed #540 2013-11-22 15:48:03 -05:00
psychobunny
288341945d missing login menu in visible-sm range 2013-11-22 15:37:58 -05:00
psychobunny
d02bd72764 closes #535 2013-11-22 15:32:15 -05:00
Baris Usakli
7d3adb9275 removed unused stuff from getLatestTopics and recent.tpl 2013-11-22 15:01:00 -05:00
Baris Usakli
156950ac2f cleaned up app.createNewPosts 2013-11-22 14:51:45 -05:00
Baris Usakli
83f18c1915 closes #526 2013-11-22 14:08:02 -05:00
Baris Usakli
332730575f closes #529 2013-11-22 12:26:21 -05:00
Julian Lam
08ef67e824 closed #536 2013-11-22 11:42:42 -05:00
Dan Rowe
7e71fb218c add breadcrumb like context to favorites 2013-11-22 08:57:54 -05:00
Julian Lam
a7216caa3b closed #518 2013-11-21 22:15:04 -05:00
Julian Lam
87309601ce closed #533 2013-11-21 22:09:40 -05:00
Julian Lam
53db9db50f Merge pull request #527 from draco2003/patch-1
small wording change
2013-11-21 17:33:36 -08:00
Dan Rowe
23628668b7 small wording change 2013-11-21 20:29:23 -05:00
Baris Soner Usakli
6ac685b194 possible fix for js error 2013-11-21 20:11:06 -05:00
Baris Soner Usakli
db8c43ca97 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-21 18:40:30 -05:00
Baris Soner Usakli
bff0c8fdaf increased active users count to 16 2013-11-21 18:40:16 -05:00
Barış Soner Uşaklı
6f2b809385 Update README.md 2013-11-21 18:34:50 -05:00
Baris Soner Usakli
455479bd54 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-21 18:28:51 -05:00
Baris Soner Usakli
03b34a449d turned div into li, moved the a tags into the li elements 2013-11-21 18:28:31 -05:00
Julian Lam
08e51c8942 closed #502 2013-11-21 17:41:27 -05:00
Julian Lam
4aef5bfb72 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-21 17:36:00 -05:00
psychobunny
34c74770ce app.js minor cleanup 2013-11-21 17:02:40 -05:00
psychobunny
da8d198676 added some user friendly warnings to chat 2013-11-21 17:00:20 -05:00
Julian Lam
33868804fd fixed #517 2013-11-21 16:55:31 -05:00
psychobunny
22a3794c51 closes #525 2013-11-21 16:47:32 -05:00
psychobunny
1058d54c52 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-21 16:07:39 -05:00
psychobunny
90ce539683 fixed language file not parsing in footer 2013-11-21 16:07:32 -05:00
Baris Usakli
99c2fbd947 fixed anon count in browsing text if there are no logged in users 2013-11-21 15:56:28 -05:00
Baris Usakli
866d813218 fixed topic posting bug, if there was only 1 topic in a category the next posted topic in that category wasnt showing up until a full page reload 2013-11-21 15:33:41 -05:00
Baris Usakli
f1df8c2479 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-21 15:20:12 -05:00
Baris Usakli
6f1523c279 fixed bottom reply box for small devices 2013-11-21 15:20:03 -05:00
Julian Lam
163cdaf70c Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-21 15:05:56 -05:00
Julian Lam
a9ce8393e4 added footer.build and page.load hooks 2013-11-21 15:05:45 -05:00
Baris Usakli
f04e30c4d4 more template changes to topic 2013-11-21 14:55:38 -05:00
Baris Usakli
9d0f8b4543 template changes 2013-11-21 14:33:55 -05:00
Baris Usakli
d631a4b2e5 topic.tpl changes, moved users to the bottom of main post, added reply thread tools buttons under main post, added posts and view count 2013-11-21 13:53:19 -05:00
Julian Lam
2cf55dcf9f added action:page.load hook 2013-11-21 12:28:10 -05:00
Baris Soner Usakli
9fbb139e67 fix post delete state after more posts are loaded 2013-11-20 12:22:59 -05:00
Baris Usakli
11e3b0da7d added spacing between share and edit buttons 2013-11-19 15:03:58 -05:00
Baris Usakli
0b922d3f60 possible fix for #516 2013-11-19 13:04:12 -05:00
Baris Usakli
7e4faa3270 closes #514 2013-11-19 12:38:13 -05:00
Julian Lam
635fba1e45 upping cerlean minver 2013-11-18 20:25:43 -05:00
Baris Usakli
7c950cc350 require cleanup in user.js, removed user.latest not used anymore 2013-11-18 16:22:43 -05:00
Baris Usakli
cc0fe66e3e minor tweak to notif filter :) 2013-11-18 15:56:12 -05:00
Baris Usakli
b2d6ce59cf Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-18 15:44:46 -05:00
Baris Usakli
586a181e0a closes #507 2013-11-18 15:44:32 -05:00
Julian Lam
33150943df Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-18 15:09:56 -05:00
Julian Lam
28dab60232 resolving notifs issue, I hope 2013-11-18 15:09:34 -05:00
Barış Soner Uşaklı
71ef76b108 Merge pull request #511 from damianb/patch-3
cleanup webserver.js requires
2013-11-18 08:44:23 -08:00
Julian Lam
64008ef5d8 Merge pull request #509 from damianb/patch-2
/bin/bash to /bin/sh
2013-11-18 08:36:37 -08:00
Barış Soner Uşaklı
1859154370 Merge pull request #506 from deniswolf/cleanup_specs
Cleanup specs in test/topic.js
2013-11-18 08:20:51 -08:00
Julian Lam
fa4067e885 Merge branch 'master' of github.com:designcreateplay/NodeBB 2013-11-18 08:19:18 -05:00
Julian Lam
c8c355b319 added komodoproject file extensions to gitignore 2013-11-18 08:19:04 -05:00
Damian Bushong
51355a53d9 cleanup webserver.js requires
the .js in a require is implicit and unnecessary;
sorted the requires out so that builtins are first, then npm deps, then locally provided libs.
minor changes to some strings, just using single-quotes to match the style through the rest of the file.
2013-11-18 02:39:08 -06:00
Damian Bushong
1f3f672d3f /bin/bash to /bin/sh
No bashisms present? Don't be explicit about needing bash, then.
2013-11-18 02:27:48 -06:00
Denis Wolf
7c3fa30c13 tests: topic.js: fixed description to mirror code, refactored asserts since mocha's 'done' can process errors in callback 2013-11-18 00:00:22 +02:00
Denis Wolf
cbbb7a7c8e tests: topic.js: extract mock data init in getters 2013-11-17 23:50:19 +02:00
Denis Wolf
6893bd8b04 tests: topic.js: extract mock data init in .post 2013-11-17 23:41:38 +02:00
Denis Wolf
22eabf6620 tests: topic.js: naming flow fix for .post 2013-11-17 23:35:18 +02:00
Baris Soner Usakli
a827888ee3 closes #503 2013-11-17 12:23:19 -05:00
Baris Usakli
54d94f5988 added topic tests 2013-11-15 16:16:50 -05:00
Baris Usakli
7c1b6d6ad2 lots of refactor for error handling 2013-11-15 14:57:50 -05:00
Baris Usakli
8c4f776122 Merge branch 'master' of https://github.com/designcreateplay/NodeBB 2013-11-15 13:39:14 -05:00
Baris Usakli
84fa704b25 refactor abit adding error checking to missing parts 2013-11-15 13:39:09 -05:00
Julian Lam
535379d9d7 added password confirmation to automated setup 2013-11-14 18:45:17 -05:00
Julian Lam
d2927e2be2 Merge pull request #500 from jgable/passwordConfirm
Add admin password confirmation on setup
2013-11-14 11:27:23 -08:00
Jacob Gable
bd04b2f921 Add admin password confirmation on setup
Closes #419

- Introduce a password:confirm question
- Isolate password questions to they can be re-asked
- Verify matching password, re-ask if not
2013-11-14 12:52:00 -06:00
Julian Lam
18009ebb39 interim commit 2013-11-13 19:54:46 -05:00
210 changed files with 11526 additions and 7905 deletions

7
.gitignore vendored
View File

@@ -8,7 +8,14 @@ public/css/*.css
*.sublime-project
*.sublime-workspace
.project
.idea
*.swp
Vagrantfile
.vagrant
provision.sh
*.komodoproject
feeds/recent.rss
# winston?
error.log

View File

@@ -10,7 +10,7 @@
![NodeBB Main Category Listing](http://i.imgur.com/zffCFoh.png)
![NodeBB Topic Page](http://i.imgur.com/tcHW08M.png)
![NodeBB Topic Page](http://i.imgur.com/JihdcUa.png)
## How can I follow along/contribute?
@@ -23,7 +23,7 @@
NodeBB requires the following software to be installed:
* A version of Node.js at least 0.8 or greater
* Redis, version 2.6 or greater.
* Redis, version 2.6 or greater or MongoDB, version 2.4 or greater
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
## Installation
@@ -32,6 +32,8 @@ First, we install our base software stack:
# apt-get install git nodejs redis-server npm build-essential imagemagick
If you want to use MongoDB instead of Redis install it from http://www.mongodb.org/downloads and remove 'redis-server' from the above command. [MongoDB-Setup](https://github.com/designcreateplay/NodeBB/wiki/MongoDB-Setup)
**If your package manager only installed a version of Node.js that is less than 0.8 (e.g. Ubuntu 12.10, 13.04):**
# add-apt-repository ppa:chris-lea/node.js

53
app.js
View File

@@ -25,6 +25,7 @@
var fs = require('fs'),
async = require('async'),
semver = require('semver'),
winston = require('winston'),
pkg = require('./package.json'),
path = require('path'),
@@ -48,6 +49,12 @@
winston.error(err.stack);
};
require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
if(err || !stdout) {
winston.warn('Couldn\'t find convert. Did you install imagemagick?');
}
});
// Log GNU copyright info along with server info
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
@@ -55,15 +62,16 @@
winston.info('');
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('install') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
// Load server-side configs
nconf.file({
file: __dirname + '/config.json'
});
meta = require('./src/meta.js');
meta = require('./src/meta');
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
nconf.set('upload_url', nconf.get('url') + 'uploads/');
nconf.set('base_dir', __dirname);
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
winston.info('NodeBB instance bound to: ' + ((nconf.get('bind_address') === "0.0.0.0" || !nconf.get('bind_address')) ? 'Any address (0.0.0.0)' : nconf.get('bind_address')));
@@ -72,29 +80,27 @@
winston.info('Base Configuration OK.');
}
if (semver.gt(pkg.dependencies['nodebb-theme-cerulean'], require('./node_modules/nodebb-theme-cerulean/package.json').version)) {
winston.error('nodebb-theme-cerulean is out of date - please run npm install.')
}
require('./src/database').init(function(err) {
meta.configs.init(function () {
// Initial setup for Redis & Reds
var reds = require('reds'),
RDB = require('./src/redis.js');
reds.createClient = function () {
return reds.client || (reds.client = RDB);
};
var templates = require('./public/src/templates'),
translator = require('./public/src/translator'),
webserver = require('./src/webserver'),
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket'], 'browser client minification': true}),
websockets = require('./src/websockets'),
plugins = require('./src/plugins'),
notifications = require('./src/notifications'),
upgrade = require('./src/upgrade');
var templates = require('./public/src/templates.js'),
translator = require('./public/src/translator.js'),
webserver = require('./src/webserver.js'),
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
websockets = require('./src/websockets.js'),
posts = require('./src/posts.js'),
plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself
Notifications = require('./src/notifications'),
Upgrade = require('./src/upgrade');
Upgrade.check(function(schema_ok) {
upgrade.check(function(schema_ok) {
if (schema_ok || nconf.get('check-schema') === false) {
websockets.init(SocketIO);
plugins.init();
global.templates = {};
global.translator = translator;
@@ -112,9 +118,11 @@
], customTemplates);
plugins.ready(function() {
templates.ready(webserver.init);
});
Notifications.init();
notifications.init();
} else {
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
winston.warn(' node app --upgrade');
@@ -124,7 +132,8 @@
}
});
});
} else if (nconf.get('setup') || !fs.existsSync(__dirname + '/config.json')) {
});
} else if (nconf.get('setup') || nconf.get('install') || !fs.existsSync(__dirname + '/config.json')) {
// New install, ask setup questions
if (nconf.get('setup')) {
winston.info('NodeBB Setup Triggered via Command Line');
@@ -156,11 +165,13 @@
nconf.file({
file: __dirname + '/config.json'
});
require('./src/database').init(function(err) {
meta = require('./src/meta.js');
meta.configs.init(function () {
require('./src/upgrade').upgrade();
});
});
} else/* if (nconf.get('help') */{
winston.info('Usage: node app [options] [arguments]');
winston.info(' [NODE_ENV=development | NODE_ENV=production] node app [--start] [arguments]');

View File

@@ -2,85 +2,97 @@
{
"name": "Announcements",
"description": "Announcements regarding our community",
"blockclass": "category-blue",
"icon" : "icon-bullhorn",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-bullhorn",
"order": 1
},
{
"name": "General Discussion",
"description": "A place to talk about whateeeever you want",
"blockclass": "category-blue",
"icon" : "icon-comment",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-comment",
"order": 2
},
{
"name": "NodeBB Development",
"description": "NodeBB development news and announcements",
"blockclass": "category-blue",
"icon" : "icon-github",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-github",
"order": 3
},
{
"name": "Blogs",
"description": "Blog posts from individual members",
"blockclass": "category-blue",
"icon" : "icon-pencil",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-pencil",
"order": 4
},
{
"name": "Feature Requests",
"description": "Got a feature request you'd like to see? Give us a shout here.",
"blockclass": "category-purple",
"icon" : "icon-lightbulb",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-lightbulb-o",
"order": 5
},
{
"name": "Bug Reports",
"description": "Having trouble with NodeBB? Let us know...",
"blockclass": "category-purple",
"icon" : "icon-cogs",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-cogs",
"order": 6
},
{
"name": "NodeBB Plugins",
"description": "Enhance your NodeBB with plugins!",
"blockclass": "category-purple",
"icon" : "icon-plus-sign",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-plus-square",
"order": 7
},
{
"name": "NodeBB Link Exchange",
"description": "Link exchange",
"blockclass": "category-purple",
"icon" : "icon-exchange",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-exchange",
"order": 8
},
{
"name": "News",
"description": "News from around the world",
"blockclass": "category-darkblue",
"icon" : "icon-globe",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-globe",
"order": 9
},
{
"name": "Movies",
"description": "Discuss the latest movies here",
"blockclass": "category-darkblue",
"icon" : "icon-film",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-film",
"order": 10
},
{
"name": "Games",
"description": "Discuss the latest games here",
"blockclass": "category-darkblue",
"icon" : "icon-screenshot",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-crosshairs",
"order": 11
},
{
"name": "Random",
"description": "Anything and (almost) everything welcome!",
"blockclass": "category-darkblue",
"icon" : "icon-beer",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-beer",
"order": 12
}
]

81
mocks/databasemock.js Normal file
View File

@@ -0,0 +1,81 @@
/**
* Database Mock - wrapper for database.js, makes system use separate test db, instead of production
* ATTENTION: testing db is flushed before every use!
*/
(function(module) {
'use strict';
var utils = require('./../public/src/utils.js'),
path = require('path'),
nconf = require('nconf'),
winston = require('winston'),
errorText;
nconf.file({ file: path.join(__dirname, '../config.json') });
var dbType = nconf.get('database'),
testDbConfig = nconf.get('test_database'),
productionDbConfig = nconf.get(dbType);
if(!testDbConfig){
errorText = 'test_database is not defined';
winston.info(
"\n===========================================================\n"+
"Please, add parameters for test database in config.json\n"+
"For example (redis):\n"+
'"test_database": {' + '\n' +
' "host": "127.0.0.1",' + '\n' +
' "port": "6379",' + '\n' +
' "password": "",' + '\n' +
' "database": "1"' + '\n' +
'}\n'+
" or (mongo):\n" +
'"test_database": {' + '\n' +
' "host": "127.0.0.1",' + '\n' +
' "port": "27017",' + '\n' +
' "password": "",' + '\n' +
' "database": "1"' + '\n' +
'}\n'+
"==========================================================="
);
winston.error(errorText);
throw new Error(errorText);
}
if( testDbConfig.database === productionDbConfig.database &&
testDbConfig.host === productionDbConfig.host &&
testDbConfig.port === productionDbConfig.port
){
errorText = 'test_database has the same config as production db';
winston.error(errorText);
throw new Error(errorText);
}
nconf.set(dbType, testDbConfig);
db = require('../src/database');
before(function(done) {
db.init(function(err) {
//Clean up
db.flushdb(function(err) {
if(err){
winston.error(err);
throw new Error(err);
} else {
winston.info('test_database flushed');
done();
}
//TODO: data seeding, if needed at all
});
});
});
module.exports = db;
}(module));

View File

@@ -1,69 +0,0 @@
/**
* Redis Mock - wrapper for redis.js, makes system use separate test db, instead of production
* ATTENTION: testing db is flushed before every use!
*/
(function(module) {
'use strict';
var RedisDB,
redis = require('redis'),
utils = require('./../public/src/utils.js'),
path = require('path'),
nconf = require('nconf'),
winston = require('winston'),
errorText;
nconf.file({ file: path.join(__dirname, '../config.json') });
var testDbConfig = nconf.get('redis_test'),
productionDbConfig = nconf.get('redis');
if(!testDbConfig){
errorText = 'redis_test database is not defined';
winston.info(
"\n===========================================================\n"+
"Please, add parameters for test database in config.json\n"+
"For example:\n"+
'"redis_test": {' + '\n' +
' "host": "127.0.0.1",' + '\n' +
' "port": "6379",' + '\n' +
' "password": "",' + '\n' +
' "database": "1"' + '\n' +
'}\n'+
"==========================================================="
);
winston.error(errorText);
throw new Error(errorText);
}
if( testDbConfig.database === productionDbConfig.database &&
testDbConfig.host === productionDbConfig.host &&
testDbConfig.port === productionDbConfig.port
){
errorText = 'redis_test database has the same config as production db';
winston.error(errorText);
throw new Error(errorText);
}
nconf.set('redis',testDbConfig);
RedisDB = require('../src/redis.js');
//Clean up
RedisDB.send_command('flushdb', [], function(error){
if(error){
winston.error(error);
throw new Error(error);
} else {
winston.info('redis_test db flushed');
}
});
//TODO: data seeding, if needed at all
module.exports = RedisDB;
}(module));

58
nodebb
View File

@@ -1,6 +1,54 @@
#!/bin/bash
clear
echo "Launching NodeBB in \"development\" mode."
echo "To run the production build of NodeBB, please use \"forever\"."
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1
# $0 script path
# $1 action
# $2 subaction
case "$1" in
start)
node app
;;
dev)
echo "Launching NodeBB in \"development\" mode."
echo "To run the production build of NodeBB, please use \"forever\"."
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
NODE_ENV=development node app
;;
watch)
echo "Launching NodeBB in \"development\" mode."
echo "To run the production build of NodeBB, please use \"forever\"."
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- app $1
;;
language)
case "$2" in
check)
node app --language="check"
;;
*)
echo "Language Settings"
echo $"Usage: $0 language {check}"
echo ''
column -s ' ' -t <<< '
check Compare language files against the /en directory
'
;;
esac
;;
*)
echo "Welcome to NodeBB"
echo $"Usage: $0 {start|dev|watch|language}"
echo ''
column -s ' ' -t <<< '
start Start NodeBB in production mode
dev Start NodeBB in development mode
watch Start NodeBB in development mode and watch for changes
language Language settings
'
exit 1
esac

View File

@@ -2,7 +2,7 @@
"name": "nodebb",
"license": "GPLv3 or later",
"description": "NodeBB Forum",
"version": "0.1.0",
"version": "0.2.0",
"homepage": "http://www.nodebb.org",
"repository": {
"type": "git",
@@ -14,12 +14,10 @@
},
"dependencies": {
"socket.io": "~0.9.16",
"redis": "0.8.3",
"express": "3.2.0",
"express-namespace": "~0.1.1",
"emailjs": "0.3.4",
"cookie": "0.0.6",
"connect-redis": "1.4.5",
"passport": "0.1.17",
"passport-local": "0.1.6",
"passport-twitter": "0.1.5",
@@ -28,7 +26,7 @@
"less-middleware": "0.1.12",
"marked": "0.2.8",
"bcrypt": "0.7.5",
"async": "0.2.8",
"async": "~0.2.8",
"node-imagemagick": "0.1.8",
"gravatar": "1.0.6",
"nconf": "~0.6.7",
@@ -40,13 +38,18 @@
"prompt": "~0.2.11",
"uglify-js": "~2.4.0",
"validator": "~1.5.1",
"nodebb-plugin-mentions": "~0.1.14",
"nodebb-plugin-markdown": "~0.1.8",
"nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla",
"nodebb-theme-cerulean": "0.0.6",
"cron": "~1.0.1"
"nodebb-plugin-mentions": "~0.1.16",
"nodebb-plugin-markdown": "~0.2.1",
"nodebb-theme-vanilla": "~0.0.10",
"nodebb-theme-cerulean": "0.0.10",
"cron": "~1.0.1",
"semver": "~2.2.1"
},
"optionalDependencies": {
"redis": "0.8.3",
"mongodb": "~1.3.19",
"connect-redis": "1.4.5",
"connect-mongo": "0.4.0",
"hiredis": "~0.1.15"
},
"devDependencies": {

View File

@@ -0,0 +1,14 @@
{
"new_topic_button": "Neues Thema",
"no_topics": "<strong>Es gibt noch keine Threads in dieser Kategorie.</strong><br />Warum beginnst du nicht den ersten?",
"sidebar.recent_replies": "Neuste Antworten",
"sidebar.active_participants": "Aktive Teilnehmer",
"sidebar.moderators": "Moderatoren",
"posts": "Posts",
"views": "Aufrufe",
"posted": "Geposted",
"browsing": "Sieht zu",
"no_replies": "Niemand hat geantwortet",
"replied": "geantwortet",
"last_edited_by": "zuletzt editiert durch"
}

View File

@@ -0,0 +1,10 @@
{
"chat.chatting_with": "Chatten mit <span id='chat-with-name'></span>",
"chat.placeholder": "schreibe hier etwas, und drücke Enter zum absenden",
"chat.send": "Senden",
"stats.online": "Online",
"stats.users": "Benutzer",
"stats.topics": "Themen",
"stats.posts": "Beiträge",
"success": "erfolg"
}

View File

@@ -0,0 +1,31 @@
{
"home": "Übersicht",
"search": "Suche",
"buttons.close": "Schließen",
"403.title": "Zugriff Verweigert",
"403.message": "Du bist nicht dazu berechtigt, diese Seite aufzurufen. <a href='/login'>Logge dich ein</a> und versuche es erneut.",
"404.title": " Nicht Gefunden",
"404.message": "Die abgefragte Seite wurde nicht gefunden. <a href='/''>Zurück zur Übersicht</a>.",
"500.title": "Internal error.",
"500.message": "Ooops! Looks like something went wrong!",
"register": "Registrierung",
"login": "Login",
"logout": "Logout",
"logout.title": "Du bist ausgeloggt.",
"logout.message": "Du hast dich soeben erfolgreich aus dem Forum ausgeloggt.",
"save_changes": "Speichere Änderungen",
"close": "Schließen",
"header.admin": "Admin",
"header.recent": "Aktuell",
"header.unread": "Ungelesen",
"header.users": "Benutzer",
"header.search": "Suche",
"header.profile": "Profil",
"notifications.loading": "Benachrichtigungen laden",
"chats.loading": "Nachrichten werden geladen"
}

View File

@@ -0,0 +1,10 @@
{
"login": "Einloggen",
"username": "Benutzername",
"password": "Passwort",
"remember_me": "Eingeloggt bleiben?",
"forgot_password": "Passwort vergessen?",
"alternative_logins": "Login Alternativen",
"failed_login_attempt": " Anmeldeversuch fehlgeschlagen, versuche es erneut.",
"login_successful": "Du hast dich erfolgreich eingeloggt!"
}

View File

@@ -0,0 +1,9 @@
{
"title": "Benachrichtigungen",
"back_to_home": "Zurück zur Startseite",
"mark_all_as_read": "Alles als gelesen markieren",
"outgoing_link": "Externer Link",
"outgoing_link_message": "Du verlässt nun",
"continue_to": "Gehe weiter zu",
"return_to": "Kehre zurück zu"
}

View File

@@ -0,0 +1,5 @@
{
"day": "Tag",
"week": "Woche",
"month": "Monat"
}

View File

@@ -0,0 +1,16 @@
{
"register": "Registrieren",
"help.email": "Deine E-Mail Adresse ist standardmäßig nicht öffentlich sichtbar.",
"help.username_restrictions": "Einen einmaligen Benutzernamen. 3-16 Zeichen. Andere Benutzer können dich mit @<span id='yourUsername'>Benutzername</span> anschreiben.",
"help.minimum_password_length": "Dein Passwort muss mindestens sechs Zeichen lang sein.",
"email_address": "E-Mail",
"email_address_placeholder": "E-Mail Adresse hier eingeben",
"username": "Benutzername",
"username_placeholder": "Benutzernamen eingeben",
"password": "Passwort",
"password_placeholder": "Passwort eingeben",
"confirm_password": "Passwort bestätigen",
"confirm_password_placeholder": "Passwort zur Bestätigung erneut eingeben",
"register_now_button": "Jetzt registrieren",
"alternative_registration": "Alternative Registrierung"
}

View File

@@ -0,0 +1,13 @@
{
"reset_password": "Passwort zurücksetzen",
"update_password": "Ändere Passwort",
"password_change": "Passwort wurde geändert",
"password_reset_successful": "<p>Das Passwort wurde erfolgreich zurückgesetzt. <a href=\"/login\">Log dich neu ein</a>.",
"wrong_reset_code.title": "Der Reset-Code ist falsch.",
"wrong_reset_code.message": "Der empfangene Reset-Code war falsch. Bitte versuche es erneut oder <a href=\"/reset\">fordere einen neuen Code an</a>.",
"new_password": "Neues Passwort",
"repeat_password": "Wiederhole das Passwort",
"enter_email": "Bitte gib Deine <strong>E-Mail Adresse</strong> ein und wir senden Dir eine Anleitung, wie Du Dein Passwort zurücksetzen kannst.",
"password_reset_sent": "Passwortzrücksetzung beantragt.",
"invalid_email": "Ungültige E-Mail / Adresse existiert nicht!"
}

View File

@@ -0,0 +1,43 @@
{
"topic": "Thema",
"topics": "Themen",
"no_topics_found": "Keine passende Themen gefunden.",
"profile": "Profil",
"posted_by": "geschrieben von",
"chat": "Chat",
"notify_me": "Werde bei neues Antworten auf dieses Thema benachrichtigt.",
"quote": "zitieren",
"reply": "antworten",
"edit": "bearbeiten",
"delete": "löschen",
"banned": "gesperrt",
"link": "Link",
"thread_tools.title": "Thread Tools",
"thread_tools.pin": "Thread pinnen",
"thread_tools.unpin": "Thread nicht mehr pinnen",
"thread_tools.lock": "Thread sperren",
"thread_tools.move": "Thread verschieben",
"thread_tools.delete": "Thread löschen",
"load_categories": "Kategorien laden",
"disabled_categories_note": "Deaktivierte Kategorien sind ausgegraut.",
"confirm_move": "verschieben",
"favourite": "Favorit",
"favourites": "Favoriten",
"favourites.not_logged_in.title": "Nicht eingeloggt!",
"favourites.not_logged_in.message": "Bitte logge dich ein, um diesen Beitrag favorisieren zu können.",
"favourites.has_no_favourites":"Du hast noch keine Favoriten.",
"posted_by": "Geposted von",
"loading": "Lade",
"more_posts": "Mehr Posts",
"move_topic": "Thema verschieben",
"topic_will_be_moved_to": "Dieses Thema wird verschoben nach",
"reputation": "Reputation",
"posts": "Posts"
}

View File

@@ -0,0 +1,5 @@
{
"no_unread_topics": "Es gibt keine ungelesenen Themen.",
"mark_all_read": "alle als gelesen markieren",
"load_more": "mehr laden"
}

View File

@@ -0,0 +1,38 @@
{
"banned": "Gebannt",
"offline": "offline",
"email": "E-Mail",
"fullname": "Kompletter Name",
"website": "Homepage",
"location": "Wohnort",
"age": "Alter",
"joined": "Beigetreten",
"profile_views": "Profilaufrufe",
"reputation": "Reputation",
"posts": "Posts",
"followers": "Follower",
"following": "Folgt",
"signature": "Signatur",
"gravatar": "Gravatar",
"birthday": "Geburtstag",
"change_picture": "Ändere Profilbild",
"edit": "Ändern",
"uploaded_picture": "Hochgeladene Bilder",
"upload_new_picture": "Neues Bild hochladen",
"change_password": "Ändere Passwort",
"confirm_password": "Passwort wiederholen",
"password": "Passwort",
"upload_picture": "Bild hochladen",
"upload_a_picture": "Ein Bild hochladen",
"image_spec": "Du solltest nur Dateien die PNG, JPG, oder GIF kleiner als 256kb hochladen.",
"settings": "Einstellungen",
"show_email": "Zeige meine E-Mail Adresse an.",
"has_no_follower": "Dieser User hat noch keine Follower.",
"follows_no_one": "Dieser User folgt noch niemanden."
}

View File

@@ -0,0 +1,9 @@
{
"latest_users": "neuste Benutzer",
"top_posters": "meiste Beiträge",
"most_reputation": "höhstes Ansehen",
"online": "Online",
"search": "Suchen",
"enter_username": "Benutzer durchsuchen",
"load_more": "mehr laden"
}

View File

@@ -3,5 +3,12 @@
"no_topics": "<strong>There are no topics in this category.</strong><br />Why don't you try posting one?",
"sidebar.recent_replies": "Recent Replies",
"sidebar.active_participants": "Active Participants",
"sidebar.moderators": "Moderators"
"sidebar.moderators": "Moderators",
"posts": "posts",
"views": "views",
"posted": "posted",
"browsing": "browsing",
"no_replies": "No one has replied",
"replied": "replied",
"last_edited_by": "last edited by"
}

View File

@@ -1,9 +1,10 @@
{
"chat.chatting_with": "Chat with <span id='chat-with-name'></span>",
"chat.chatting_with": "Chat with <span id=\"chat-with-name\"></span>",
"chat.placeholder": "type chat message here, press enter to send",
"chat.send": "Send",
"stats.online": "Online",
"stats.users": "Users",
"stats.topics": "Topics",
"stats.posts": "Posts"
"stats.posts": "Posts",
"success": "success"
}

View File

@@ -5,14 +5,27 @@
"403.title": "Access Denied",
"403.message": "You seem to have stumbled upon a page that you do not have access to. Perhaps you should <a href='/login'>try logging in</a>?",
"404.title": "Not Found",
"404.message": "You seem to have stumbled upon a page that does not exist. Return to the <a href='/''>home page</a>.",
"404.message": "You seem to have stumbled upon a page that does not exist. Return to the <a href='/'>home page</a>.",
"500.title": "Internal error.",
"500.message": "Oops! Looks like something went wrong!",
"register": "Register",
"login": "Login",
"logout": "Logout",
"logout.title": "You are now logged out.",
"logout.message": "You have successfully logged out of NodeBB",
"save_changes": "Save Changes",
"close": "Close",
"header.admin": "Admin",
"header.recent": "Recent",
"header.unread": "Unread",
"header.users": "Users",
"header.search": "Search",
"notifications.loading": "Loading Notifications"
"header.profile": "Profile",
"notifications.loading": "Loading Notifications",
"chats.loading": "Loading Chats"
}

View File

@@ -1,3 +1,9 @@
{
"title": "Notifications"
"title": "Notifications",
"back_to_home": "back to NodeBB",
"mark_all_as_read": "Mark All as Read",
"outgoing_link": "Outgoing Link",
"outgoing_link_message": "You are now leaving",
"continue_to": "Continue to",
"return_to": "Return to "
}

View File

@@ -0,0 +1,13 @@
{
"reset_password": "Reset Password",
"update_password": "Update Password",
"password_changed.title": "Password Changed",
"password_changed.message": "<p>Password successfully reset, please <a href=\"/login\">log in again</a>.",
"wrong_reset_code.title": "Incorrect Reset Code",
"wrong_reset_code.message": "The reset code received was incorrect. Please try again, or <a href=\"/reset\">request a new reset code</a>.",
"new_password": "New Password",
"repeat_password": "Confirm Password",
"enter_email": "Please enter your <strong>email address</strong> and we will send you an email with instructions on how to reset your account.",
"password_reset_sent": "Password Reset Sent",
"invalid_email": "Invalid Email / Email does not exist!"
}

View File

@@ -1,23 +1,42 @@
{
"topic": "Topic",
"topics": "Topics",
"no_topics_found": "No topics found!",
"profile": "Profile",
"posted_by": "Posted by",
"chat": "Chat",
"notify_me": "Be notified of new replies in this topic",
"favourite": "Favourite",
"quote": "Quote",
"reply": "Reply",
"edit": "Edit",
"delete": "Delete",
"banned": "banned",
"link": "Link",
"thread_tools.title": "Thread Tools",
"thread_tools.pin": "Pin Thread",
"thread_tools.lock": "Lock Thread",
"thread_tools.move": "Move Thread",
"thread_tools.delete": "Delete Thread",
"load_categories": "Loading Categories",
"disabled_categories_note": "Disabled Categories are greyed out",
"confirm_move": "Move",
"favourite": "Favourite",
"favourites": "Favorites",
"favourites.not_logged_in.title": "Not Logged In",
"favourites.not_logged_in.message": "Please log in in order to favourite this post"
"favourites.not_logged_in.message": "Please log in in order to favourite this post",
"favourites.has_no_favourites": "You don't have any favourites, favourite some posts to see them here!",
"posted_by": "posted by",
"loading": "Loading",
"more_posts": "More Posts",
"move_topic": "Move Topic",
"topic_will_be_moved_to": "This topic will be moved to the category",
"reputation": "Reputation",
"posts": "Posts"
}

View File

@@ -0,0 +1,39 @@
{
"banned": "Banned",
"offline": "Offline",
"email": "Email",
"fullname": "Full Name",
"website": "Website",
"location": "Location",
"age": "Age",
"joined": "Joined",
"profile_views": "Profile views",
"reputation": "Reputation",
"posts": "Posts",
"followers": "Followers",
"following": "Following",
"signature": "Signature",
"gravatar": "Gravatar",
"birthday": "Birthday",
"change_picture": "Change Picture",
"edit": "Edit",
"uploaded_picture": "Uploaded Picture",
"upload_new_picture": "Upload New Picture",
"change_password": "Change Password",
"confirm_password": "Confirm Password",
"password": "Password",
"upload_picture": "Upload picture",
"upload_a_picture": "Upload a picture",
"image_spec": "You may only upload PNG, JPG, or GIF files under 256kb.",
"settings": "settings",
"show_email": "Show My Email",
"has_no_follower": "This user doesn't have any followers :(",
"follows_no_one": "This user isn't following anyone :(",
"email_hidden": "Email Hidden",
"hidden": "hidden"
}

View File

@@ -0,0 +1,14 @@
{
"new_topic_button": "Nuevo Tema",
"no_topics": "<strong>No hay temas en esta categoría.</strong><br />Por que no te animas y publicas uno?",
"sidebar.recent_replies": "Respuestas recientes",
"sidebar.active_participants": "Miembros más activos",
"sidebar.moderators": "Moderadores",
"posts": "respuestas",
"views": "visitas",
"posted": "posted",
"browsing": "viendo ahora",
"no_replies": "Nadie ha respondido aún",
"replied": "respondio",
"last_edited_by": "ultima edición por"
}

View File

@@ -0,0 +1,10 @@
{
"chat.chatting_with": "Chatear con <span id='chat-with-name'></span>",
"chat.placeholder": "ingresa tu mensaje aqui, y presiona enter para enviar",
"chat.send": "Enviar",
"stats.online": "Online",
"stats.users": "Usuarios",
"stats.topics": "Temas",
"stats.posts": "Posts",
"success": "exito!"
}

View File

@@ -0,0 +1,31 @@
{
"home": "Inicio",
"search": "Buscar",
"buttons.close": "Cerrar",
"403.title": "Acceso denegado",
"403.message": "Al parecer no tienes premisos necesarios para estar en este lugar. Tal vez puedes <a href='/login'>intentar conectarte</a>?",
"404.title": "Ups... 404, no se encontra che!",
"404.message": "Al parecer lo que estas buscando no existe. Te recomendamos que vuelvas al <a href='/''>inicio</a>.",
"500.title": "Error Interno.",
"500.message": "Ooops! Algo salio mal!, No te alarmes. Nuestros simios hiperinteligentes lo solucionarán",
"register": "Registrarse",
"login": "Conectarse",
"logout": "Salir",
"logout.title": "Te has desconectado.",
"logout.message": "Haz sido desconectado correctamente",
"save_changes": "Guardar Cambios",
"close": "Cerrar",
"header.admin": "Admin",
"header.recent": "Recientes",
"header.unread": "No Leeidos",
"header.users": "Miembros",
"header.search": "Buscar",
"header.profile": "Perfil",
"notifications.loading": "Cargando Notificaciones",
"chats.loading": "Cargando Chats"
}

View File

@@ -0,0 +1,10 @@
{
"login": "Conectarse",
"username": "Usuario",
"password": "Contraseña",
"remember_me": "Recordarme?",
"forgot_password": "Olvidaste tu contraseña?",
"alternative_logins": "Conexiones Alternativas",
"failed_login_attempt": "Error al loguearte, intenta de nuevo.",
"login_successful": "Te has conectado con exito!"
}

View File

@@ -0,0 +1,9 @@
{
"title": "Notificaciones",
"back_to_home": "volver al Inicio",
"mark_all_as_read": "Marcar todo como leeido",
"outgoing_link": "Link Externo",
"outgoing_link_message": "Estas saliendo del sitio",
"continue_to": "Continuar",
"return_to": "Volver a "
}

View File

@@ -0,0 +1,5 @@
{
"day": "Día",
"week": "Semana",
"month": "Mes"
}

View File

@@ -0,0 +1,16 @@
{
"register": "Registrase",
"help.email": "Por defecto, tu email será oculto al publico.",
"help.username_restrictions": "El nombre de usuario debe tener entre %1 y %2 caracteres. Los miembros pueden responderte escribiendo @<span id='yourUsername'>usuario</span>.",
"help.minimum_password_length": "Tu contraseña debe tener al menos %1 caracteres.",
"email_address": "Email",
"email_address_placeholder": "Escribe tu email",
"username": "Usuario",
"username_placeholder": "Escribe tu usuario",
"password": "Contraseña",
"password_placeholder": "Escribe tu Contraseña",
"confirm_password": "Confirmar Contraseña",
"confirm_password_placeholder": "Confirmar Contraseña",
"register_now_button": "Registrarme ahora",
"alternative_registration": "Otros metodos interesantes para registrarse"
}

View File

@@ -0,0 +1,13 @@
{
"reset_password": "Resetear Contraseña",
"update_password": "Actualizar contraseña",
"password_changed.title": "Contraseña editada",
"password_changed.message": "<p>La contraseña fue modificada con exito, por favor <a href=\"/login\">conectate de nuevo</a>.",
"wrong_reset_code.title": "Código de Reseteo Incorrecto",
"wrong_reset_code.message": "El código de reseteo ingresado no es correcto. Por favor intentalo de nuevo o <a href=\"/reset\">pide un nuevo código</a>.",
"new_password": "Nueva Contraseña",
"repeat_password": "Confirmar Contraseña",
"enter_email": "Por favor ingresa tu <strong>email</strong> y te enviaremos un email de como resetear tu cuenta.",
"password_reset_sent": "Resteo de contraseña enviado",
"invalid_email": "Email Invalido o no existe!"
}

View File

@@ -0,0 +1,42 @@
{
"topic": "Tema",
"topics": "Temas",
"no_topics_found": "No se encontraron temas!",
"profile": "Perfil",
"posted_by": "Publicado por",
"chat": "Chat",
"notify_me": "Seras notificado cuando haya nuevas respuestas en este tema",
"quote": "Citar",
"reply": "Responder",
"edit": "Editar",
"delete": "Borrar",
"banned": "banneado",
"link": "Link",
"thread_tools.title": "Herramientas del Tema",
"thread_tools.pin": "Poner Sticky",
"thread_tools.lock": "Cerrar Tema",
"thread_tools.move": "Mover Tema",
"thread_tools.delete": "Borrar Tema",
"load_categories": "Cargando Categorias",
"disabled_categories_note": "Las categorías deshabilidas estan en gris",
"confirm_move": "Mover",
"favourite": "Favorito",
"favourites": "Favoritos",
"favourites.not_logged_in.title": "No estas conectado :(",
"favourites.not_logged_in.message": "Por favor, conectate para agregar a favorito este post.",
"favourites.has_no_favourites": "No tienes favoritos, puedes agregar alguno y volver a verlos aqui!",
"posted_by": "Publicado por",
"loading": "Cargando",
"more_posts": "Más posts",
"move_topic": "Mover Tema",
"topic_will_be_moved_to": "Este tema sera movido a la categoría",
"reputation": "Reputación",
"posts": "Posts"
}

View File

@@ -0,0 +1,5 @@
{
"no_unread_topics": "No hay temas nuevos para leer.",
"mark_all_read": "Marcar todo como leeido",
"load_more": "Cargar más"
}

View File

@@ -0,0 +1,36 @@
{
"banned": "Banneado",
"offline": "Desconectado",
"email": "Email",
"fullname": "Nombre Completo",
"website": "Website",
"location": "Ubicación",
"age": "Edad",
"joined": "Registro",
"profile_views": "Visitas en su perfil",
"reputation": "Reputación",
"posts": "Posts",
"followers": "Seguidores",
"following": "Siguiendo",
"signature": "Firma",
"gravatar": "Gravatar",
"birthday": "Cumpleaños",
"change_picture": "Cambiar Foto",
"edit": "Editar",
"uploaded_picture": "Fotos Cargadas",
"upload_new_picture": "Cargar Nueva Foto",
"change_password": "Cambiar Contraseña",
"confirm_password": "Confirmar Contraseña",
"password": "Contraseña",
"upload_picture": "Cargar foto",
"upload_a_picture": "Cargar una foto",
"image_spec": "Solo puedes usar PNG, JPG, o GIF hasta 256kb.",
"settings": "Opciones",
"show_email": "Mostrar mi Email",
"has_no_follower": "Este miembro no tiene seguidores :(",
"follows_no_one": "Este miembro no sigue a nadie, que pena :("
}

View File

@@ -0,0 +1,9 @@
{
"latest_users": "Ultimos Miembros",
"top_posters": "Top Posteadores",
"most_reputation": "Mayor Reputación",
"online": "Conectados",
"search": "Buscar",
"enter_username": "Ingresa el nombre de usuario para buscar",
"load_more": "Cargar más"
}

View File

@@ -0,0 +1,14 @@
{
"new_topic_button": "Nouveau Sujet",
"no_topics": "<strong>Il n'y a aucun topic dans cette catégorie.</strong><br />Pourquoi ne pas en créer un?",
"sidebar.recent_replies": "Réponses Récentes",
"sidebar.active_participants": "Participants Actifs",
"sidebar.moderators": "Modérateurs",
"posts": "messages",
"views": "vues",
"posted": "posté",
"browsing": "naviguer",
"no_replies": "Personne n'a répondu",
"replied": "répondu",
"last_edited_by": "dernière édition par"
}

View File

@@ -0,0 +1,10 @@
{
"chat.chatting_with": "Chat avec <span id=\"chat-with-name\"></span>",
"chat.placeholder": "taper le message ici, presser entrer pour envoyer",
"chat.send": "Envoyer",
"stats.online": "Online",
"stats.users": "Utilisateurs",
"stats.topics": "Sujets",
"stats.posts": "Message",
"success": "succès"
}

View File

@@ -0,0 +1,31 @@
{
"home": "Accueil",
"search": "Recherche",
"buttons.close": "Fermer",
"403.title": "Accès Refusé",
"403.message": "Il semble que vous vous soyez retrouvé sur une page dont vous n'avez pas accès. Peut-être devriez vous <a href='/login'>essayez de vous connecter</a>?",
"404.title": "Introuvable",
"404.message": "Il semble que vous vous soyez retrouvé sur une page qui n'existe pas. Retourner à <a href='/'>l'accueil</a>.",
"500.title": "Erreur Interne.",
"500.message": "Oops! Il semblerait que quelque chose se soit mal passé!",
"register": "S'inscrire",
"login": "Connecter",
"logout": "Déconnection",
"logout.title": "Vous êtes maintenant déconnecté.",
"logout.message": "Vous vous êtes déconnecté de NodeBB avec succès",
"save_changes": "Enregistrer les changements",
"close": "Fermer",
"header.admin": "Admin",
"header.recent": "Récent",
"header.unread": "Non Lu",
"header.users": "Utilisateurs",
"header.search": "Recherche",
"header.profile": "Profile",
"notifications.loading": "Chargement des Notifications",
"chats.loading": "Chargement des Chats"
}

View File

@@ -0,0 +1,10 @@
{
"login": "Connexion",
"username": "Identifiant",
"password": "Mot de passe",
"remember_me": "Se souvenir de moi?",
"forgot_password": "Mot de passe oublié?",
"alternative_logins": "Connexion Alternative",
"failed_login_attempt": "Echèc d'authentification, veuillez réessayer.",
"login_successful": "Vous êtes maintenant connecté!"
}

View File

@@ -0,0 +1,9 @@
{
"title": "Notifications",
"back_to_home": "retour à NodeBB",
"mark_all_as_read": "Tout marquer comme lu",
"outgoing_link": "Lien Sortant",
"outgoing_link_message": "Vous quitter NodeBB",
"continue_to": "Continuer vers",
"return_to": "Retour vers"
}

View File

@@ -0,0 +1,5 @@
{
"day": "Jour",
"week": "Semaine",
"month": "Mois"
}

View File

@@ -0,0 +1,16 @@
{
"register": "S'inscrire",
"help.email": "Par défault, votre email est masqué du public.",
"help.username_restrictions": "Un identifiant unique entre %1 et %2 charactères. Les autres utilisateurs peuvent vous citer avec @<span id='yourUsername'>username</span>.",
"help.minimum_password_length": "Votre mot de passe doit avoir au moins %1 charactères.",
"email_address": "Adresse Email",
"email_address_placeholder": "Entrer l'addresse Email",
"username": "Nom d'utilisateur",
"username_placeholder": "Entré le Nom d'utilisateur",
"password": "Mot de passe",
"password_placeholder": "Entrer le Mot de passe",
"confirm_password": "Confirmer le Mot de passe",
"confirm_password_placeholder": "Confirmer le Mot de passe",
"register_now_button": "S'enregistrer maintenant",
"alternative_registration": "Enregistrement Alternatif"
}

View File

@@ -0,0 +1,13 @@
{
"reset_password": "Réinitialiser le Mot de passe",
"update_password": "Mettre à jour le Mot de passe",
"password_changed.title": "Mot de passe modifié",
"password_changed.message": "<p>Mot de passe réinitialisé avec succès, veuillez vous <a href=\"/login\">reconnecter</a>.",
"wrong_reset_code.title": "Code de Réinisialisation Incorrect",
"wrong_reset_code.message": "Le Code de Réinisialisation est Incorrect. Veillez réessayer, ou <a href=\"/reset\">demander un nouveau Code de Réinisialisation</a>.",
"new_password": "Nouveau Mot de passe",
"repeat_password": "Confirmer le Mot de passe",
"enter_email": "Veuillez entrer votre <strong>adresse email</strong> et vous recevrez un email avec les instruction pour réinitialiser votre compte.",
"password_reset_sent": "Réinitialisation de Mot de Passe Envoyée",
"invalid_email": "Email Invalide / L'Email n'existe pas!"
}

View File

@@ -0,0 +1,42 @@
{
"topic": "Sujet",
"topics": "Sujets",
"no_topics_found": "Aucun sujet trouvé!",
"profile": "Profile",
"posted_by": "Envoyé by",
"chat": "Chat",
"notify_me": "Être notifié des réponses dans ce sujet",
"quote": "Citer",
"reply": "Répondre",
"edit": "Editer",
"delete": "Supprimer",
"banned": "bannir",
"link": "Lien",
"thread_tools.title": "Outils du Fil",
"thread_tools.pin": "Epingler le fil",
"thread_tools.lock": "Verrouiller le fil",
"thread_tools.move": "Déplacer le fil",
"thread_tools.delete": "Supprimer le fil",
"load_categories": "Chargement des Categories",
"disabled_categories_note": "Les Catégories Désactivées sont grisées",
"confirm_move": "Déplacer",
"favourite": "Favoris",
"favourites": "Favoris",
"favourites.not_logged_in.title": "Non Connecté",
"favourites.not_logged_in.message": "Veuillez vous connecter avant de mettre ce message en Favoris",
"favourites.has_no_favourites": "Vous n'avez aucun Favoris, mettre en favoris des messages pour les voir apparaître ici!",
"posted_by": "posté par",
"loading": "Chargement",
"more_posts": "d'autres Messages",
"move_topic": "Déplacer le Sujet",
"topic_will_be_moved_to": "Ce sujet sera déplacé vers la catégorie",
"reputation": "réputation",
"posts": "messages"
}

View File

@@ -0,0 +1,5 @@
{
"no_unread_topics": "Aucun sujet non lu.",
"mark_all_read": "Marquer tout comme lu",
"load_more": "Charger la suite"
}

View File

@@ -0,0 +1,36 @@
{
"banned": "Banni",
"offline": "Hors-ligne",
"email": "email",
"fullname": "Nom",
"website": "Site Web",
"location": "Emplacement",
"age": "age",
"joined": "adhésion",
"profil_views": "vues du profil",
"reputation": "réputation",
"posts": "messages",
"followers": "suiveurs",
"following": "suivis",
"signature": "signature",
"gravatar": "gravatar",
"birthday": "anniversaire",
"change_picture": "changer d'image",
"edit": "editer",
"uploaded_picture": "images uploadées",
"upload_new_picture": "uploader une nouvelle image",
"change_password": "chnger le mot de passe",
"confirm_password": "confirmer le mot de passe",
"password": "mot de passe",
"upload_picture": "Uploader un image",
"upload_a_picture": "Uploader un image",
"image_spec": "Vous pouvez uploader seulement des fichiers de types PNG, JPG, ou GIF en dessous de 256kb.",
"settings": "paramètres",
"show_my_email": "montrer mon email",
"has_no_follower": "Cet utilisateur n'a aucun suiver :(",
"follows_no_one": "Cet utilisateur ne suit personne :("
}

View File

@@ -0,0 +1,9 @@
{
"latest_users": "Derniers Utilisateurs",
"top_posters": "Meilleurs Publieur",
"most_reputation": "Meilleur Réputation",
"online": "En Ligne",
"search": "Rechercher",
"enter_username": "Entrer un nom d'utilisateur pour rechercher",
"load_more": "Charger la suite"
}

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,5 +1,6 @@
var ajaxify = {};
"use strict";
var ajaxify = {};
(function ($) {
/*global app, templates, utils*/
@@ -23,19 +24,27 @@ var ajaxify = {};
window.onpopstate = function (event) {
// "quiet": If set to true, will not call pushState
if (event !== null && event.state && event.state.url !== undefined)
ajaxify.go(event.state.url, null, null, true);
if (event !== null && event.state && event.state.url !== undefined) {
ajaxify.go(event.state.url, null, true);
}
};
var pagination;
var pagination, paginator_bar;
ajaxify.go = function (url, callback, template, quiet) {
ajaxify.currentPage = null;
ajaxify.go = function (url, callback, quiet) {
// start: the following should be set like so: ajaxify.onchange(function(){}); where the code actually belongs
$(window).off('scroll');
app.enter_room('global');
app.enterRoom('global');
pagination = pagination || document.getElementById('pagination');
if (pagination) pagination.parentNode.style.display = 'none';
paginator_bar = pagination ? document.body.querySelector('.progress-container') : undefined;
if (pagination) {
pagination.parentNode.style.display = 'none';
paginator_bar.style.display = 'none';
}
window.onscroll = null;
// end
@@ -62,41 +71,61 @@ var ajaxify = {};
}
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
if (quiet !== true) {
ajaxify.currentPage = tpl_url;
if (window.history && window.history.pushState) {
window.history.pushState({
"url": url
}, url, RELATIVE_PATH + "/" + url);
window.history[!quiet ? 'pushState' : 'replaceState']({
url: url
}, url, RELATIVE_PATH + '/' + url);
$.ajax(RELATIVE_PATH + '/plugins/fireHook', {
type: 'PUT',
data: {
_csrf: $('#csrf_token').val(),
hook: 'page.load',
args: {
template: tpl_url,
url: url,
uid: app.uid
}
}
});
}
translator.load(tpl_url);
jQuery('#footer, #content').fadeOut(100);
jQuery('#footer, #content').removeClass('hide').addClass('ajaxifying');
templates.flush();
templates.load_template(function () {
exec_body_scripts(content);
require(['forum/' + tpl_url], function(script) {
if (script && script.init) script.init();
if (script && script.init) {
script.init();
}
});
if (callback) {
callback();
}
app.process_page();
app.processPage();
jQuery('#content, #footer').stop(true, true).fadeIn(200, function () {
if (window.location.hash)
jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying');
if (window.location.hash) {
hash = window.location.hash;
if (hash)
app.scrollToPost(hash.substr(1));
}
if (hash) {
require(['forum/topic'], function(topic) {
topic.scrollToPost(hash.substr(1));
});
}
utils.refreshTitle(url);
app.refreshTitle(url);
}, url, template);
}, url);
return true;
}
@@ -104,28 +133,36 @@ var ajaxify = {};
return false;
};
ajaxify.refresh = function() {
ajaxify.go(ajaxify.currentPage);
};
$('document').ready(function () {
if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers
if (!window.history || !window.history.pushState) {
return; // no ajaxification for old browsers
}
content = content || document.getElementById('content');
// Enhancing all anchors to ajaxify...
$(document.body).on('click', 'a', function (e) {
function hrefEmpty(href) {
return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#";
return href === 'javascript:;' || href === window.location.href + "#" || href.slice(-1) === "#";
}
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:')
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') {
return;
}
if(!window.location.pathname.match(/\/(403|404)$/g))
if(!window.location.pathname.match(/\/(403|404)$/g)) {
app.previousUrl = window.location.href;
}
if (this.getAttribute('data-ajaxify') == 'false') {
if (this.getAttribute('data-ajaxify') === 'false') {
return;
}
if (!e.ctrlKey && e.which === 1) {
if ((!e.ctrlKey && !e.shiftKey) && e.which === 1) {
if (this.host === window.location.host) {
// Internal link
var url = this.href.replace(rootUrl + '/', '');

View File

@@ -1,16 +1,16 @@
var socket,
config,
app = {
'username': null,
'uid': null
"username": null,
"uid": null,
"isFocused": true,
"currentRoom": null
};
(function () {
var showWelcomeMessage = false;
app.loadConfig = function() {
$.ajax({
url: RELATIVE_PATH + '/api/config',
success: function (data) {
@@ -47,11 +47,40 @@ var socket,
socket.on('connect', function (data) {
if (reconnecting) {
reconnectEl.html('<i class="icon-ok"></i> Connected!');
reconnectEl.tooltip('destroy');
reconnectEl.html('<i class="fa fa-check"></i>');
reconnecting = false;
// Rejoin room that was left when we disconnected
var url_parts = document.location.pathname.slice(RELATIVE_PATH.length).split('/').slice(1),
room;
switch(url_parts[0]) {
case 'user':
room = 'user/' + templates.get('theirid');
case 'topic':
room = 'topic_' + url_parts[1];
break;
case 'category':
room = 'category_' + url_parts[1];
break;
case 'recent': // intentional fall-through
case 'unread':
room = 'recent_posts';
break;
case 'admin':
room = 'admin';
break;
default:
room = 'global';
break;
}
app.enterRoom(room, true);
socket.emit('reconnected');
setTimeout(function() {
reconnectEl.removeClass('active');
reconnectEl.removeClass('active').addClass("hide");
}, 3000);
}
@@ -74,8 +103,12 @@ var socket,
if (!reconnectEl) reconnectEl = $('#reconnect');
reconnecting = true;
reconnectEl.addClass('active');
reconnectEl.html('<i class="icon-spinner icon-spin"></i> Reconnecting...');
if (!reconnectEl.hasClass('active')) reconnectEl.html('<i class="fa fa-spinner fa-spin"></i>');
reconnectEl.addClass('active').removeClass("hide");
reconnectEl.tooltip({
placement: 'bottom'
});
});
socket.on('api:user.get_online_users', function (users) {
@@ -88,10 +121,10 @@ var socket,
if (uid && jQuery.inArray(uid, users) !== -1) {
el.find('i').remove();
el.prepend('<i class="icon-circle"></i>');
el.prepend('<i class="fa fa-circle"></i>');
} else {
el.find('i').remove();
el.prepend('<i class="icon-circle-blank"></i>');
el.prepend('<i class="fa fa-circle-o"></i>');
}
el.processed = true;
@@ -125,25 +158,25 @@ var socket,
setTimeout(app.logout, 1000);
});
app.enter_room('global');
app.enterRoom('global');
}
},
async: false
});
}
};
app.logout = function() {
$.post(RELATIVE_PATH + '/logout', {
_csrf: $('#csrf_token').val()
}, function() {
window.location.reload(false);
window.location.href = RELATIVE_PATH + '/';
});
}
};
// takes a string like 1000 and returns 1,000
app.addCommas = function (text) {
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
};
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
app.strip_tags = function (input, allowed) {
@@ -154,7 +187,7 @@ var socket,
return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
});
}
};
// use unique alert_id to have multiple alerts visible at a time, use the same alert_id to fade out the current instance
// type : error, success, info, warning/notify
@@ -186,46 +219,38 @@ var socket,
clearTimeout(alert.attr('timeoutId'));
startTimeout(alert, params.timeout);
} else {
var div = document.createElement('div'),
button = document.createElement('button'),
strong = document.createElement('strong'),
p = document.createElement('p');
var div = $('<div id="' + alert_id + '" class="alert toaster-alert alert-' + params.type +'"></div>'),
button = $('<button class="close">&times;</button>'),
strong = $('<strong>' + title + '</strong>'),
p = $('<p>' + params.message + '</p>');
p.innerHTML = params.message;
strong.innerHTML = title;
div.append(button)
.append(strong)
.append(p);
div.className = "alert toaster-alert " + "alert-" + params.type;
div.setAttribute('id', alert_id);
div.appendChild(button);
div.appendChild(strong);
div.appendChild(p);
button.className = 'close';
button.innerHTML = '&times;';
button.onclick = function (ev) {
div.parentNode.removeChild(div);
}
button.on('click', function () {
div.remove();
});
if (params.location == null)
params.location = 'alert_window';
jQuery('#' + params.location).prepend(jQuery(div).fadeIn('100'));
$('#' + params.location).prepend(div.fadeIn('100'));
if (params.timeout) {
startTimeout(div, params.timeout);
}
if (params.clickfn) {
div.onclick = function () {
div.on('click', function () {
params.clickfn();
jQuery(div).fadeOut(500, function () {
this.remove();
div.fadeOut(500, function () {
$(this).remove();
});
});
}
}
}
}
};
app.alertSuccess = function (message, timeout) {
if (!timeout)
@@ -237,7 +262,7 @@ var socket,
type: 'success',
timeout: timeout
});
}
};
app.alertError = function (message, timeout) {
if (!timeout)
@@ -249,24 +274,24 @@ var socket,
type: 'danger',
timeout: timeout
});
}
};
app.current_room = null;
app.enter_room = function (room) {
app.enterRoom = function (room, force) {
if (socket) {
if (app.current_room === room)
if (app.currentRoom === room && !force) {
return;
}
socket.emit('event:enter_room', {
'enter': room,
'leave': app.current_room
'leave': app.currentRoom
});
app.current_room = room;
app.currentRoom = room;
}
};
app.populate_online_users = function () {
app.populateOnlineUsers = function () {
var uids = [];
jQuery('.post-row').each(function () {
@@ -274,11 +299,9 @@ var socket,
});
socket.emit('api:user.get_online_users', uids);
}
app.process_page = function () {
app.populate_online_users();
};
function highlightNavigationLink() {
var path = window.location.pathname,
parts = path.split('/'),
active = parts[parts.length - 1];
@@ -295,14 +318,39 @@ var socket,
}
});
}
};
app.createUserTooltips = function() {
$('img[title].teaser-pic,img[title].user-img').each(function() {
$(this).tooltip({
placement: 'top',
title: $(this).attr('title')
});
});
};
app.makeNumbersHumanReadable = function(elements) {
elements.each(function() {
$(this).html(utils.makeNumberHumanReadable($(this).attr('title')));
});
};
app.processPage = function () {
app.populateOnlineUsers();
highlightNavigationLink();
$('span.timeago').timeago();
$('.post-content img').addClass('img-responsive');
app.makeNumbersHumanReadable($('.human-readable-number'));
app.createUserTooltips();
setTimeout(function () {
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
}, 100);
}
};
app.showLoginMessage = function () {
function showAlert() {
@@ -322,15 +370,37 @@ var socket,
showAlert();
}
}
}
};
app.addCommasToNumbers = function () {
$('.formatted-number').each(function (index, element) {
$(element).html(app.addCommas($(element).html()));
});
}
};
app.openChat = function (username, touid) {
if (username === app.username) {
app.alert({
type: 'warning',
title: 'Invalid Chat',
message: "You can't chat with yourself!",
timeout: 5000
});
return;
}
if (!app.username) {
app.alert({
type: 'danger',
title: 'Not Logged In',
message: 'Please log in to chat with <strong>' + username + '</strong>',
timeout: 5000
});
return;
}
require(['chat'], function (chat) {
var chatModal;
if (!chat.modalExists(touid)) {
@@ -341,62 +411,7 @@ var socket,
chat.load(chatModal.attr('UUID'));
chat.center(chatModal);
});
}
app.createNewPosts = function (data) {
if (data.posts[0].uid !== app.uid) {
data.posts[0].display_moderator_tools = 'none';
}
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
translator.translate(html, function(translatedHTML) {
var uniqueid = new Date().getTime(),
tempContainer = jQuery('<div id="' + uniqueid + '"></div>')
.appendTo("#post-container")
.hide()
.append(translatedHTML)
.fadeIn('slow');
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
socket.emit('api:post.privileges', data.posts[x].pid);
}
tempContainer.replaceWith(tempContainer.contents());
infiniteLoaderActive = false;
app.populate_online_users();
app.addCommasToNumbers();
$('span.timeago').timeago();
$('.post-content img').addClass('img-responsive');
});
}
app.infiniteLoaderActive = false;
app.loadMorePosts = function (tid, callback) {
if (app.infiniteLoaderActive)
return;
app.infiniteLoaderActive = true;
if ($('#loading-indicator').attr('done') === '0')
$('#loading-indicator').removeClass('hide');
socket.emit('api:topic.loadMore', {
tid: tid,
after: document.querySelectorAll('#post-container li[data-pid]').length
}, function (data) {
app.infiniteLoaderActive = false;
if (data.posts.length) {
$('#loading-indicator').attr('done', '0');
app.createNewPosts(data);
} else {
$('#loading-indicator').attr('done', '1');
}
$('#loading-indicator').addClass('hide');
if (callback)
callback(data.posts);
});
}
};
app.scrollToTop = function () {
$('body,html').animate({
@@ -408,56 +423,66 @@ var socket,
$('body,html').animate({
scrollTop: $('html').height() - 100
});
};
var titleObj = {
active: false,
interval: undefined,
titles: []
};
app.alternatingTitle = function (title) {
if (typeof title !== 'string') return;
if (title.length > 0) {
titleObj.titles[1] = title;
if (titleObj.interval) {
clearInterval(titleObj.interval);
}
titleObj.interval = setInterval(function() {
window.document.title = titleObj.titles[titleObj.titles.indexOf(window.document.title) ^ 1];
}, 2000);
} else {
if (titleObj.interval) {
clearInterval(titleObj.interval);
}
if (titleObj.titles[0]) window.document.title = titleObj.titles[0];
}
};
app.refreshTitle = function(url) {
if (!url) {
var a = document.createElement('a');
a.href = document.location;
url = a.pathname.slice(1);
}
app.scrollToPost = function (pid) {
if (!pid)
return;
var container = $(document.body),
scrollTo = $('#post_anchor_' + pid),
tid = $('#post-container').attr('data-tid');
function animateScroll() {
$('body,html').animate({
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
}, 400);
//$('body,html').scrollTop(scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height());
}
if (!scrollTo.length && tid) {
var intervalID = setInterval(function () {
app.loadMorePosts(tid, function (posts) {
scrollTo = $('#post_anchor_' + pid);
if (tid && scrollTo.length) {
animateScroll();
}
if (!posts.length || scrollTo.length)
clearInterval(intervalID);
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
app.alternatingTitle('');
});
}, 100);
} else if (tid) {
animateScroll();
}
}
};
jQuery('document').ready(function () {
$('#search-form').on('submit', function () {
var input = $(this).find('input');
ajaxify.go("search/" + input.val(), null, "search");
ajaxify.go("search/" + input.val());
input.val('');
return false;
});
$(window).blur(function(){
app.isFocused = false;
});
$(window).focus(function(){
app.isFocused = true;
app.alternatingTitle('');
});
});
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
app.loadConfig();
app.alternatingTitle('');
}());

View File

@@ -10,24 +10,28 @@ define(['forum/accountheader'], function(header) {
$(document).ready(function() {
var username = $('.account-username a').html();
app.enter_room('user/' + theirid);
app.enterRoom('user/' + theirid);
app.addCommasToNumbers();
$('.user-recent-posts img').addClass('img-responsive');
var followBtn = $('#follow-btn');
var unfollowBtn = $('#unfollow-btn');
var chatBtn = $('#chat-btn');
if (yourid !== theirid && yourid !== "0") {
if (isFollowing) {
followBtn.hide();
unfollowBtn.show();
followBtn.addClass('hide');
unfollowBtn.removeClass('hide');
} else {
followBtn.show();
unfollowBtn.hide();
followBtn.removeClass('hide');
unfollowBtn.addClass('hide');
}
chatBtn.removeClass('hide');
} else {
followBtn.hide();
unfollowBtn.hide();
followBtn.addClass('hide');
unfollowBtn.addClass('hide');
chatBtn.addClass('hide');
}
followBtn.on('click', function() {
@@ -35,8 +39,8 @@ define(['forum/accountheader'], function(header) {
uid: theirid
}, function(success) {
if (success) {
followBtn.hide();
unfollowBtn.show();
followBtn.addClass('hide');
unfollowBtn.removeClass('hide');
app.alertSuccess('You are now following ' + username + '!');
} else {
app.alertError('There was an error following' + username + '!');
@@ -50,8 +54,8 @@ define(['forum/accountheader'], function(header) {
uid: theirid
}, function(success) {
if (success) {
followBtn.show();
unfollowBtn.hide();
followBtn.removeClass('hide');
unfollowBtn.addClass('hide');
app.alertSuccess('You are no longer following ' + username + '!');
} else {
app.alertError('There was an error unfollowing ' + username + '!');
@@ -60,6 +64,10 @@ define(['forum/accountheader'], function(header) {
return false;
});
chatBtn.on('click', function() {
app.openChat(username, theirid);
});
$('.user-recent-posts .topic-row').on('click', function() {
ajaxify.go($(this).attr('topic-url'));
});
@@ -71,6 +79,7 @@ define(['forum/accountheader'], function(header) {
socket.on('event:new_post', function(data) {
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
$('.user-recent-posts').prepend(html);
$('.user-recent-posts span.timeago').timeago();
});
});
@@ -81,10 +90,10 @@ define(['forum/accountheader'], function(header) {
if (data.online) {
onlineStatus.find('span span').text('online');
onlineStatus.find('i').attr('class', 'icon-circle');
onlineStatus.find('i').attr('class', 'fa fa-circle');
} else {
onlineStatus.find('span span').text('offline');
onlineStatus.find('i').attr('class', 'icon-circle-blank');
onlineStatus.find('i').attr('class', 'fa fa-circle-o');
}
};

View File

@@ -1,11 +1,13 @@
define(['forum/accountheader', 'uploader'], function(header, uploader) {
var AccountEdit = {};
var AccountEdit = {},
gravatarPicture = '',
uploadedPicture = '';
AccountEdit.init = function() {
header.init();
var gravatarPicture = templates.get('gravatarpicture');
var uploadedPicture = templates.get('uploadedpicture');
gravatarPicture = templates.get('gravatarpicture');
uploadedPicture = templates.get('uploadedpicture');
var selectedImageType = '';
@@ -39,6 +41,17 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
return false;
});
function getSignatureCharsLeft() {
return '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')';
}
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
$('#inputSignature').on('keyup change', function(ev) {
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
});
$('#changePictureBtn').on('click', function() {
selectedImageType = '';
AccountEdit.updateImages();
@@ -50,14 +63,14 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
});
$('#gravatar-box').on('click', function() {
$('#gravatar-box .icon-ok').show();
$('#uploaded-box .icon-ok').hide();
$('#gravatar-box .fa-check').show();
$('#uploaded-box .fa-check').hide();
selectedImageType = 'gravatar';
});
$('#uploaded-box').on('click', function() {
$('#gravatar-box .icon-ok').hide();
$('#uploaded-box .icon-ok').show();
$('#gravatar-box .fa-check').hide();
$('#uploaded-box .fa-check').show();
selectedImageType = 'uploaded';
});
@@ -82,7 +95,9 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
$('#uploadPictureBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
uploader.open(config.relative_path + '/user/uploadpicture', function(imageUrlOnServer) {
uploader.open(RELATIVE_PATH + '/user/uploadpicture', function(imageUrlOnServer) {
imageUrlOnServer = imageUrlOnServer + '?' + new Date().getTime();
$('#user-current-picture').attr('src', imageUrlOnServer);
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
@@ -97,6 +112,22 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
return false;
});
function showError(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
validationError = true;
}
function showSuccess(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
}
(function handlePasswordChange() {
var currentPassword = $('#inputCurrentPassword');
@@ -106,44 +137,31 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
var password_confirm = $('#inputNewPasswordAgain');
var passwordvalid = false;
var passwordsmatch = false;
var successIcon = '<i class="fa fa-check"></i>';
function onPasswordChanged() {
passwordvalid = utils.isPasswordValid(password.val());
if (password.val().length < config.minimumPasswordLength) {
password_notify.html('Password too short');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
showError(password_notify, 'Password too short!');
} else if (!passwordvalid) {
password_notify.html('Invalid password');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
showError(password_notify, 'Invalid password!');
} else {
password_notify.html('OK!');
password_notify.attr('class', 'alert alert-success');
password_notify.removeClass('hide');
showSuccess(password_notify, successIcon);
}
onPasswordConfirmChanged();
}
function onPasswordConfirmChanged() {
if (password_notify.hasClass('alert-danger') || !password_confirm.val()) {
password_confirm_notify.addClass('hide');
return;
}
if(password.val()) {
if (password.val() !== password_confirm.val()) {
password_confirm_notify.html('Passwords must match!');
password_confirm_notify.attr('class', 'alert alert-danger');
password_confirm_notify.removeClass('hide');
showError(password_confirm_notify, 'Passwords must match!')
passwordsmatch = false;
} else {
password_confirm_notify.html('OK!');
password_confirm_notify.attr('class', 'alert alert-success');
password_confirm_notify.removeClass('hide');
showSuccess(password_confirm_notify, successIcon);
passwordsmatch = true;
}
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
@@ -159,8 +177,6 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
currentPassword.val('');
password.val('');
password_confirm.val('');
password_notify.addClass('hide');
password_confirm_notify.addClass('hide');
passwordsmatch = false;
passwordvalid = false;
@@ -194,31 +210,33 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
AccountEdit.updateImages = function() {
var currentPicture = $('#user-current-picture').attr('src');
var gravatarPicture = templates.get('gravatarpicture');
var uploadedPicture = templates.get('uploadedpicture');
if (gravatarPicture) {
$('#user-gravatar-picture').attr('src', gravatarPicture);
$('#gravatar-box').show();
} else
} else {
$('#gravatar-box').hide();
}
if (uploadedPicture) {
$('#user-uploaded-picture').attr('src', uploadedPicture);
$('#uploaded-box').show();
} else
} else {
$('#uploaded-box').hide();
}
if (currentPicture == gravatarPicture)
$('#gravatar-box .icon-ok').show();
else
$('#gravatar-box .icon-ok').hide();
if (currentPicture == gravatarPicture) {
$('#gravatar-box .fa-check').show();
} else {
$('#gravatar-box .fa-check').hide();
}
if (currentPicture == uploadedPicture)
$('#uploaded-box .icon-ok').show();
else
$('#uploaded-box .icon-ok').hide();
if (currentPicture == uploadedPicture) {
$('#uploaded-box .fa-check').show();
} else {
$('#uploaded-box .fa-check').hide();
}
}
return AccountEdit;

View File

@@ -10,8 +10,8 @@ define(['forum/accountheader'], function(header) {
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
};
socket.emit('api:user.saveSettings', settings, function(success) {
if (success) {
socket.emit('api:user.saveSettings', settings, function(err) {
if (!err) {
app.alertSuccess('Settings saved!');
} else {
app.alertError('There was an error saving settings!');

View File

@@ -1,4 +1,4 @@
define(function() {
define(['uploader'], function(uploader) {
var Categories = {};
Categories.init = function() {
@@ -18,27 +18,31 @@ define(function() {
}
function select_icon(el) {
var selected = el.attr('class').replace(' icon-2x', '');
jQuery('#icons .selected').removeClass('selected');
var selected = el.attr('class').replace(' fa-2x', '');
$('#icons .selected').removeClass('selected');
if (selected)
jQuery('#icons .' + selected).parent().addClass('selected');
$('#icons .' + selected).parent().addClass('selected');
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
if (confirm) {
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
el.attr('class', iconClass + ' icon-2x');
el.val(iconClass);
el.attr('value', iconClass);
var iconClass = $('.bootbox .selected').children(':first').attr('class');
el.attr('class', iconClass + ' fa-2x');
// remove the 'fa ' from the class name, just need the icon name itself
var categoryIconClass = iconClass.replace('fa ', '');
el.val(categoryIconClass);
el.attr('value', categoryIconClass);
modified(el);
}
});
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
jQuery('.bootbox .col-md-3').on('click', function() {
jQuery('.bootbox .selected').removeClass('selected');
jQuery(this).addClass('selected');
$('.bootbox .col-md-3').on('click', function() {
$('.bootbox .selected').removeClass('selected');
$(this).addClass('selected');
});
}, 500);
}
@@ -58,13 +62,13 @@ define(function() {
}
}
jQuery('#entry-container').sortable({
$('#entry-container').sortable({
stop: function( event, ui ) {
updateCategoryOrders();
}
});
jQuery('.blockclass').each(function() {
jQuery(this).val(this.getAttribute('data-value'));
$('.blockclass').each(function() {
$(this).val(this.getAttribute('data-value'));
});
@@ -77,7 +81,9 @@ define(function() {
name: $('#inputName').val(),
description: $('#inputDescription').val(),
icon: $('#new-category-modal i').val(),
blockclass: $('#inputBlockclass').val()
bgColor: '#0059b2',
color: '#fff',
order: $('.admin-categories #entry-container').children().length + 1
};
socket.emit('api:admin.categories.create', category, function(err, data) {
@@ -100,54 +106,50 @@ define(function() {
});
}
jQuery('document').ready(function() {
$('document').ready(function() {
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
jQuery('.nav-pills li').removeClass('active');
jQuery('.nav-pills li a').each(function() {
$('.nav-pills li').removeClass('active');
$('.nav-pills li a').each(function() {
if (this.getAttribute('href').match(active)) {
jQuery(this.parentNode).addClass('active');
$(this.parentNode).addClass('active');
return false;
}
});
jQuery('#save').on('click', save);
jQuery('#addNew').on('click', showCreateCategoryModal);
jQuery('#create-category-btn').on('click', createNewCategory);
$('#save').on('click', save);
$('#addNew').on('click', showCreateCategoryModal);
$('#create-category-btn').on('click', createNewCategory);
jQuery('#entry-container').on('click', '.icon', function(ev) {
$('#entry-container').on('click', '.icon', function(ev) {
select_icon($(this).find('i'));
});
jQuery('#new-category-modal').on('click', '.icon', function(ev) {
$('#new-category-modal').on('click', '.icon', function(ev) {
select_icon($(this).find('i'));
});
jQuery('.blockclass').on('change', function(ev) {
update_blockclass(ev.target);
});
jQuery('.category_name, .category_description, .blockclass').on('change', function(ev) {
$('.admin-categories form input').on('change', function(ev) {
modified(ev.target);
});
jQuery('.entry-row button').each(function(index, element) {
$('.dropdown li[data-disabled]').each(function(index, element) {
var disabled = $(element).attr('data-disabled');
if (disabled == "0" || disabled == "")
$(element).html('Disable');
else
$(element).html('Enable');
if (disabled == "0" || disabled == "") {
$(element).html('<a href="#"><i class="fa fa-power-off"></i> Disable</a>');
} else {
$(element).html('<a href="#"><i class="fa fa-power-off"></i> Enable</a>');
}
});
jQuery('#entry-container').on('click', '.disable-btn', function(ev) {
var btn = jQuery(this);
$('.dropdown').on('click', '[data-disabled]', function(ev) {
var btn = $(this);
var categoryRow = btn.parents('li');
var cid = categoryRow.attr('data-cid');
var disabled = btn.html() == "Disable" ? "1" : "0";
var disabled = this.getAttribute('data-disabled') === '0' ? '1' : '0';
categoryRow.remove();
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid]['disabled'] = disabled;
@@ -156,6 +158,191 @@ define(function() {
return false;
});
// Colour Picker
$('[data-name="bgColor"], [data-name="color"]').each(function(idx, inputEl) {
var jinputEl = $(this),
previewEl = jinputEl.parents('[data-cid]').find('.preview-box');
jinputEl.ColorPicker({
color: this.value || '#000',
onChange: function(hsb, hex) {
jinputEl.val('#' + hex);
if (inputEl.getAttribute('data-name') === 'bgColor') previewEl.css('background', '#' + hex);
else if (inputEl.getAttribute('data-name') === 'color') previewEl.css('color', '#' + hex);
modified(inputEl);
}
});
});
// Permissions modal
$('.permissions').on('click', function() {
var cid = $(this).parents('li[data-cid]').attr('data-cid');
Categories.launchPermissionsModal(cid);
});
$('.upload-button').on('click', function() {
var inputEl = this;
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', function(imageUrlOnServer) {
inputEl.value = imageUrlOnServer;
$(inputEl).parents('li[data-cid]').find('.preview-box').css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
modified(inputEl);
});
});
$('.admin-categories').delegate('.delete-image', 'click', function() {
var parent = $(this).parents('li[data-cid]'),
inputEl = parent.find('.upload-button'),
preview = parent.find('.preview-box'),
bgColor = parent.find('.category_bgColor').val();
inputEl.value = '';
modified(inputEl);
preview.css('background', bgColor);
$(this).hide();
});
});
};
Categories.launchPermissionsModal = function(cid) {
var modal = $('#category-permissions-modal'),
searchEl = modal.find('#permission-search'),
resultsEl = modal.find('.search-results'),
groupsResultsEl = modal.find('.groups-results'),
searchDelay;
searchEl.off().on('keyup', function() {
var searchEl = this,
resultsFrag = document.createDocumentFragment(),
liEl = document.createElement('li');
clearTimeout(searchDelay);
searchDelay = setTimeout(function() {
socket.emit('api:admin.categories.search', searchEl.value, cid, function(err, results) {
var numResults = results.length,
resultObj;
for(var x=0;x<numResults;x++) {
resultObj = results[x];
liEl.setAttribute('data-uid', resultObj.uid);
liEl.innerHTML = '<div class="pull-right">' +
'<div class="btn-group">' +
'<button type="button" data-priv="+r" class="btn btn-default' + (resultObj.privileges['+r'] ? ' active' : '') + '">Read</button>' +
'<button type="button" data-priv="+w" class="btn btn-default' + (resultObj.privileges['+w'] ? ' active' : '') + '">Write</button>' +
'</div>' +
'</div>' +
'<img src="' + resultObj.picture + '" /> ' + resultObj.username;
resultsFrag.appendChild(liEl.cloneNode(true));
}
resultsEl.html(resultsFrag);
});
}, 250);
});
Categories.refreshPrivilegeList(cid);
resultsEl.off().on('click', '[data-priv]', function(e) {
var btnEl = $(this),
uid = btnEl.parents('li[data-uid]').attr('data-uid'),
privilege = this.getAttribute('data-priv');
e.preventDefault();
socket.emit('api:admin.categories.setPrivilege', cid, uid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
btnEl.toggleClass('active', privileges[privilege]);
Categories.refreshPrivilegeList(cid);
});
});
modal.off().on('click', '.members li > img', function() {
searchEl.val(this.getAttribute('title'));
searchEl.keyup();
});
// User Groups and privileges
socket.emit('api:admin.categories.groupsearch', cid, function(err, results) {
var groupsFrag = document.createDocumentFragment(),
liEl = document.createElement('li');
var numResults = results.length,
resultObj;
for(var x=0;x<numResults;x++) {
resultObj = results[x];
liEl.setAttribute('data-gid', resultObj.gid);
liEl.innerHTML = '<div class="pull-right">' +
'<div class="btn-group">' +
'<button type="button" data-gpriv="+gr" class="btn btn-default' + (resultObj.privileges['+gr'] ? ' active' : '') + '">Read</button>' +
'<button type="button" data-gpriv="+gw" class="btn btn-default' + (resultObj.privileges['+gw'] ? ' active' : '') + '">Write</button>' +
'</div>' +
'</div>' +
' '+resultObj.name;
groupsFrag.appendChild(liEl.cloneNode(true));
}
groupsResultsEl.html(groupsFrag);
});
groupsResultsEl.off().on('click', '[data-gpriv]', function(e) {
var btnEl = $(this),
gid = btnEl.parents('li[data-gid]').attr('data-gid'),
privilege = this.getAttribute('data-gpriv');
e.preventDefault();
socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
btnEl.toggleClass('active', privileges[privilege]);
});
})
modal.modal();
};
Categories.refreshPrivilegeList = function (cid) {
var modalEl = $('#category-permissions-modal'),
readMembers = modalEl.find('#category-permissions-read'),
writeMembers = modalEl.find('#category-permissions-write');
socket.emit('api:admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
var readLength = privilegeList['+r'].length,
writeLength = privilegeList['+w'].length,
readFrag = document.createDocumentFragment(),
writeFrag = document.createDocumentFragment(),
liEl = document.createElement('li'),
x, userObj;
if (readLength > 0) {
for(x=0;x<readLength;x++) {
userObj = privilegeList['+r'][x];
liEl.setAttribute('data-uid', userObj.uid);
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
readFrag.appendChild(liEl.cloneNode(true));
}
} else {
liEl.className = 'empty';
liEl.innerHTML = 'No users are in this list';
readFrag.appendChild(liEl.cloneNode(true));
}
if (writeLength > 0) {
for(x=0;x<writeLength;x++) {
userObj = privilegeList['+w'][x];
liEl.setAttribute('data-uid', userObj.uid);
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
writeFrag.appendChild(liEl.cloneNode(true));
}
} else {
liEl.className = 'empty';
liEl.innerHTML = 'No users are in this list';
writeFrag.appendChild(liEl.cloneNode(true));
}
readMembers.html(readFrag);
writeMembers.html(writeFrag);
});
};

View File

@@ -45,10 +45,12 @@ define(function() {
errorEl.html(errorText).removeClass('hide');
} else {
createModal.modal('hide');
errorEl.addClass('hide');
createNameEl.val('');
createModal.on('hidden.bs.modal', function() {
ajaxify.go('admin/groups');
});
createModal.modal('hide');
}
});
});

View File

@@ -20,8 +20,16 @@ define(function() {
document.getElementById('connections').innerHTML = total;
});
app.enter_room('admin');
app.enterRoom('admin');
socket.emit('api:get_all_rooms');
$('#logout-link').on('click', function() {
$.post(RELATIVE_PATH + '/logout', {
_csrf: $('#csrf_token').val()
}, function() {
window.location.href = RELATIVE_PATH + '/';
});
})
};
return Admin;

View File

@@ -13,7 +13,7 @@ define(function() {
socket.on('api:admin.plugins.toggle', function(status) {
pluginTgl = document.querySelector('.plugins li[data-plugin-id="' + status.id + '"] button');
pluginTgl.innerHTML = '<i class="icon-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';
pluginTgl.innerHTML = '<i class="fa fa-power-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';
app.alert({
alert_id: 'plugin_toggled_' + status.id,

View File

@@ -32,12 +32,14 @@ define(['uploader'], function(uploader) {
break;
case 'checkbox':
fields[x].checked = app.config[key] === '1' ? true : false;
fields[x].checked = parseInt(app.config[key], 10) === 1;
break;
}
}
} else if (fields[x].nodeName === 'TEXTAREA') {
if (app.config[key]) fields[x].value = app.config[key];
} else if (fields[x].nodeName === 'SELECT') {
if (app.config[key]) fields[x].value = app.config[key];
}
}
@@ -61,6 +63,8 @@ define(['uploader'], function(uploader) {
}
} else if (fields[x].nodeName === 'TEXTAREA') {
value = fields[x].value;
} else if (fields[x].nodeName === 'SELECT') {
value = fields[x].value;
}
socket.emit('api:config.set', {
@@ -71,13 +75,20 @@ define(['uploader'], function(uploader) {
});
$('#uploadLogoBtn').on('click', function() {
uploader.open(config.relative_path + '/admin/uploadlogo', function(image) {
uploader.open(RELATIVE_PATH + '/admin/uploadlogo', function(image) {
$('#logoUrl').val(image);
});
uploader.hideAlerts();
});
$('#uploadFaviconBtn').on('click', function() {
uploader.open(RELATIVE_PATH + '/admin/uploadfavicon', function(icon) {
$('#faviconUrl').val(icon);
});
uploader.hideAlerts();
});
};
Settings.remove = function(key) {

View File

@@ -42,10 +42,15 @@ define(function() {
loadMoreEl.addEventListener('click', function() {
if (this.className.indexOf('disabled') === -1) {
var topics = document.querySelectorAll('.topics li[data-tid]'),
lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
var topics = document.querySelectorAll('.topics li[data-tid]');
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
if(!topics.length) {
return;
}
var lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
this.innerHTML = '<i class="fa fa-refresh fa-spin"></i> Retrieving topics';
socket.emit('api:admin.topics.getMore', {
limit: 10,
after: lastTid

View File

@@ -64,6 +64,40 @@ define(function() {
});
}
function handleUserCreate() {
$('#createUser').on('click', function() {
$('#create-modal').modal('show');
});
$('#create-modal-go').on('click', function() {
var username = $('#create-user-name').val(),
email = $('#create-user-email').val(),
password = $('#create-user-password').val(),
passwordAgain = $('#create-user-password-again').val(),
errorEl = $('#create-modal-error');
if(password !== passwordAgain) {
return errorEl.html('<strong>Error</strong><p>Passwords must match!</p>').removeClass('hide');
}
var user = {
username: username,
email: email,
password: password
};
socket.emit('api:admin.user.createUser', user, function(err, data) {
if(err) {
return errorEl.html('<strong>Error</strong><p>' + err + '</p>').removeClass('hide');
}
$('#create-modal').modal('hide');
app.alertSuccess('User created!');
ajaxify.go('admin/users');
});
});
}
jQuery('document').ready(function() {
@@ -91,7 +125,7 @@ define(function() {
timeoutId = setTimeout(function() {
var username = $('#search-user').val();
jQuery('.icon-spinner').removeClass('none');
jQuery('.fa-spinner').removeClass('none');
socket.emit('api:admin.user.search', username);
}, 250);
@@ -99,6 +133,8 @@ define(function() {
initUsers();
handleUserCreate();
socket.removeAllListeners('api:admin.user.search');
socket.on('api:admin.user.search', function(data) {
@@ -108,7 +144,7 @@ define(function() {
userListEl = document.querySelector('.users');
userListEl.innerHTML = html;
jQuery('.icon-spinner').addClass('none');
jQuery('.fa-spinner').addClass('none');
if (data && data.length === 0) {
$('#user-notfound-notify').html('User not found!')

View File

@@ -1,18 +1,17 @@
define(function () {
var Category = {};
define(['composer'], function(composer) {
var Category = {},
loadingMoreTopics = false;
Category.init = function() {
var cid = templates.get('category_id'),
room = 'category_' + cid,
twitterEl = jQuery('#twitter-intent'),
facebookEl = jQuery('#facebook-share'),
googleEl = jQuery('#google-share'),
twitter_url = templates.get('twitter-intent-url'),
facebook_url = templates.get('facebook-share-url'),
google_url = templates.get('google-share-url'),
loadingMoreTopics = false;
google_url = templates.get('google-share-url');
app.enter_room(room);
app.enterRoom('category_' + cid);
twitterEl.on('click', function () {
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
@@ -28,9 +27,7 @@ define(function () {
});
$('#new_post').on('click', function () {
require(['composer'], function (cmp) {
cmp.push(0, cid);
});
composer.newTopic(cid);
});
ajaxify.register_events([
@@ -56,7 +53,7 @@ define(function () {
li.setAttribute('data-pid', posts[i].pid);
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded" src="' + posts[i].picture + '" class="" /></a>' +
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded user-img" src="' + posts[i].picture + '" class="" /></a>' +
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
'<strong><span>'+ posts[i].username + '</span></strong>' +
'<p>' +
@@ -69,6 +66,7 @@ define(function () {
recent_replies.appendChild(frag);
}
$('#category_recent_replies span.timeago').timeago();
app.createUserTooltips();
});
$(window).off('scroll').on('scroll', function (ev) {
@@ -83,8 +81,10 @@ define(function () {
Category.onNewTopic = function(data) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: [data]
}),
topic = $(html),
});
translator.translate(html, function(translatedHTML) {
var topic = $(translatedHTML),
container = $('#topics-container'),
topics = $('#topics-container').children('.category-item'),
numTopics = topics.length;
@@ -94,22 +94,26 @@ define(function () {
if (numTopics > 0) {
for (var x = 0; x < numTopics; x++) {
if ($(topics[x]).find('.icon-pushpin').length)
if ($(topics[x]).find('.fa-thumb-tack').length) {
if(x === numTopics - 1) {
topic.insertAfter(topics[x]);
}
continue;
}
topic.insertBefore(topics[x]);
topic.hide().fadeIn('slow');
break;
}
} else {
container.append(topic);
topic.hide().fadeIn('slow');
}
topic.hide().fadeIn('slow');
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
addActiveUser(data);
$('#topics-container span.timeago').timeago();
});
}
function addActiveUser(data) {
@@ -128,22 +132,29 @@ define(function () {
}
Category.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
jQuery('#category-no-topics').remove();
html = $(translatedHTML);
container.append(html);
$('#topics-container span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
Category.loadMoreTopics = function(cid) {
if (loadingMoreTopics) {
return;
}
loadingMoreTopics = true;
socket.emit('api:category.loadMore', {
cid: cid,

View File

@@ -3,10 +3,6 @@ define(['forum/accountheader'], function(header) {
AccountHeader.init = function() {
header.init();
$('.user-favourite-posts .topic-row').on('click', function() {
ajaxify.go($(this).attr('topic-url'));
});
};
return AccountHeader;

View File

@@ -5,14 +5,15 @@
});
socket.on('api:updateHeader', function(data) {
jQuery('#search-button').on('click', function() {
jQuery('#search-fields').removeClass('hide').show();
jQuery(this).hide();
jQuery('#search-fields input').focus()
jQuery('#search-form').on('submit', function() {
jQuery('#search-fields').hide();
jQuery('#search-button').show();
$('#search-button').on('click', function() {
$('#search-fields').removeClass('hide').show();
$(this).hide();
$('#search-fields input').focus();
$('#search-form').on('submit', function() {
$('#search-fields').hide();
$('#search-button').show();
});
$('#search-fields input').on('blur', function() {
@@ -22,16 +23,17 @@
});
var loggedInMenu = $('#logged-in-menu'),
isLoggedIn = data.uid > 0;
isLoggedIn = data.uid > 0,
allowGuestSearching = (data.config || {}).allowGuestSearching === '1';
if (isLoggedIn) {
jQuery('.nodebb-loggedin').show();
jQuery('.nodebb-loggedout').hide();
$('.nodebb-loggedin').show();
$('.nodebb-loggedout').hide();
$('#logged-out-menu').addClass('hide');
$('#logged-in-menu').removeClass('hide');
$('#search-button').show();
$('#search-button').removeClass("hide").show();
var userLabel = loggedInMenu.find('#user_label');
@@ -46,10 +48,14 @@
$('#logout-link').on('click', app.logout);
}
} else {
$('#search-button').hide();
if (allowGuestSearching) {
$('#search-button').removeClass("hide").show();
} else {
$('#search-button').addClass("hide").hide();
}
jQuery('.nodebb-loggedin').hide();
jQuery('.nodebb-loggedout').show();
$('.nodebb-loggedin').hide();
$('.nodebb-loggedout').show();
$('#logged-out-menu').removeClass('hide');
$('#logged-in-menu').addClass('hide');
@@ -66,7 +72,8 @@
var notifContainer = document.getElementsByClassName('notifications')[0],
notifTrigger = notifContainer.querySelector('a'),
notifList = document.getElementById('notif-list'),
notifIcon = document.querySelector('.notifications a i');
notifIcon = $('.notifications a');
notifTrigger.addEventListener('click', function(e) {
e.preventDefault();
if (notifContainer.className.indexOf('open') === -1) {
@@ -77,7 +84,6 @@
numUnread = data.unread.length,
x;
notifList.innerHTML = '';
console.log(data);
if ((data.read.length + data.unread.length) > 0) {
for (x = 0; x < numUnread; x++) {
notifEl.setAttribute('data-nid', data.unread[x].nid);
@@ -105,12 +111,19 @@
notifList.appendChild(notifFrag);
if (data.unread.length > 0) notifIcon.className = 'icon-circle active';
else notifIcon.className = 'icon-circle-blank';
if (data.unread.length > 0) {
notifIcon.toggleClass('active', true);
} else {
notifIcon.toggleClass('active', false);
}
socket.emit('api:notifications.mark_all_read', null, function() {
notifIcon.className = 'icon-circle-blank';
utils.refreshTitle();
notifIcon.toggleClass('active', false);
app.refreshTitle();
// Update favicon + local count
Tinycon.setBubble(0);
localStorage.setItem('notifications:count', 0);
});
});
}
@@ -135,8 +148,29 @@
}
});
var updateNotifCount = function(count) {
// Update notification icon, if necessary
if (count > 0) {
notifIcon.toggleClass('active', true);
} else {
notifIcon.toggleClass('active', false);
}
// Update the favicon + saved local count
Tinycon.setBubble(count);
localStorage.setItem('notifications:count', count);
};
socket.emit('api:notifications.getCount', function(err, count) {
if (!err) {
updateNotifCount(count);
} else {
updateNotifCount(0);
}
});
socket.on('event:new_notification', function() {
document.querySelector('.notifications a i').className = 'icon-circle active';
notifIcon.toggleClass('active', true);
app.alert({
alert_id: 'new_notif',
title: 'New notification',
@@ -144,26 +178,93 @@
type: 'warning',
timeout: 2000
});
utils.refreshTitle();
app.refreshTitle();
if (ajaxify.currentPage === 'notifications') {
ajaxify.refresh();
}
// Update the favicon + local storage
var savedCount = parseInt(localStorage.getItem('notifications:count'),10) || 0;
updateNotifCount(savedCount+1);
});
socket.on('event:notifications.updateCount', function(count) {
updateNotifCount(count);
});
// Chats Dropdown
var chatsToggleEl = $('#chat_dropdown'),
chatsListEl = $('#chat-list'),
chatDropdownEl = chatsToggleEl.parent();
chatsToggleEl.on('click', function() {
if (chatDropdownEl.hasClass('open')) {
return;
}
socket.on('chatMessage', function(data) {
socket.emit('api:chats.list', function(chats) {
var chatsFrag = document.createDocumentFragment(),
chatEl = document.createElement('li'),
numChats = chats.length,
x, userObj;
if (numChats > 0) {
for(x=0;x<numChats;x++) {
userObj = chats[x];
chatEl.setAttribute('data-uid', userObj.uid);
chatEl.innerHTML = '<a href="javascript:app.openChat(\'' + userObj.username + '\', ' + userObj.uid + ');"><img src="' + userObj.picture + '" title="' + userObj.username + '" />' + userObj.username + '</a>';
chatsFrag.appendChild(chatEl.cloneNode(true));
}
} else {
chatEl.innerHTML = '<a href="#">No Recent Chats</a>';
chatsFrag.appendChild(chatEl.cloneNode(true));
}
chatsListEl.empty();
chatsListEl.html(chatsFrag);
});
});
socket.on('event:chats.receive', function(data) {
require(['chat'], function(chat) {
var modal = null;
if (chat.modalExists(data.fromuid)) {
modal = chat.getModal(data.fromuid);
chat.appendChatMessage(modal, data.message, data.timestamp);
if (modal.is(":visible")) {
chat.load(modal.attr('UUID'));
} else {
modal = chat.createModal(data.username, data.fromuid);
chat.toggleNew(modal.attr('UUID'), true);
}
chat.load(modal.attr('UUID'));
if (!modal.is(":visible") || !app.isFocused) {
app.alternatingTitle(data.username + ' has messaged you');
}
} else {
modal = chat.createModal(data.username, data.fromuid);
chat.toggleNew(modal.attr('UUID'), true);
app.alternatingTitle(data.username + ' has messaged you');
}
});
});
require(['mobileMenu'], function(mobileMenu) {
mobileMenu.init();
});
function updateUnreadCount(count) {
var badge = $('#numUnreadBadge');
badge.html(count > 20 ? '20+' : count);
if (count > 0) {
badge
.removeClass('badge-inverse')
.addClass('badge-important');
} else {
badge
.removeClass('badge-important')
.addClass('badge-inverse');
}
}
socket.on('event:unread.updateCount', updateUnreadCount);
socket.emit('api:unread.count', updateUnreadCount);
}());

View File

@@ -2,23 +2,6 @@ define(function() {
var Login = {};
Login.init = function() {
// Alternate Logins
var altLoginEl = document.querySelector('.alt-logins');
altLoginEl.addEventListener('click', function(e) {
var target;
switch (e.target.nodeName) {
case 'LI':
target = e.target;
break;
case 'I':
target = e.target.parentNode;
break;
}
if (target) {
document.location.href = target.getAttribute('data-url');
}
});
$('#login').on('click', function() {
var loginData = {
'username': $('#username').val(),
@@ -26,17 +9,23 @@ define(function() {
'_csrf': $('#csrf-token').val()
};
$('#login').attr('disabled', 'disabled').html('Logging in...');
$('#login-error-notify').hide();
$.ajax({
type: "POST",
url: RELATIVE_PATH + '/login',
data: loginData,
success: function(data, textStatus, jqXHR) {
if (!data.success) {
$('#login-error-notify').show();
$('#login').removeAttr('disabled').html('Login');
} else {
$('#login-error-notify').hide();
if(!app.previousUrl) { app.previousUrl = '/'; }
$('#login').html('Redirecting...');
if(!app.previousUrl) {
app.previousUrl = '/';
}
if(app.previousUrl.indexOf('/reset/') != -1)
window.location.replace(RELATIVE_PATH + "/?loggedin");
@@ -48,6 +37,7 @@ define(function() {
},
error: function(data, textStatus, jqXHR) {
$('#login-error-notify').show();
$('#login').removeAttr('disabled').html('Login');
},
dataType: 'json',
async: true,
@@ -63,6 +53,12 @@ define(function() {
});
document.querySelector('#content input').focus();
if(!config.emailSetup)
$('#reset-link').addClass('hide');
else
$('#reset-link').removeClass('hide');
};
return Login;

View File

@@ -8,7 +8,7 @@ define(function() {
var active = '';
Recent.init = function() {
app.enter_room('recent_posts');
app.enterRoom('recent_posts');
ajaxify.register_events([
'event:new_topic',
@@ -81,16 +81,20 @@ define(function() {
}
Recent.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
$('#category-no-topics').remove();
html = $(html);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
Recent.loadMoreTopics = function() {

View File

@@ -12,7 +12,7 @@ define(function() {
password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify'),
validationError = false,
successIcon = '<i class="icon icon-ok"></i>';
successIcon = '<i class="fa fa-check"></i>';
$('#referrer').val(app.previousUrl);
@@ -41,11 +41,12 @@ define(function() {
if (!utils.isEmailValid(emailEl.val())) {
showError(email_notify, 'Invalid email address.');
} else
} else {
socket.emit('user.email.exists', {
email: emailEl.val()
});
}
}
emailEl.on('blur', function() {
validateEmail();
@@ -134,11 +135,6 @@ define(function() {
}
});
// Alternate Logins
$('.alt-logins li').on('click', function(e) {
document.location.href = $(this).attr('data-url');
});
function validateForm() {
validationError = false;
@@ -151,7 +147,9 @@ define(function() {
}
register.on('click', function(e) {
if (validateForm()) e.preventDefault();
if (validateForm()) {
e.preventDefault();
}
});
};

View File

@@ -1,47 +1,42 @@
define(function() {
var Topic = {};
define(['composer'], function(composer) {
var Topic = {},
infiniteLoaderActive = false,
pagination;
function showBottomPostBar() {
if($('#post-container .post-row').length > 1) {
$('.topic-main-buttons').removeClass('hide').parent().removeClass('hide');
}
}
Topic.init = function() {
var expose_tools = templates.get('expose_tools'),
tid = templates.get('topic_id'),
postListEl = document.getElementById('post-container'),
editBtns = document.querySelectorAll('#post-container .post-buttons .edit, #post-container .post-buttons .edit i'),
thread_state = {
locked: templates.get('locked'),
deleted: templates.get('deleted'),
pinned: templates.get('pinned')
},
topic_name = templates.get('topic_name'),
twitter_url = templates.get('twitter-intent-url'),
facebook_url = templates.get('facebook-share-url'),
google_url = templates.get('google-share-url');
topic_name = templates.get('topic_name');
function fixDeleteStateForPosts() {
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
for (var x = 0, numPosts = postEls.length; x < numPosts; x++) {
if (postEls[x].getAttribute('data-deleted') === '1') {
toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
}
postEls[x].removeAttribute('data-deleted');
}
}
jQuery('document').ready(function() {
app.addCommasToNumbers();
app.enterRoom('topic_' + tid);
var room = 'topic_' + tid,
adminTools = document.getElementById('thread-tools');
app.enter_room(room);
$('.twitter-share').on('click', function () {
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
return false;
});
$('.facebook-share').on('click', function () {
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
return false;
});
$('.google-share').on('click', function () {
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
return false;
});
showBottomPostBar();
// Resetting thread state
if (thread_state.locked === '1') set_locked_state(true);
@@ -50,11 +45,10 @@ define(function() {
if (expose_tools === '1') {
var moveThreadModal = $('#move_thread_modal');
adminTools.style.visibility = 'inherit';
$('.thread-tools').removeClass('hide');
// Add events to the thread tools
$('#delete_thread').on('click', function(e) {
$('.delete_thread').on('click', function(e) {
if (thread_state.deleted !== '1') {
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
if (confirm) {
@@ -73,7 +67,7 @@ define(function() {
return false;
});
$('#lock_thread').on('click', function(e) {
$('.lock_thread').on('click', function(e) {
if (thread_state.locked !== '1') {
socket.emit('api:topic.lock', {
tid: tid
@@ -86,7 +80,7 @@ define(function() {
return false;
});
$('#pin_thread').on('click', function(e) {
$('.pin_thread').on('click', function(e) {
if (thread_state.pinned !== '1') {
socket.emit('api:topic.pin', {
tid: tid
@@ -99,7 +93,7 @@ define(function() {
return false;
});
$('#move_thread').on('click', function(e) {
$('.move_thread').on('click', function(e) {
moveThreadModal.modal('show');
return false;
});
@@ -108,8 +102,7 @@ define(function() {
var loadingEl = document.getElementById('categories-loading');
if (loadingEl) {
socket.once('api:categories.get', function(data) {
console.log(data);
socket.emit('api:categories.get', function(data) {
// Render categories
var categoriesFrag = document.createDocumentFragment(),
categoryEl = document.createElement('li'),
@@ -125,8 +118,10 @@ define(function() {
categoriesEl.className = 'category-list';
for (x = 0; x < numCategories; x++) {
info = data.categories[x];
categoryEl.className = info.blockclass + (info.disabled === '1' ? ' disabled' : '');
categoryEl.innerHTML = '<i class="' + info.icon + '"></i> ' + info.name;
categoryEl.style.background = info.bgColor;
categoryEl.style.color = info.color || '#fff';
categoryEl.className = info.disabled === '1' ? ' disabled' : '';
categoryEl.innerHTML = '<i class="fa ' + info.icon + '"></i> ' + info.name;
categoryEl.setAttribute('data-cid', info.cid);
categoriesFrag.appendChild(categoryEl.cloneNode(true));
}
@@ -148,7 +143,7 @@ define(function() {
commitEl.disabled = true;
$(cancelEl).fadeOut(250);
$(moveThreadModal).find('.modal-header button').fadeOut(250);
commitEl.innerHTML = 'Moving <i class="icon-spin icon-refresh"></i>';
commitEl.innerHTML = 'Moving <i class="fa-spin fa-refresh"></i>';
socket.once('api:topic.move', function(data) {
moveThreadModal.modal('hide');
@@ -177,20 +172,15 @@ define(function() {
}
});
});
socket.emit('api:categories.get');
}
});
}
// Fix delete state for this thread's posts
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
for (var x = 0, numPosts = postEls.length; x < numPosts; x++) {
if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
postEls[x].removeAttribute('data-deleted');
}
fixDeleteStateForPosts();
// Follow Thread State
var followEl = $('.main-post .follow'),
var followEl = $('.posts .follow'),
set_follow_state = function(state, quiet) {
if (state && !followEl.hasClass('btn-success')) {
followEl.addClass('btn-success');
@@ -246,7 +236,7 @@ define(function() {
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
if(bookmark) {
app.scrollToPost(parseInt(bookmark, 10));
Topic.scrollToPost(parseInt(bookmark, 10));
}
$('#post-container').on('click', '.deleted', function(ev) {
@@ -258,43 +248,45 @@ define(function() {
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
app.loadMorePosts(tid);
if ($(window).scrollTop() > bottom && !infiniteLoaderActive && $('#post-container').children().length) {
loadMorePosts(tid, function(posts) {
fixDeleteStateForPosts();
});
}
});
}
var reply_fn = function() {
$('.topic').on('click', '.post_reply', function() {
var selectionText = '',
selection = window.getSelection() || document.getSelection();
if ($(selection.baseNode).parents('.post-content').length > 0) {
var snippet = selection.toString();
if (snippet.length > 0) selectionText = '> ' + snippet.replace(/\n/g, '\n> ');
if (snippet.length > 0) {
selectionText = '> ' + snippet.replace(/\n/g, '\n> ');
}
}
var username = '',
post = $(this).parents('li[data-pid]');
if(post.length) {
username = '@' + post.attr('data-username') + ' ';
}
if (thread_state.locked !== '1') {
require(['composer'], function(cmp) {
cmp.push(tid, null, null, selectionText.length > 0 ? selectionText + '\n\n' : '');
});
composer.newReply(tid, topic_name, selectionText.length > 0 ? selectionText + '\n\n' + username : '' + username);
}
};
$('#post-container').on('click', '.post_reply', reply_fn);
$('#post_reply').on('click', reply_fn);
});
$('#post-container').on('click', '.quote', function() {
if (thread_state.locked !== '1') {
var pid = $(this).parents('li').attr('data-pid');
socket.once('api:posts.getRawPost', function(data) {
socket.emit('api:posts.getRawPost', {pid: pid}, function(data) {
quoted = '> ' + data.post.replace(/\n/g, '\n> ') + '\n\n';
require(['composer'], function(cmp) {
cmp.push(tid, null, null, quoted);
});
});
socket.emit('api:posts.getRawPost', {
pid: pid
composer.newReply(tid, topic_name, quoted);
});
}
});
@@ -303,16 +295,15 @@ define(function() {
var pid = $(this).parents('li').attr('data-pid');
var uid = $(this).parents('li').attr('data-uid');
var element = $(this).find('i');
if (element.attr('class') == 'icon-star-empty') {
if ($(this).attr('data-favourited') == 'false') {
socket.emit('api:posts.favourite', {
pid: pid,
room_id: app.current_room
room_id: app.currentRoom
});
} else {
socket.emit('api:posts.unfavourite', {
pid: pid,
room_id: app.current_room
room_id: app.currentRoom
});
}
});
@@ -325,13 +316,28 @@ define(function() {
});
});
$('#post-container').delegate('.edit', 'click', function(e) {
var pid = $(this).parents('li').attr('data-pid'),
main = $(this).parents('.main-post');
require(['composer'], function(cmp) {
cmp.push(null, null, pid);
$('#post-container').on('click', '.twitter-share', function () {
var pid = $(this).parents('li').attr('data-pid');
window.open('https://twitter.com/intent/tweet?url=' + encodeURIComponent(window.location.href + '#' + pid) + '&text=' + topic_name, '_blank', 'width=550,height=420,scrollbars=no,status=no');
return false;
});
$('#post-container').on('click', '.facebook-share', function () {
var pid = $(this).parents('li').attr('data-pid');
window.open('https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(window.location.href + '#' + pid), '_blank', 'width=626,height=436,scrollbars=no,status=no');
return false;
});
$('#post-container').on('click', '.google-share', function () {
var pid = $(this).parents('li').attr('data-pid');
window.open('https://plus.google.com/share?url=' + encodeURIComponent(window.location.href + '#' + pid), '_blank', 'width=500,height=570,scrollbars=no,status=no');
return false;
});
$('#post-container').delegate('.edit', 'click', function(e) {
var pid = $(this).parents('li').attr('data-pid');
composer.editPost(pid);
});
$('#post-container').delegate('.delete', 'click', function(e) {
@@ -341,13 +347,25 @@ define(function() {
confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?');
if (confirmDel) {
deleteAction ?
if(deleteAction) {
socket.emit('api:posts.delete', {
pid: pid
}) :
socket.emit('api:posts.restore', {
pid: pid
pid: pid,
tid: tid
}, function(err) {
if(err) {
return app.alertError('Can\'t delete post!');
}
});
} else {
socket.emit('api:posts.restore', {
pid: pid,
tid: tid
}, function(err) {
if(err) {
return app.alertError('Can\'t restore post!');
}
});
}
}
});
@@ -355,9 +373,6 @@ define(function() {
var username = $(this).parents('li.row').attr('data-username');
var touid = $(this).parents('li.row').attr('data-uid');
if (username === app.username || !app.username)
return;
app.openChat(username, touid);
});
@@ -381,12 +396,15 @@ define(function() {
var userLink = $('<a href="/user/' + userslug + '"></a>').append(userIcon);
userLink.attr('data-uid', uid);
var div = $('<div class="inline-block"></div>');
div.append(userLink);
userLink.tooltip({
placement: 'left',
placement: 'top',
title: username
});
return userLink;
return div;
}
}
@@ -428,7 +446,7 @@ define(function() {
activeEl.find('.anonymous-box').remove();
if(anonymousCount || remainingUsers) {
var anonLink = $('<i class="icon-user anonymous-box"></i>');
var anonLink = $('<div class="anonymous-box inline-block"><i class="fa fa-user"></i></div>');
activeEl.append(anonLink);
var title = '';
@@ -440,12 +458,12 @@ define(function() {
title = anonymousCount + ' guest(s)';
anonLink.tooltip({
placement: 'left',
placement: 'top',
title: title
});
}
}
app.populate_online_users();
app.populateOnlineUsers();
});
socket.on('event:rep_up', function(data) {
@@ -456,7 +474,21 @@ define(function() {
adjust_rep(-1, data.pid, data.uid);
});
socket.on('event:new_post', app.createNewPosts);
socket.on('event:new_post', function(data) {
var posts = data.posts;
for (var p in posts) {
if (posts.hasOwnProperty(p)) {
var post = posts[p],
postcount = jQuery('.user_postcount_' + post.uid),
ptotal = parseInt(postcount.html(), 10);
ptotal += 1;
postcount.html(ptotal);
}
}
createNewPosts(data);
});
socket.on('event:topic_deleted', function(data) {
if (data.tid === tid && data.status === 'ok') {
@@ -521,30 +553,36 @@ define(function() {
socket.on('api:posts.favourite', function(data) {
if (data.status === 'ok' && data.pid) {
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
if (favEl) {
favEl.className = 'icon-star';
$(favEl).parent().addClass('btn-warning');
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
if(favBtn.length) {
favBtn.addClass('btn-warning')
.attr('data-favourited', true)
.find('i').attr('class', 'fa fa-star');
}
}
});
socket.on('api:posts.unfavourite', function(data) {
if (data.status === 'ok' && data.pid) {
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
if (favEl) {
favEl.className = 'icon-star-empty';
$(favEl).parent().removeClass('btn-warning');
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
if(favBtn.length) {
favBtn.removeClass('btn-warning')
.attr('data-favourited', false)
.find('i').attr('class', 'fa fa-star-o');
}
}
});
socket.on('event:post_deleted', function(data) {
if (data.pid) toggle_post_delete_state(data.pid, true);
if (data.pid) {
toggle_post_delete_state(data.pid);
}
});
socket.on('event:post_restored', function(data) {
if (data.pid) toggle_post_delete_state(data.pid, true);
if (data.pid) {
toggle_post_delete_state(data.pid);
}
});
socket.on('api:post.privileges', function(privileges) {
@@ -566,21 +604,21 @@ define(function() {
}
function set_locked_state(locked, alert) {
var threadReplyBtn = document.getElementById('post_reply'),
var threadReplyBtn = $('.topic-main-buttons .post_reply'),
postReplyBtns = document.querySelectorAll('#post-container .post_reply'),
quoteBtns = document.querySelectorAll('#post-container .quote'),
editBtns = document.querySelectorAll('#post-container .edit'),
deleteBtns = document.querySelectorAll('#post-container .delete'),
numPosts = document.querySelectorAll('#post_container li[data-pid]').length,
lockThreadEl = document.getElementById('lock_thread'),
lockThreadEl = $('.lock_thread'),
x;
if (locked === true) {
lockThreadEl.innerHTML = '<i class="icon-unlock"></i> Unlock Thread';
threadReplyBtn.disabled = true;
threadReplyBtn.innerHTML = 'Locked <i class="icon-lock"></i>';
lockThreadEl.html('<i class="fa fa-unlock"></i> Unlock Thread');
threadReplyBtn.attr('disabled', true);
threadReplyBtn.html('Locked <i class="fa fa-lock"></i>');
for (x = 0; x < numPosts; x++) {
postReplyBtns[x].innerHTML = 'Locked <i class="icon-lock"></i>';
postReplyBtns[x].innerHTML = 'Locked <i class="fa fa-lock"></i>';
quoteBtns[x].style.display = 'none';
editBtns[x].style.display = 'none';
deleteBtns[x].style.display = 'none';
@@ -598,11 +636,11 @@ define(function() {
thread_state.locked = '1';
} else {
lockThreadEl.innerHTML = '<i class="icon-lock"></i> Lock Thread';
threadReplyBtn.disabled = false;
threadReplyBtn.innerHTML = 'Reply';
lockThreadEl.html('<i class="fa fa-lock"></i> Lock Thread');
threadReplyBtn.attr('disabled', false);
threadReplyBtn.html('Reply');
for (x = 0; x < numPosts; x++) {
postReplyBtns[x].innerHTML = 'Reply <i class="icon-reply"></i>';
postReplyBtns[x].innerHTML = 'Reply <i class="fa fa-reply"></i>';
quoteBtns[x].style.display = 'inline-block';
editBtns[x].style.display = 'inline-block';
deleteBtns[x].style.display = 'inline-block';
@@ -623,13 +661,14 @@ define(function() {
}
function set_delete_state(deleted) {
var deleteThreadEl = document.getElementById('delete_thread'),
deleteTextEl = deleteThreadEl.getElementsByTagName('span')[0],
var deleteThreadEl = $('.delete_thread'),
deleteTextEl = $('.delete_thread span'),
//deleteThreadEl.getElementsByTagName('span')[0],
threadEl = $('#post-container'),
deleteNotice = document.getElementById('thread-deleted') || document.createElement('div');
if (deleted) {
deleteTextEl.innerHTML = '<i class="icon-comment"></i> Restore Thread';
deleteTextEl.html('<i class="fa fa-comment"></i> Restore Thread');
threadEl.addClass('deleted');
// Spawn a 'deleted' notice at the top of the page
@@ -640,7 +679,7 @@ define(function() {
thread_state.deleted = '1';
} else {
deleteTextEl.innerHTML = '<i class="icon-trash"></i> Delete Thread';
deleteTextEl.html('<i class="fa fa-trash-o"></i> Delete Thread');
threadEl.removeClass('deleted');
deleteNotice.parentNode.removeChild(deleteNotice);
@@ -649,10 +688,10 @@ define(function() {
}
function set_pinned_state(pinned, alert) {
var pinEl = document.getElementById('pin_thread');
var pinEl = $('.pin_thread');
if (pinned) {
pinEl.innerHTML = '<i class="icon-pushpin"></i> Unpin Thread';
pinEl.html('<i class="fa fa-thumb-tack"></i> Unpin Thread');
if (alert) {
app.alert({
'alert_id': 'thread_pin',
@@ -665,7 +704,7 @@ define(function() {
thread_state.pinned = '1';
} else {
pinEl.innerHTML = '<i class="icon-pushpin"></i> Pin Thread';
pinEl.html('<i class="fa fa-thumb-tack"></i> Pin Thread');
if (alert) {
app.alert({
'alert_id': 'thread_pin',
@@ -702,6 +741,7 @@ define(function() {
} else {
postEl.toggleClass('none');
}
updatePostCount();
});
socket.emit('api:post.privileges', pid);
}
@@ -740,8 +780,12 @@ define(function() {
var postAuthorImage, mobileAuthorOverlay, pagination;
var postcount = templates.get('postcount');
Topic.postCount = templates.get('postcount');
window.onscroll = updateHeader;
window.onload = updateHeader;
};
function updateHeader() {
if (pagination == null) {
@@ -752,30 +796,29 @@ define(function() {
app.scrollToBottom();
});
}
jQuery('.mobile-author-overlay').css('bottom', '0px');
postAuthorImage = postAuthorImage || document.getElementById('mobile-author-image');
mobileAuthorOverlay = mobileAuthorOverlay || document.getElementById('mobile-author-overlay');
pagination = pagination || document.getElementById('pagination');
pagination.parentNode.style.display = 'block';
var windowHeight = jQuery(window).height();
var scrollTop = jQuery(window).scrollTop();
var scrollBottom = scrollTop + windowHeight;
var progressBar = $('.progress-bar');
var progressBarContainer = $('.progress-container');
var tid = templates.get('topic_id');
if (scrollTop < 50 && postcount > 1) {
pagination.parentNode.style.display = 'block';
progressBarContainer.css('display', '');
if (scrollTop < jQuery('.posts > .post-row:first-child').height() && Topic.postCount > 1) {
localStorage.removeItem("topic:" + tid + ":bookmark");
postAuthorImage.src = (jQuery('.main-post .avatar img').attr('src'));
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery('.main-post').attr('data-username') + ', ' + jQuery('.main-post').find('.relativeTimeAgo').html();
pagination.innerHTML = '0 out of ' + postcount;
pagination.innerHTML = '1 out of ' + Topic.postCount;
progressBar.width(0);
return;
}
var count = 0, smallestNonNegative = 0;
jQuery('.sub-posts').each(function() {
jQuery('.posts > .post-row:not(".deleted")').each(function() {
count++;
this.postnumber = count;
@@ -794,22 +837,158 @@ define(function() {
smallestNonNegative = Number.MAX_VALUE;
}
pagination.innerHTML = this.postnumber + ' out of ' + postcount;
postAuthorImage.src = (jQuery(this).find('.profile-image-block img').attr('src'));
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery(this).attr('data-username') + ', ' + jQuery(this).find('.relativeTimeAgo').html();
pagination.innerHTML = (this.postnumber-1) + ' out of ' + Topic.postCount;
progressBar.width(((this.postnumber-1) / Topic.postCount * 100) + '%');
}
});
setTimeout(function() {
if (scrollTop + windowHeight == jQuery(document).height()) {
pagination.innerHTML = postcount + ' out of ' + postcount;
pagination.innerHTML = Topic.postCount + ' out of ' + Topic.postCount;
progressBar.width('100%');
}
}, 100);
}
window.onscroll = updateHeader;
window.onload = updateHeader;
};
Topic.scrollToPost = function(pid) {
if (!pid) {
return;
}
var container = $(document.body),
scrollTo = $('#post_anchor_' + pid),
tid = $('#post-container').attr('data-tid');
function animateScroll() {
$('body,html').animate({
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
}, 400);
}
if (!scrollTo.length && tid) {
var intervalID = setInterval(function () {
loadMorePosts(tid, function (posts) {
scrollTo = $('#post_anchor_' + pid);
if (tid && scrollTo.length) {
animateScroll();
}
if (!posts.length || scrollTo.length)
clearInterval(intervalID);
});
}, 100);
} else if (tid) {
animateScroll();
}
}
function createNewPosts(data, infiniteLoaded) {
if(!data || (data.posts && !data.posts.length)) {
return;
}
function removeAlreadyAddedPosts() {
data.posts = data.posts.filter(function(post) {
return $('#post-container li[data-pid="' + post.pid +'"]').length === 0;
});
}
function findInsertionPoint() {
var after = null,
firstPid = data.posts[0].pid;
$('#post-container li[data-pid]').each(function() {
if(parseInt(firstPid, 10) > parseInt($(this).attr('data-pid'), 10)) {
after = $(this);
if(after.next().length && after.next().hasClass('post-bar')) {
after = after.next();
}
} else {
return false;
}
});
return after;
}
removeAlreadyAddedPosts();
if(!data.posts.length) {
return;
}
var insertAfter = findInsertionPoint();
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
var regexp = new RegExp("<!--[\\s]*IF @first[\\s]*-->([\\s\\S]*?)<!--[\\s]*ENDIF @first[\\s]*-->", 'g');
html = html.replace(regexp, '');
translator.translate(html, function(translatedHTML) {
var translated = $(translatedHTML);
if(!infiniteLoaded) {
translated.removeClass('infiniteloaded');
}
translated.insertAfter(insertAfter)
.hide()
.fadeIn('slow');
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
socket.emit('api:post.privileges', data.posts[x].pid);
}
infiniteLoaderActive = false;
app.populateOnlineUsers();
app.addCommasToNumbers();
$('span.timeago').timeago();
$('.post-content img').addClass('img-responsive');
updatePostCount();
showBottomPostBar();
});
}
function updatePostCount() {
socket.emit('api:topics.postcount', templates.get('topic_id'), function(err, postcount) {
if(!err) {
Topic.postCount = postcount;
$('#topic-post-count').html(Topic.postCount);
updateHeader();
}
})
}
function loadMorePosts(tid, callback) {
var indicatorEl = $('.loading-indicator');
if (infiniteLoaderActive) {
return;
}
infiniteLoaderActive = true;
if (indicatorEl.attr('done') === '0') {
indicatorEl.fadeIn();
}
socket.emit('api:topic.loadMore', {
tid: tid,
after: parseInt($('#post-container .post-row.infiniteloaded').last().attr('data-index'), 10) + 1
}, function (data) {
infiniteLoaderActive = false;
if (data.posts.length) {
indicatorEl.attr('done', '0');
createNewPosts(data, true);
} else {
indicatorEl.attr('done', '1');
}
indicatorEl.fadeOut();
if (callback) {
callback(data.posts);
}
});
}
return Topic;
});

View File

@@ -1,10 +1,9 @@
define(function() {
var Unread = {};
var Unread = {},
loadingMoreTopics = false;
Unread.init = function() {
var loadingMoreTopics = false;
app.enter_room('recent_posts');
app.enterRoom('recent_posts');
ajaxify.register_events([
'event:new_topic',
@@ -72,16 +71,20 @@ define(function() {
});
function onTopicsLoaded(topics) {
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
$('#category-no-topics').remove();
html = $(translatedHTML);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
function loadMoreTopics() {
@@ -109,8 +112,9 @@ define(function() {
});
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20)
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20) {
$('#load-more-btn').show();
}
$('#load-more-btn').on('click', function() {
loadMoreTopics();

View File

@@ -36,7 +36,7 @@ define(function() {
var username = $('#search-user').val();
if (username == '') {
jQuery('#user-notfound-notify').html('<i class="icon icon-circle-blank"></i>');
jQuery('#user-notfound-notify').html('<i class="fa fa-circle-o"></i>');
jQuery('#user-notfound-notify').parent().removeClass('btn-warning label-warning btn-success label-success');
return;
}
@@ -44,7 +44,7 @@ define(function() {
if (lastSearch === username) return;
lastSearch = username;
jQuery('#user-notfound-notify').html('<i class="icon-spinner icon-spin"></i>');
jQuery('#user-notfound-notify').html('<i class="fa fa-spinner fa-spin"></i>');
setTimeout(function() {
socket.emit('api:admin.user.search', username);

View File

@@ -67,7 +67,8 @@ define(['taskbar'], function(taskbar) {
chatModal.find('.close').on('click', function(e) {
clearInterval(chatModal.intervalId);
chatModal.intervalId = 0;
chatModal.hide();
chatModal.remove();
chatModal.data('modal', null);
taskbar.discard('chat', uuid);
});
@@ -81,7 +82,11 @@ define(['taskbar'], function(taskbar) {
checkOnlineStatus(chatModal);
});
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with ' + username});
taskbar.push('chat', chatModal.attr('UUID'), {
title:'<i class="fa fa-comment"></i> ' + username,
state: ''
});
return chatModal;
}
@@ -97,6 +102,8 @@ define(['taskbar'], function(taskbar) {
chatModal.show();
module.bringModalToTop(chatModal);
checkOnlineStatus(chatModal);
taskbar.updateActive(uuid);
chatModal.find('#chat-message-input').focus();
}
module.minimize = function(uuid) {
@@ -108,7 +115,7 @@ define(['taskbar'], function(taskbar) {
}
function getChatMessages(chatModal, callback) {
socket.emit('getChatMessages', {touid:chatModal.touid}, function(messages) {
socket.emit('api:chats.get', {touid:chatModal.touid}, function(messages) {
for(var i = 0; i<messages.length; ++i) {
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
}
@@ -135,7 +142,7 @@ define(['taskbar'], function(taskbar) {
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
if(msg.length) {
msg = msg +'\n';
socket.emit('sendChatMessage', { touid:chatModal.touid, message:msg});
socket.emit('api:chats.send', { touid:chatModal.touid, message:msg});
chatModal.find('#chat-message-input').val('');
}
}
@@ -149,7 +156,11 @@ define(['taskbar'], function(taskbar) {
chatContent.scrollTop(
chatContent[0].scrollHeight - chatContent.height()
);
}
};
module.toggleNew = function(uuid, state) {
taskbar.toggleNew(uuid, state);
};
return module;
});

View File

@@ -1,76 +1,448 @@
define(['taskbar'], function(taskbar) {
var composer = {
initialized: false,
active: undefined,
taskbar: taskbar,
posts: {},
postContainer: undefined,
posts: {}
};
var uploadsInProgress = [];
function allowed() {
if(!(parseInt(app.uid, 10) > 0 || parseInt(config.allowGuestPosting, 10) === 1)) {
app.alert({
type: 'danger',
timeout: 5000,
alert_id: 'post_error',
title: 'Please Log In to Post',
message: 'Posting is currently restricted to registered members only, click here to log in',
clickfn: function() {
ajaxify.go('login');
}
});
return false;
}
return true;
}
function createImagePlaceholder(img) {
var text = $('.post-window textarea').val(),
textarea = $('.post-window textarea'),
imgText = "!["+img.name+"](uploading...)";
composer.newTopic = function(cid) {
if(allowed()) {
push({
cid: cid,
title: '',
body: '',
modified: false
});
}
}
text += imgText;
textarea.val(text + " ");
uploadsInProgress.push(1);
socket.emit("api:posts.uploadImage", img, function(err, data) {
composer.newReply = function(tid, title, text) {
if(allowed()) {
push({
tid: tid,
title: title,
body: text,
modified: false
});
}
}
var currentText = textarea.val();
imgText = "!["+data.name+"](uploading...)";
composer.editPost = function(pid) {
if(allowed()) {
socket.emit('api:composer.push', {
pid: pid
}, function(threadData) {
console.log(threadData);
push({
pid: pid,
title: threadData.title,
body: threadData.body,
modified: false
});
});
}
}
if(!err)
textarea.val(currentText.replace(imgText, "!["+data.name+"]("+data.url+")"));
else
textarea.val(currentText.replace(imgText, "!["+data.name+"](upload error)"));
uploadsInProgress.pop();
function push(post) {
var uuid = utils.generateUUID();
taskbar.push('composer', uuid, {
title: post.title ? post.title : 'New Topic',
icon: post.picture
});
composer.posts[uuid] = post;
composer.load(uuid);
}
composer.load = function(post_uuid) {
if($('#cmp-uuid-' + post_uuid).length) {
composer.activateReposition(post_uuid);
} else {
composer.createNewComposer(post_uuid);
}
}
composer.createNewComposer = function(post_uuid) {
templates.preload_template('composer', function() {
var composerTemplate = templates['composer'].parse({});
composerTemplate = $(composerTemplate);
composerTemplate.attr('id', 'cmp-uuid-' + post_uuid);
$(document.body).append(composerTemplate);
composer.activateReposition(post_uuid);
var postContainer = $(composerTemplate[0]);
if(config.imgurClientIDSet) {
initializeFileReader(post_uuid);
}
var postData = composer.posts[post_uuid],
titleEl = postContainer.find('.title'),
bodyEl = postContainer.find('textarea');
if (parseInt(postData.tid) > 0) {
titleEl.val('Replying to: ' + postData.title);
titleEl.prop('readOnly', true);
} else if (parseInt(postData.pid) > 0) {
titleEl.val(postData.title);
titleEl.prop('readOnly', true);
socket.emit('api:composer.editCheck', postData.pid, function(editCheck) {
if (editCheck.titleEditable) {
postContainer.find('input').prop('readonly', false);
}
});
} else {
titleEl.val(postData.title);
titleEl.prop('readOnly', false);
}
bodyEl.val(postData.body);
postContainer.on('change', 'input, textarea', function() {
composer.posts[post_uuid].modified = true;
});
postContainer.on('click', '.action-bar button', function() {
var action = $(this).attr('data-action');
switch(action) {
case 'post':
composer.post(post_uuid);
break;
case 'discard':
if (composer.posts[post_uuid].modified) {
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
if (discard) {
composer.discard(post_uuid);
}
});
} else {
composer.discard(post_uuid);
}
break;
}
});
postContainer.on('click', '.formatting-bar span', function() {
var postContentEl = postContainer.find('textarea'),
iconClass = $(this).find('i').attr('class'),
cursorEnd = postContentEl.val().length,
selectionStart = postContentEl[0].selectionStart,
selectionEnd = postContentEl[0].selectionEnd,
selectionLength = selectionEnd - selectionStart;
function insertIntoInput(element, value) {
var start = postContentEl[0].selectionStart;
element.val(element.val().slice(0, start) + value + element.val().slice(start, element.val().length));
postContentEl[0].selectionStart = postContentEl[0].selectionEnd = start + value.length;
}
switch(iconClass) {
case 'fa fa-bold':
if (selectionStart === selectionEnd) {
// Nothing selected
insertIntoInput(postContentEl, "**bolded text**");
} else {
// Text selected
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '**' + postContentEl.val().slice(selectionStart, selectionEnd) + '**' + postContentEl.val().slice(selectionEnd));
postContentEl[0].selectionStart = selectionStart + 2;
postContentEl[0].selectionEnd = selectionEnd + 2;
}
break;
case 'fa fa-italic':
if (selectionStart === selectionEnd) {
// Nothing selected
insertIntoInput(postContentEl, "*italicised text*");
} else {
// Text selected
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '*' + postContentEl.val().slice(selectionStart, selectionEnd) + '*' + postContentEl.val().slice(selectionEnd));
postContentEl[0].selectionStart = selectionStart + 1;
postContentEl[0].selectionEnd = selectionEnd + 1;
}
break;
case 'fa fa-list':
// Nothing selected
insertIntoInput(postContentEl, "\n\n* list item");
break;
case 'fa fa-link':
if (selectionStart === selectionEnd) {
// Nothing selected
insertIntoInput(postContentEl, "[link text](link url)");
} else {
// Text selected
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '[' + postContentEl.val().slice(selectionStart, selectionEnd) + '](link url)' + postContentEl.val().slice(selectionEnd));
postContentEl[0].selectionStart = selectionStart + selectionLength + 3;
postContentEl[0].selectionEnd = selectionEnd + 11;
}
break;
}
});
postContainer.on('click', '.formatting-bar span .fa-picture-o', function() {
$('#files').click();
});
$('#files').on('change', function(e) {
var files = e.target.files;
if(files) {
for (var i=0; i<files.length; i++) {
loadFile(post_uuid, files[i]);
}
}
});
var resizeActive = false,
resizeCenterX = 0,
resizeOffset = 0,
resizeStart = function(e) {
bodyRect = document.body.getBoundingClientRect();
resizeRect = resizeEl.getBoundingClientRect();
resizeCenterX = resizeRect.left + (resizeRect.width/2);
resizeOffset = resizeCenterX - e.clientX;
resizeSnaps.half = bodyRect.width / 2;
resizeSnaps.none = bodyRect.width;
resizeActive = true;
$(document.body).on('mousemove', resizeAction);
document.body.addEventListener('touchmove', resizeTouchAction);
},
resizeStop = function() {
resizeActive = false;
$(document.body).off('mousemove', resizeAction);
document.body.removeEventListener('touchmove', resizeTouchAction);
},
resizeTouchAction = function(e) {
e.preventDefault();
resizeAction(e.touches[0]);
},
resizeAction = function(e) {
if (resizeActive) {
position = (e.clientX + resizeOffset);
if (Math.abs(position - resizeSnaps.half) <= 15) {
// Half snap
postContainer.css('width', resizeSnaps.half);
resizeSavePosition(resizeSnaps.half);
} else if (Math.abs(position - resizeSnaps.none) <= 30) {
// Minimize snap
postContainer.css('width', bodyRect.width - resizeSnaps.none + 15);
resizeSavePosition(resizeSnaps.none);
} else if (position <= 30) {
// Full snap
postContainer.css('width', bodyRect.width - 15);
resizeSavePosition(bodyRect.width - 15);
} else {
// OH SNAP, NO SNAPS!
postContainer.css('width', bodyRect.width - position);
resizeSavePosition(bodyRect.width - position);
}
}
},
resizeSavePosition = function(px) {
var percentage = px/bodyRect.width;
localStorage.setItem('composer:resizePercentage', percentage);
},
resizeSnaps = {
none: 0,
half: 0,
full: 0
},
resizeRect, bodyRect;
var resizeEl = postContainer.find('.resizer')[0];
resizeEl.addEventListener('mousedown', resizeStart);
resizeEl.addEventListener('mouseup', resizeStop);
resizeEl.addEventListener('touchstart', function(e) {
e.preventDefault();
resizeStart(e.touches[0]);
});
resizeEl.addEventListener('touchend', function(e) {
e.preventDefault();
resizeStop();
});
// .on('mousedown touchstart', resizeStart)
// .on('mouseup touchend', resizeStop)
window.addEventListener('resize', function() {
if (composer.active !== undefined) {
composer.activateReposition(composer.active);
}
});
});
}
function loadFile(file) {
var reader = new FileReader(),
dropDiv = $('.post-window .imagedrop'),
uuid = dropDiv.parents('[data-uuid]').attr('data-uuid');
composer.activateReposition = function(post_uuid) {
$(reader).on('loadend', function(e) {
var bin = this.result;
bin = bin.split(',')[1];
var img = {
name: file.name,
data: bin
};
createImagePlaceholder(img);
dropDiv.hide();
});
reader.readAsDataURL(file);
if(composer.active && composer.active !== post_uuid) {
composer.minimize(composer.active);
}
function initializeFileReader() {
jQuery.event.props.push( "dataTransfer" );
var percentage = localStorage.getItem('composer:resizePercentage'),
bodyRect = document.body.getBoundingClientRect(),
postContainer = $('#cmp-uuid-' + post_uuid);
composer.active = post_uuid;
if (percentage) {
if (bodyRect.width >= 768) {
postContainer.css('width', Math.floor(bodyRect.width * percentage) + 'px');
} else {
postContainer.css('width', '100%');
}
}
if(config.imgurClientIDSet) {
postContainer.find('.upload-instructions').removeClass('hide')
}
postContainer.css('visibility', 'visible');
composer.focusElements(post_uuid);
}
composer.focusElements = function(post_uuid) {
var postContainer = $('#cmp-uuid-' + post_uuid),
postData = composer.posts[post_uuid],
titleEl = postContainer.find('.title'),
bodyEl = postContainer.find('textarea');
if ((parseInt(postData.tid) || parseInt(postData.pid)) > 0) {
bodyEl.focus();
bodyEl.selectionStart = bodyEl.val().length;
bodyEl.selectionEnd = bodyEl.val().length;
} else if (parseInt(postData.cid) > 0) {
titleEl.focus();
}
}
composer.post = function(post_uuid) {
var postData = composer.posts[post_uuid],
postContainer = $('#cmp-uuid-' + post_uuid),
titleEl = postContainer.find('.title'),
bodyEl = postContainer.find('textarea');
titleEl.val(titleEl.val().trim());
bodyEl.val(bodyEl.val().trim());
if(postData.uploadsInProgress && postData.uploadsInProgress.length) {
return app.alert({
type: 'warning',
timeout: 2000,
title: 'Still uploading',
message: "Please wait for uploads to complete.",
alert_id: 'post_error'
});
}
if (titleEl.val().length < config.minimumTitleLength) {
return app.alert({
type: 'danger',
timeout: 2000,
title: 'Title too short',
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
alert_id: 'post_error'
});
}
if (bodyEl.val().length < config.minimumPostLength) {
return app.alert({
type: 'danger',
timeout: 2000,
title: 'Content too short',
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
alert_id: 'post_error'
});
}
// Still here? Let's post.
if (parseInt(postData.cid) > 0) {
socket.emit('api:topics.post', {
'title' : titleEl.val(),
'content' : bodyEl.val(),
'category_id' : postData.cid
});
} else if (parseInt(postData.tid) > 0) {
socket.emit('api:posts.reply', {
'topic_id' : postData.tid,
'content' : bodyEl.val()
});
} else if (parseInt(postData.pid) > 0) {
socket.emit('api:posts.edit', {
pid: postData.pid,
content: bodyEl.val(),
title: titleEl.val()
});
}
composer.discard(post_uuid);
}
composer.discard = function(post_uuid) {
if (composer.posts[post_uuid]) {
$('#cmp-uuid-' + post_uuid).remove();
delete composer.posts[post_uuid];
composer.active = undefined;
taskbar.discard('composer', post_uuid);
}
}
composer.minimize = function(post_uuid) {
var postContainer = $('#cmp-uuid-' + post_uuid);
postContainer.css('visibility', 'hidden');
composer.active = undefined;
taskbar.minimize('composer', post_uuid);
}
function initializeFileReader(post_uuid) {
if(jQuery.event.props.indexOf('dataTransfer') === -1) {
jQuery.event.props.push('dataTransfer');
}
var draggingDocument = false;
if(window.FileReader) {
var drop = $('.post-window .imagedrop'),
textarea = $('.post-window textarea');
var postContainer = $('#cmp-uuid-' + post_uuid),
drop = postContainer.find('.imagedrop'),
textarea = postContainer.find('textarea');
$(document).on('dragstart', function(e) {
$(document).off('dragstart').on('dragstart', function(e) {
draggingDocument = true;
}).on('dragend', function(e) {
}).off('dragend').on('dragend', function(e) {
draggingDocument = false;
});
textarea.on('dragenter', function(e) {
if(draggingDocument)
if(draggingDocument) {
return;
}
drop.css('top', textarea.position().top + 'px');
drop.css('height', textarea.height());
drop.css('line-height', textarea.height() + 'px');
drop.show();
drop.on('dragleave', function(ev) {
@@ -89,321 +461,82 @@ define(['taskbar'], function(taskbar) {
drop.on('drop', function(e) {
e.preventDefault();
var uuid = drop.parents('[data-uuid]').attr('data-uuid'),
dt = e.dataTransfer,
var dt = e.dataTransfer,
files = dt.files;
for (var i=0; i<files.length; i++) {
loadFile(files[i]);
loadFile(post_uuid, files[i]);
}
if(!files.length)
if(!files.length) {
drop.hide();
}
return false;
});
}
}
composer.init = function() {
if (!composer.initialized) {
var taskbar = document.getElementById('taskbar');
function loadFile(post_uuid, file) {
composer.postContainer = document.createElement('div');
composer.postContainer.className = 'post-window row';
composer.postContainer.innerHTML = '<div class="col-md-5">' +
'<input type="text" tabIndex="1" placeholder="Enter your topic title here..." />' +
'<div class="btn-toolbar formatting-bar">' +
'<div class="btn-group">' +
'<span class="btn btn-link" tabindex="-1"><i class="icon-bold"></i></span>' +
'<span class="btn btn-link" tabindex="-1"><i class="icon-italic"></i></span>' +
'<span class="btn btn-link" tabindex="-1"><i class="icon-list"></i></span>' +
'<span class="btn btn-link" tabindex="-1"><i class="icon-link"></i></span>' +
'</div>' +
'</div>' +
'<textarea tabIndex="2"></textarea>' +
'<div class="imagedrop"><div>Drag and Drop Images Here</div></div>'+
'<div class="btn-toolbar action-bar">' +
'<div class="btn-group" style="float: right; margin-right: -8px">' +
'<button data-action="minimize" class="btn hidden-xs" tabIndex="4"><i class="icon-download-alt"></i> Minimize</button>' +
'<button class="btn" data-action="discard" tabIndex="5"><i class="icon-remove"></i> Discard</button>' +
'<button data-action="post" class="btn" tabIndex="3"><i class="icon-ok"></i> Submit</button>' +
'</div>' +
'</div>' +
'</div>';
if (!file.type.match('image.*')) {
return;
}
document.body.insertBefore(composer.postContainer, taskbar);
var reader = new FileReader(),
dropDiv = $('#cmp-uuid-' + post_uuid).find('.imagedrop');
if(config.imgurClientIDSet)
initializeFileReader();
$(reader).on('loadend', function(e) {
var bin = this.result.split(',')[1];
socket.on('api:composer.push', function(threadData) {
if (!threadData.error) {
var uuid = utils.generateUUID();
composer.taskbar.push('composer', uuid, {
title: (!threadData.cid ? (threadData.title || '') : 'New Topic'),
icon: threadData.picture
});
composer.posts[uuid] = {
tid: threadData.tid,
cid: threadData.cid,
pid: threadData.pid,
title: threadData.title || '',
body: threadData.body || '',
modified: false
var img = {
name: file.name,
data: bin
};
composer.load(uuid);
createImagePlaceholder(post_uuid, img);
dropDiv.hide();
});
reader.readAsDataURL(file);
}
function createImagePlaceholder(post_uuid, img) {
var postContainer = $('#cmp-uuid-' + post_uuid),
textarea = postContainer.find('textarea'),
text = textarea.val(),
imgText = "![" + img.name + "](uploading...)";
text += imgText;
textarea.val(text + " ");
if(!composer.posts[post_uuid].uploadsInProgress) {
composer.posts[post_uuid].uploadsInProgress = [];
}
composer.posts[post_uuid].uploadsInProgress.push(1);
socket.emit("api:posts.uploadImage", img, function(err, data) {
if(err) {
return app.alertError(err.message);
}
var currentText = textarea.val();
imgText = "![" + data.name + "](uploading...)";
if(!err) {
textarea.val(currentText.replace(imgText, "![" + data.name + "](" + data.url + ")"));
} else {
app.alert({
type: 'danger',
timeout: 5000,
alert_id: 'post_error',
title: 'Please Log In to Post',
message: 'Posting is currently restricted to registered members only, click here to log in',
clickfn: function() {
ajaxify.go('login');
textarea.val(currentText.replace(imgText, "![" + data.name + "](upload error)"));
}
composer.posts[post_uuid].uploadsInProgress.pop();
});
}
});
socket.on('api:composer.editCheck', function(editCheck) {
if (editCheck.titleEditable === true) composer.postContainer.querySelector('input').readOnly = false;
});
// Post Window events
var jPostContainer = $(composer.postContainer),
postContentEl = composer.postContainer.querySelector('textarea');
jPostContainer.on('change', 'input, textarea', function() {
var uuid = $(this).parents('.post-window')[0].getAttribute('data-uuid');
if (this.nodeName === 'INPUT') composer.posts[uuid].title = this.value;
else if (this.nodeName === 'TEXTAREA') composer.posts[uuid].body = this.value;
// Mark this post window as having been changed
composer.posts[uuid].modified = true;
});
jPostContainer.on('click', '.action-bar button', function() {
var action = this.getAttribute('data-action'),
uuid = $(this).parents('.post-window').attr('data-uuid');
switch(action) {
case 'post': composer.post(uuid); break;
case 'minimize': composer.minimize(uuid); break;
case 'discard':
if (composer.posts[uuid].modified) {
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
if (discard) composer.discard(uuid);
});
} else {
composer.discard(uuid);
}
break;
}
});
jPostContainer.on('click', '.formatting-bar span', function() {
var iconClass = this.querySelector('i').className,
cursorEnd = postContentEl.value.length,
selectionStart = postContentEl.selectionStart,
selectionEnd = postContentEl.selectionEnd,
selectionLength = selectionEnd - selectionStart;
switch(iconClass) {
case 'icon-bold':
if (selectionStart === selectionEnd) {
// Nothing selected
postContentEl.value = postContentEl.value + '**bolded text**';
postContentEl.selectionStart = cursorEnd+2;
postContentEl.selectionEnd = postContentEl.value.length - 2;
} else {
// Text selected
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '**' + postContentEl.value.slice(selectionStart, selectionEnd) + '**' + postContentEl.value.slice(selectionEnd);
postContentEl.selectionStart = selectionStart + 2;
postContentEl.selectionEnd = selectionEnd + 2;
}
break;
case 'icon-italic':
if (selectionStart === selectionEnd) {
// Nothing selected
postContentEl.value = postContentEl.value + '*italicised text*';
postContentEl.selectionStart = cursorEnd+1;
postContentEl.selectionEnd = postContentEl.value.length - 1;
} else {
// Text selected
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '*' + postContentEl.value.slice(selectionStart, selectionEnd) + '*' + postContentEl.value.slice(selectionEnd);
postContentEl.selectionStart = selectionStart + 1;
postContentEl.selectionEnd = selectionEnd + 1;
}
break;
case 'icon-list':
// Nothing selected
postContentEl.value = postContentEl.value + "\n\n* list item";
postContentEl.selectionStart = cursorEnd+4;
postContentEl.selectionEnd = postContentEl.value.length;
break;
case 'icon-link':
if (selectionStart === selectionEnd) {
// Nothing selected
postContentEl.value = postContentEl.value + '[link text](link url)';
postContentEl.selectionStart = cursorEnd+12;
postContentEl.selectionEnd = postContentEl.value.length - 1;
} else {
// Text selected
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '[' + postContentEl.value.slice(selectionStart, selectionEnd) + '](link url)' + postContentEl.value.slice(selectionEnd);
postContentEl.selectionStart = selectionStart + selectionLength + 3;
postContentEl.selectionEnd = selectionEnd + 11;
}
break;
}
});
window.addEventListener('resize', function() {
if (composer.active !== undefined) composer.reposition(composer.active);
});
composer.initialized = true;
}
}
composer.push = function(tid, cid, pid, text) {
socket.emit('api:composer.push', {
tid: tid, // Replying
cid: cid, // Posting
pid: pid, // Editing
body: text // Predefined text
});
}
composer.load = function(post_uuid) {
var post_data = composer.posts[post_uuid],
titleEl = composer.postContainer.querySelector('input'),
bodyEl = composer.postContainer.querySelector('textarea');
composer.reposition(post_uuid);
composer.active = post_uuid;
composer.postContainer.setAttribute('data-uuid', post_uuid);
if (parseInt(post_data.tid) > 0) {
titleEl.value = 'Replying to: ' + post_data.title;
titleEl.readOnly = true;
} else if (parseInt(post_data.pid) > 0) {
titleEl.value = post_data.title;
titleEl.readOnly = true;
socket.emit('api:composer.editCheck', post_data.pid);
} else {
titleEl.value = post_data.title;
titleEl.readOnly = false;
}
bodyEl.value = post_data.body;
// Direct user focus to the correct element
if ((parseInt(post_data.tid) || parseInt(post_data.pid)) > 0) {
bodyEl.focus();
bodyEl.selectionStart = bodyEl.value.length;
bodyEl.selectionEnd = bodyEl.value.length;
} else if (parseInt(post_data.cid) > 0) {
titleEl.focus();
}
}
composer.reposition = function(post_uuid) {
var postWindowEl = composer.postContainer.querySelector('.col-md-5'),
taskbarBtn = document.querySelector('#taskbar [data-uuid="' + post_uuid + '"]'),
btnRect = taskbarBtn.getBoundingClientRect(),
taskbarRect = document.getElementById('taskbar').getBoundingClientRect(),
windowRect, leftPos;
composer.postContainer.style.display = 'block';
windowRect = postWindowEl.getBoundingClientRect();
leftPos = btnRect.left + btnRect.width - windowRect.width;
postWindowEl.style.left = (leftPos > 0 ? leftPos : 0) + 'px';
composer.postContainer.style.bottom = taskbarRect.height + "px";
}
composer.post = function(post_uuid) {
// Check title and post length
var postData = composer.posts[post_uuid],
titleEl = composer.postContainer.querySelector('input'),
bodyEl = composer.postContainer.querySelector('textarea');
titleEl.value = titleEl.value.trim();
bodyEl.value = bodyEl.value.trim();
if(uploadsInProgress.length) {
return app.alert({
type: 'warning',
timeout: 2000,
title: 'Still uploading',
message: "Please wait for uploads to complete.",
alert_id: 'post_error'
});
}
if (titleEl.value.length < config.minimumTitleLength) {
return app.alert({
type: 'danger',
timeout: 2000,
title: 'Title too short',
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
alert_id: 'post_error'
});
}
if (bodyEl.value.length < config.minimumPostLength) {
return app.alert({
type: 'danger',
timeout: 2000,
title: 'Content too short',
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
alert_id: 'post_error'
});
}
// Still here? Let's post.
if (parseInt(postData.cid) > 0) {
socket.emit('api:topics.post', {
'title' : titleEl.value,
'content' : bodyEl.value,
'category_id' : postData.cid
});
} else if (parseInt(postData.tid) > 0) {
socket.emit('api:posts.reply', {
'topic_id' : postData.tid,
'content' : bodyEl.value
});
} else if (parseInt(postData.pid) > 0) {
socket.emit('api:posts.edit', {
pid: postData.pid,
content: bodyEl.value,
title: titleEl.value
});
}
composer.discard(post_uuid);
}
composer.discard = function(post_uuid) {
if (composer.posts[post_uuid]) {
$(composer.postContainer).find('.imagedrop').hide();
delete composer.posts[post_uuid];
uploadsInProgress.length = 0;
composer.minimize();
taskbar.discard('composer', post_uuid);
}
}
composer.minimize = function(uuid) {
composer.postContainer.style.display = 'none';
composer.active = undefined;
taskbar.minimize('composer', uuid);
}
composer.init();
return {
push: composer.push,
newTopic: composer.newTopic,
newReply: composer.newReply,
editPost: composer.editPost,
load: composer.load,
minimize: composer.minimize
};

View File

@@ -1,122 +0,0 @@
define(function() {
var mobileMenu = {};
var categories = null,
overlay = null,
menuBtn = null,
postBtn = null,
initialized = false;
function loadCategories(callback) {
if (categories) {
callback(true);
return;
}
jQuery.getJSON(RELATIVE_PATH+'/api/home', function(data) {
categories = data.categories;
initialized = true;
if (callback) {
callback(true);
}
});
}
function displayCategories() {
var baseIcon = document.createElement('a'),
baseImage = document.createElement('i'),
baseName = document.createElement('span');
baseIcon.className = 'mobile-menu-icon';
for (var i=0, ii=categories.length; i<ii; i++) {
var icon = baseIcon.cloneNode(true),
image = baseImage.cloneNode(true),
name = baseName.cloneNode(true);
var category = categories[i];
image.className = category.icon + ' icon-3x';
name.innerHTML = '<br />' + category.name;
icon.appendChild(image);
icon.appendChild(name);
icon.src = 'category/' + category.slug;
icon.onclick = function() {
jQuery('.mobile-menu-icon').toggleClass('menu-visible');
setTimeout(function() {
jQuery(overlay).toggleClass('menu-visible');
}, 200);
ajaxify.go(this.src);
}
overlay.appendChild(icon);
}
}
function animateIcons() {
jQuery(overlay).toggleClass('menu-visible');
setTimeout(function() {
jQuery('.mobile-menu-icon').toggleClass('menu-visible');
}, 100);
}
mobileMenu.onNavigate = function() {
if (initialized == false) return false;
var cid = templates.get('category_id'),
tid = templates.get('topic_id');
if (cid) {
postBtn.style.display = 'inline-block';
postBtn.onclick = function() {
require(['composer'], function(cmp) {
cmp.push(0, cid);
});
};
postBtn.children[0].className = 'icon-plus icon-2x';
} else if (tid) {
postBtn.style.display = 'inline-block';
postBtn.onclick = function() {
require(['composer'], function(cmp) {
cmp.push(tid);
});
};
postBtn.children[0].className = 'icon-reply icon-2x'
} else {
postBtn.style.display = 'none';
}
};
mobileMenu.init = function() {
return; // disabling until this can be pluginified.
overlay = overlay || document.getElementById('mobile-menu-overlay');
menuBtn = menuBtn || document.getElementById('mobile-menu-btn');
postBtn = postBtn || document.getElementById('mobile-post-btn');
menuBtn.onclick = function() {
animateIcons();
}
loadCategories(function() {
displayCategories();
mobileMenu.onNavigate();
});
}
return {
init: mobileMenu.init,
onNavigate: mobileMenu.onNavigate
}
});

View File

@@ -25,6 +25,8 @@ define(function() {
if (_btn.className.indexOf('active') === -1) {
taskbar.minimizeAll();
module.load(uuid);
taskbar.toggleNew(uuid, false);
app.alternatingTitle('');
// Highlight the button
$(taskbar.tasklist).removeClass('active');
@@ -69,7 +71,7 @@ define(function() {
'</a>';
btnEl.setAttribute('data-module', module);
btnEl.setAttribute('data-uuid', uuid);
btnEl.className = options.state || 'active';
btnEl.className = options.state !== undefined ? options.state : 'active';
if (!options.state || options.state === 'active') taskbar.minimizeAll();
taskbar.tasklist.appendChild(btnEl);
@@ -82,14 +84,27 @@ define(function() {
},
minimizeAll: function() {
$(taskbar.tasklist.querySelectorAll('.active')).removeClass('active');
},
toggleNew: function(uuid, state) {
var btnEl = $(taskbar.tasklist.querySelector('[data-uuid="' + uuid + '"]'));
btnEl.toggleClass('new', state);
},
updateActive: function(uuid) {
var tasks = $(taskbar.tasklist).find('li');
tasks.removeClass('active');
tasks.filter('[data-uuid="' + uuid + '"]').addClass('active');
}
}
if (!taskbar.initialized) taskbar.init();
if (!taskbar.initialized) {
taskbar.init();
}
return {
push: taskbar.push,
discard: taskbar.discard,
minimize: taskbar.minimize
minimize: taskbar.minimize,
toggleNew: taskbar.toggleNew,
updateActive: taskbar.updateActive
}
});

View File

@@ -122,23 +122,17 @@
return '';
}
templates.preload_template = function(tpl_name, callback) {
templates.load_template = function (callback, url, template) {
var location = document.location || window.location,
api_url = (url === '' || url === '/') ? 'home' : url,
tpl_url = templates.get_custom_map(api_url.split('?')[0]),
trimmed = api_url;
if (!tpl_url) {
tpl_url = templates.getTemplateNameFromUrl(api_url);
if(templates[tpl_name]) {
return callback();
}
var template_data = null;
var timestamp = new Date().getTime(); //debug
if (!templates[tpl_url]) {
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_url + '.tpl?v=' + timestamp, function (html) {
// TODO: This should be "load_template", and the current load_template
// should be named something else
// TODO: The "Date.now()" in the line below is only there for development purposes.
// It should be removed at some point.
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_name + '.tpl?v=' + Date.now(), function (html) {
var template = function () {
this.toString = function () {
return this.html;
@@ -149,8 +143,27 @@
template.prototype.html = String(html);
template.prototype.blocks = {};
templates[tpl_url] = new template;
templates[tpl_name] = new template;
callback();
});
}
templates.load_template = function (callback, url, template) {
var location = document.location || window.location,
api_url = (url === '' || url === '/') ? 'home' : url,
tpl_url = templates.get_custom_map(api_url.split('?')[0]);
if (!tpl_url) {
tpl_url = templates.getTemplateNameFromUrl(api_url);
}
var template_data = null;
var timestamp = new Date().getTime(); //debug
if (!templates[tpl_url]) {
templates.preload_template(tpl_url, function() {
parse_template();
});
} else {
@@ -167,11 +180,13 @@
template_data = data;
parse_template();
}).fail(function (data) {
if(data && data.status == 404) {
ajaxify.go('404');
return;
if (data && data.status == 404) {
return ajaxify.go('404');
} else if (data && data.status === 403) {
return ajaxify.go('403');
} else {
app.alertError(data.responseJSON.error);
}
app.alertError("Can't load template data!");
});
function parse_template() {
@@ -235,11 +250,11 @@
}
function makeRegex(block) {
return new RegExp("<!-- BEGIN " + block + " -->[\\s\\S]*<!-- END " + block + " -->", 'g');
return new RegExp("<!--[\\s]*BEGIN " + block + "[\\s]*-->[\\s\\S]*<!--[\\s]*END " + block + "[\\s]*-->", 'g');
}
function makeConditionalRegex(block) {
return new RegExp("<!-- IF " + block + " -->[\\s\\S]*<!-- ENDIF " + block + " -->", 'g');
return new RegExp("<!--[\\s]*IF " + block + "[\\s]*-->([\\s\\S]*?)<!--[\\s]*ENDIF " + block + "[\\s]*-->", 'g');
}
function getBlock(regex, block, template) {
@@ -248,22 +263,12 @@
if (self.blocks && block !== undefined) self.blocks[block] = data[0];
data = data[0]
.replace("<!-- BEGIN " + block + " -->", "")
.replace("<!-- END " + block + " -->", "");
return data;
}
function getConditionalBlock(regex, block, template) {
data = template.match(regex);
if (data == null) return;
if (self.blocks && block !== undefined) self.blocks[block] = data[0];
var begin = new RegExp("(\r\n)*<!-- BEGIN " + block + " -->(\r\n)*", "g"),
end = new RegExp("(\r\n)*<!-- END " + block + " -->(\r\n)*", "g"),
data = data[0]
.replace("<!-- IF " + block + " -->", "")
.replace("<!-- ENDIF " + block + " -->", "");
.replace(begin, "")
.replace(end, "");
return data;
}
@@ -275,7 +280,7 @@
var template = this.html,
regex, block;
return (function parse(data, namespace, template) {
return (function parse(data, namespace, template, blockInfo) {
if (!data || data.length == 0) {
template = '';
}
@@ -302,28 +307,48 @@
result = "";
do {
result += parse(data[d][i], namespace, block);
result += parse(data[d][i], namespace, block, {iterator: i, total: numblocks});
} while (i++ < numblocks);
namespace = namespace.replace(d + '.', '');
template = setBlock(regex, result, template);
} else if (data[d] instanceof Object) {
namespace += d + '.';
regex = makeRegex(d),
block = getBlock(regex, namespace, template)
if (block == null) continue;
block = parse(data[d], namespace, block);
template = setBlock(regex, block, template);
template = parse(data[d], d + '.', template);
} else {
var conditional = makeConditionalRegex(d),
block = getConditionalBlock(conditional, namespace, template);
function checkConditional(key, value) {
var conditional = makeConditionalRegex(key),
matches = template.match(conditional);
if (block && !data[d]) {
template = template.replace(conditional, '');
if (matches !== null) {
for (var i = 0, ii = matches.length; i < ii; i++) {
var conditionalBlock = matches[i].split(/<!-- ELSE -->/);
if (conditionalBlock[1]) {
// there is an else statement
if (!value) {
template = template.replace(matches[i], conditionalBlock[1].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
} else {
template = template.replace(matches[i], conditionalBlock[0].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
}
} else {
// regular if statement
if (!value) {
template = template.replace(matches[i], '');
} else {
template = template.replace(matches[i], matches[i].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
}
}
}
}
}
checkConditional(namespace + d, data[d]);
checkConditional('!' + namespace + d, !data[d]);
if (blockInfo) {
checkConditional('@first', blockInfo.iterator === 0);
checkConditional('@last', blockInfo.iterator === blockInfo.total);
}
template = replace(namespace + d, data[d], template);
}
@@ -333,8 +358,12 @@
if (namespace) {
var regex = new RegExp("{" + namespace + "[\\s\\S]*?}", 'g');
template = template.replace(regex, '');
namespace = '';
}
// clean up all undefined conditionals
template = template.replace(/<!-- IF([^@]*?)ENDIF([^@]*?)-->/gi, '');
return template;
})(data, "", template);

View File

@@ -56,6 +56,10 @@
var now = +new Date(),
difference = now - Math.floor(parseFloat(timestamp));
if(difference < 0) {
difference = 0;
}
difference = Math.floor(difference / 1000);
if (difference < 60) {
@@ -169,53 +173,24 @@
return tags;
},
refreshTitle: function(url) {
if (!url) {
var a = document.createElement('a');
a.href = document.location;
url = a.pathname.slice(1);
}
var notificationIcon;
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
document.title = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
notificationIcon = notificationIcon || document.querySelector('.notifications a i');
if (numNotifications > 0 && notificationIcon) {
notificationIcon.className = 'icon-circle active';
}
});
jQuery.getJSON(RELATIVE_PATH + '/api/unread/total', function(data) {
var badge = jQuery('#numUnreadBadge');
badge.html(data.count > 20 ? '20+' : data.count);
if (data.count > 0) {
badge
.removeClass('badge-inverse')
.addClass('badge-important');
} else {
badge
.removeClass('badge-important')
.addClass('badge-inverse');
}
});
},
isRelativeUrl: function(url) {
var firstChar = url.slice(0, 1);
return (firstChar === '.' || firstChar === '/');
},
makeNumberHumanReadable: function(num) {
num = parseInt(num, 10);
if (num > 999999) {
return (num / 1000000).toFixed(1) + 'm';
}
else if(num > 999) {
return (num / 1000).toFixed(1) + 'k';
}
var n = parseInt(num, 10);
if(!n) {
return num;
}
if (n > 999999) {
return (n / 1000000).toFixed(1) + 'm';
}
else if(n > 999) {
return (n / 1000).toFixed(1) + 'k';
}
return n;
}
};

5
public/templates/500.tpl Normal file
View File

@@ -0,0 +1,5 @@
<div class="alert alert-danger">
<strong>[[global:500.title]]</strong>
<p>[[global:500.message]]</p>
<p>{errorMessage}</p>
</div>

View File

@@ -13,69 +13,92 @@
<img src="{picture}" class="user-profile-picture img-thumbnail"/>
</div>
<div class="account-online-status">
<span><i class="icon-circle-blank"></i> <span>offline</span></span>
<span><i class="fa fa-circle-o"></i> <span>[[user:offline]]</span></span>
</div>
<div class="{show_banned}">
<span class="label label-danger">banned</span>
<!-- IF banned -->
<div>
<span class="label label-danger">[[user:banned]]</span>
</div>
<!-- ENDIF banned -->
<div>
<a id="chat-btn" href="#" class="btn btn-default hide">Chat</a>
</div>
<div id="user-actions">
<a id="follow-btn" href="#" class="btn btn-default">Follow</a>
<a id="unfollow-btn" href="#" class="btn btn-default">Unfollow</a>
<a id="follow-btn" href="#" class="btn btn-default hide">Follow</a>
<a id="unfollow-btn" href="#" class="btn btn-default hide">Unfollow</a>
</div>
</div>
<div class="col-md-4">
<div class="inline-block">
<div class="account-bio-block">
<span class="account-bio-label">email</span><i class="icon-eye-close {emailClass}" title="Email hidden"></i>
<span class="account-bio-label">[[user:email]]</span><i class="fa fa-eye-slash {emailClass}" title="[[user:email_hidden]]"></i>
<!-- IF email -->
<span>{email}</span>
<!-- ELSE -->
<i class="fa fa-eye-slash" title="[[user:email_hidden]]"></i> [[user:hidden]]
<!-- ENDIF email -->
<br/>
<span class="account-bio-label">full name</span>
<!-- IF fullname -->
<span class="account-bio-label">[[user:fullname]]</span>
<span>{fullname}</span>
<br/>
<!-- ENDIF fullname -->
<span class="account-bio-label">website</span>
<span><a href="{website}">{website}</a></span>
<!-- IF website -->
<span class="account-bio-label">[[user:website]]</span>
<span><a href="{website}">{websiteName}</a></span>
<br/>
<!-- ENDIF website -->
<span class="account-bio-label">location</span>
<!-- IF location -->
<span class="account-bio-label">[[user:location]]</span>
<span>{location}</span>
<br/>
<!-- ENDIF location -->
<span class="account-bio-label">age</span>
<!-- IF age -->
<span class="account-bio-label">[[user:age]]</span>
<span>{age}</span>
<br/>
<!-- ENDIF age -->
<hr/>
<span class="account-bio-label">joined</span>
<span class="account-bio-label">[[user:joined]]</span>
<span class="timeago" title="{joindate}"></span>
<br/>
<span class="account-bio-label">profile views</span>
<span class="account-bio-label">[[user:profile_views]]</span>
<span class="formatted-number">{profileviews}</span>
<br/>
<span class="account-bio-label">reputation</span>
<span class="account-bio-label">[[user:reputation]]</span>
<span class="formatted-number">{reputation}</span>
<br/>
<span class="account-bio-label">posts</span>
<span class="account-bio-label">[[user:posts]]</span>
<span class="formatted-number">{postcount}</span>
<br/>
<span class="account-bio-label">followers</span>
<span class="account-bio-label">[[user:followers]]</span>
<span class="formatted-number">{followerCount}</span>
<br/>
<span class="account-bio-label">following</span>
<span class="account-bio-label">[[user:following]]</span>
<span class="formatted-number">{followingCount}</span>
<br/>
<hr/>
<span class="account-bio-label">signature</span>
<!-- IF !disableSignatures -->
<!-- IF signature -->
<span class="account-bio-label">[[user:signature]]</span>
<div class="post-signature">
<span id='signature'>{signature}</span>
</div>
<!-- ENDIF signature -->
<!-- ENDIF !disableSignatures -->
</div>
</div>
</div>

View File

@@ -1,27 +1,26 @@
<div class="well account">
<div class="well">
<div id="change-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Change Picture" aria-hidden="true">
<div id="change-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="[[user:change_picture]]" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Change Picture</h3>
<h3 id="myModalLabel">[[user:change_picture]]</h3>
</div>
<div class="modal-body">
<div id="gravatar-box">
<img id="user-gravatar-picture" src="" class="img-thumbnail user-profile-picture">
<span class="user-picture-label">Gravatar</span>
<i class='icon-ok icon-2x'></i>
<span class="user-picture-label">[[user:gravatar]]</span>
<i class='fa fa-check fa-2x'></i>
</div>
<br/>
<div id="uploaded-box">
<img id="user-uploaded-picture" src="" class="img-thumbnail user-profile-picture">
<span class="user-picture-label">Uploaded picture</span>
<i class='icon-ok icon-2x'></i>
<span class="user-picture-label">[[user:uploaded_picture]]</span>
<i class='fa fa-check fa-2x'></i>
</div>
<a id="uploadPictureBtn" href="#">Upload new picture</a>
<a id="uploadPictureBtn" href="#">[[user:upload_new_picture]]</a>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
@@ -33,8 +32,8 @@
<div class="account-username-box" data-userslug="{userslug}">
<span class="account-username">
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
<a href="/user/{userslug}/edit">edit</a>
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
<a href="/user/{userslug}/edit">[[user:edit]]</a>
</span>
</div>
@@ -42,7 +41,7 @@
<div class="col-md-2" style="text-align: center; margin-bottom:20px;">
<div class="account-picture-block text-center">
<img id="user-current-picture" class="user-profile-picture img-thumbnail" src="{picture}" /><br /><br />
<a id="changePictureBtn" href="#" class="btn btn-primary">change picture</a>
<a id="changePictureBtn" href="#" class="btn btn-primary">[[user:change_picture]]</a>
</div>
</div>
@@ -50,51 +49,53 @@
<div>
<form class='form-horizontal'>
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<label class="control-label" for="inputEmail">[[user:email]]</label>
<div class="controls">
<input class="form-control" type="text" id="inputEmail" placeholder="Email" value="{email}">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputFullname">Full Name</label>
<label class="control-label" for="inputFullname">[[user:fullname]]</label>
<div class="controls">
<input class="form-control" type="text" id="inputFullname" placeholder="Full Name" value="{fullname}">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputWebsite">Website</label>
<label class="control-label" for="inputWebsite">[[user:website]]</label>
<div class="controls">
<input class="form-control" type="text" id="inputWebsite" placeholder="http://website.com" value="{website}">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputLocation">Location</label>
<label class="control-label" for="inputLocation">[[user:location]]</label>
<div class="controls">
<input class="form-control" type="text" id="inputLocation" placeholder="Location" value="{location}">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputBirthday">Birthday</label>
<label class="control-label" for="inputBirthday">[[user:birthday]]</label>
<div class="controls">
<input class="form-control" type="date" id="inputBirthday" placeholder="mm/dd/yyyy" value="{birthday}">
</div>
</div>
<!-- IF !disableSignatures -->
<div class="control-group">
<label class="control-label" for="inputSignature">Signature</label>
<label class="control-label" for="inputSignature">[[user:signature]]</label> <small><label id="signatureCharCountLeft"></label></small>
<div class="controls">
<textarea class="form-control" id="inputSignature" placeholder="max 150 chars" rows="5">{signature}</textarea>
<textarea class="form-control" id="inputSignature" rows="5">{signature}</textarea>
</div>
</div>
<!-- ENDIF !disableSignatures -->
<input type="hidden" id="inputUID" value="{uid}"><br />
<div class="form-actions">
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
<a id="submitBtn" href="#" class="btn btn-primary">[[global:save_changes]]</a>
</div>
</form>
@@ -114,23 +115,27 @@
</div>
<div class="control-group">
<label class="control-label" for="inputNewPassword">Password</label>
<div class="controls">
<label class="control-label" for="inputNewPassword">[[user:password]]</label>
<div class="input-group">
<input class="form-control" type="password" id="inputNewPassword" placeholder="New Password" value="">
<div id="password-notify" class="alert alert-danger hide"></div>
<span class="input-group-addon">
<span id="password-notify"><i class="fa fa-circle-o"></i></span>
</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputNewPasswordAgain">Confirm Password</label>
<div class="controls">
<label class="control-label" for="inputNewPasswordAgain">[[user:confirm_password]]</label>
<div class="input-group">
<input class="form-control" type="password" id="inputNewPasswordAgain" placeholder="Confirm Password" value="">
<div id="password-confirm-notify" class="alert alert-danger hide"></div>
<span class="input-group-addon">
<span id="password-confirm-notify"><i class="fa fa-circle-o"></i></span>
</span>
</div>
</div>
<br/>
<div class="form-actions">
<a id="changePasswordBtn" href="#" class="btn btn-primary">Change Password</a>
<a id="changePasswordBtn" href="#" class="btn btn-primary">[[user:change_password]]</a>
</div>
</form>

View File

@@ -1,10 +1,9 @@
<div class="well">
<div class="well account">
<div class="account-username-box" data-userslug="{userslug}">
<span class="account-username">
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
<a href="/user/{userslug}/settings">settings</a>
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
<a href="/user/{userslug}/settings">[[user:settings]]</a>
</span>
</div>
@@ -13,7 +12,7 @@
<h4>privacy</h4>
<div class="checkbox">
<label>
<input id="showemailCheckBox" type="checkbox" {showemail}> Show my email
<input id="showemailCheckBox" type="checkbox" {showemail}> [[user:show_email]]
</label>
</div>
</div>
@@ -23,6 +22,6 @@
</div>
</div>
<div class="form-actions">
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
<a id="submitBtn" href="#" class="btn btn-primary">[[global:save_changes]]</a>
</div>
</div>

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,6 @@
<!-- IF redis -->
<h1>Redis</h1>
<hr />
<div id="admin-redis-info">
@@ -21,4 +24,29 @@
<span>Keyspace Hits</span> <span class="text-right">{keyspace_hits}</span><br/>
<span>Keyspace Misses</span> <span class="text-right">{keyspace_misses}</span><br/>
</div>
<hr />
<h3>Raw Info </h3>
<div class="highlight">
<pre>{raw}</pre>
</div>
<!-- ENDIF redis -->
<!-- IF mongo -->
<h1>Mongo</h1>
<hr />
<div id="admin-redis-info">
<span>Collections</span> <span class="text-right">{collections}</span><br/>
<span>Objects</span> <span class="text-right">{objects}</span><br/>
<span>Avg. Object Size</span> <span class="text-right">{avgObjSize} kb</span><br/>
<hr/>
<span>Data Size</span> <span class="text-right">{dataSize} kb</span><br/>
<span>Storage Size</span> <span class="text-right">{storageSize} kb</span><br/>
<span>File Size</span> <span class="text-right">{fileSize} kb</span><br/>
</div>
<hr />
<h3>Raw Info </h3>
<div class="highlight">
<pre>{raw}</pre>
</div>
<!-- ENDIF mongo -->

View File

@@ -12,14 +12,14 @@
<p>{groups.description}</p>
<div class="btn-group">
<button class="btn btn-default" data-action="members">Members</button>
<!-- IF groups.deletable -->
<button class="btn btn-danger" data-action="delete">Delete Group</button>
<!-- ENDIF groups.deletable -->
</div>
</div>
<div class="col-lg-4">
<ul class="pull-right members">
<!-- BEGIN members -->
<li data-uid="{groups.members.uid}" title="{groups.members.username}"><img src="{groups.members.picture}" /></li>
<!-- END members -->
<!-- BEGIN members --><li data-uid="{groups.members.uid}" title="{groups.members.username}"><img src="{groups.members.picture}" /></li><!-- END members -->
</ul>
</div>
</div>

View File

@@ -12,6 +12,7 @@
<script type="text/javascript" src="{relative_path}/vendor/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-git.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/qunit/qunit-git.css">
<link rel="stylesheet" type="text/css" href="{relative_path}/vendor/colorpicker/colorpicker.css">
<script type="text/javascript" src="{relative_path}/socket.io/socket.io.js"></script>
<script type="text/javascript" src="{relative_path}/src/app.js"></script>
<script type="text/javascript" src="{relative_path}/src/templates.js"></script>
@@ -21,6 +22,7 @@
<script src="{relative_path}/vendor/jquery/js/jquery.form.js"></script>
<script src="{relative_path}/vendor/requirejs/require.js"></script>
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
<script src="{relative_path}/vendor/colorpicker/colorpicker.js"></script>
<script>
require.config({
@@ -52,13 +54,13 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>
<a href="/admin/index"><i class="icon-home"></i> Home</a>
<a href="/admin/index"><i class="fa fa-home" title="Home"></i></a>
</li>
<li>
<a href="/admin/settings"><i class="icon-cogs"></i> Settings</a>
<a href="/admin/settings"><i class="fa fa-cogs" title="Settings"></i></a>
</li>
<li>
<a href="/" target="_top"><i class="icon-book"></i> Forum</a>
<a href="/" target="_top"><i class="fa fa-book" title="Forum"></i></a>
</li>
<li>
<a href="#" id="reconnect"></a>
@@ -89,31 +91,36 @@
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="col-sm-3">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">NodeBB</li>
<li class='active'>
<a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a>
<a href='{relative_path}/admin/index'><i class='fa fa-home'></i> Home</a>
</li>
<li><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
<li><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
<li><a href="{relative_path}/admin/groups"><i class="icon-group"></i> Groups</a></li>
<li><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
<li><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
<li><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
<li><a href='{relative_path}/admin/settings'><i class='icon-cogs'></i> Settings</a></li>
<li><a href='{relative_path}/admin/redis'><i class='icon-hdd'></i> Redis</a></li>
<li><a href='{relative_path}/admin/logger'><i class='icon-th'></i> Logger</a></li>
<li><a href="{relative_path}/admin/motd"><i class="icon-comment"></i> MOTD</a></li>
<li><a href='{relative_path}/admin/categories/active'><i class='fa fa-folder'></i> Categories</a></li>
<li><a href='{relative_path}/admin/users/latest'><i class='fa fa-user'></i> Users</a></li>
<li><a href="{relative_path}/admin/groups"><i class="fa fa-group"></i> Groups</a></li>
<li><a href='{relative_path}/admin/topics'><i class='fa fa-book'></i> Topics</a></li>
<li><a href='{relative_path}/admin/themes'><i class='fa fa-th'></i> Themes</a></li>
<li><a href='{relative_path}/admin/plugins'><i class='fa fa-code-fork'></i> Plugins</a></li>
<li><a href='{relative_path}/admin/settings'><i class='fa fa-cogs'></i> Settings</a></li>
<li><a href='{relative_path}/admin/database'><i class='fa fa-hdd-o'></i> Database</a></li>
<li><a href='{relative_path}/admin/logger'><i class='fa fa-th'></i> Logger</a></li>
<li><a href="{relative_path}/admin/motd"><i class="fa fa-comment"></i> MOTD</a></li>
</ul>
</div>
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Social Authentication</li>
<li><a href='{relative_path}/admin/twitter'><i class='icon-twitter-sign'></i> Twitter</a></li>
<li><a href='{relative_path}/admin/facebook'><i class='icon-facebook-sign'></i> Facebook</a></li>
<li><a href='{relative_path}/admin/gplus'><i class='icon-google-plus-sign'></i> Google+</a></li>
<li><a href='{relative_path}/admin/twitter'><i class='fa fa-twitter-square'></i> Twitter</a></li>
<li><a href='{relative_path}/admin/facebook'><i class='fa fa-facebook-square'></i> Facebook</a></li>
<li><a href='{relative_path}/admin/gplus'><i class='fa fa-google-plus-square'></i> Google+</a></li>
<!-- BEGIN authentication -->
<li>
<a href='{relative_path}/admin{authentication.route}'><i class="fa {authentication.icon}"></i> {authentication.name}</a>
</li>
<!-- END authentication -->
</ul>
</div>
<div class="well sidebar-nav">
@@ -121,7 +128,7 @@
<li class="nav-header">Plugins</li>
<!-- BEGIN plugins -->
<li>
<a href='{relative_path}/admin{plugins.route}'><i class="{plugins.icon}"></i> {plugins.name}</a>
<a href='{relative_path}/admin{plugins.route}'><i class="fa {plugins.icon}"></i> {plugins.name}</a>
</li>
<!-- END plugins -->
</ul>
@@ -144,4 +151,4 @@
</div><!--/.well -->
</div><!--/span-->
<div class="col-md-9" id="content">
<div class="col-sm-9" id="content">

View File

@@ -3,10 +3,10 @@
<h1>Welcome to NodeBB</h1>
<br />
<p>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-comment"></i> NodeBB Forum</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Plugins</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Themes</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-twitter"></i> dcplabs</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-comment"></i> NodeBB Forum</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-github-alt"></i> Get Plugins</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-github-alt"></i> Get Themes</a>
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-twitter"></i> dcplabs</a>
</p>
<p><small>You are running <strong>NodeBB v{version}</strong>. Always make sure that your <strong>NodeBB</strong> is up to date for the latest security patches and bug fixes.</small></p>
</div>

View File

@@ -12,11 +12,14 @@
<input type="text" class="form-control" placeholder="Keywords describing your community, comma-seperated" data-field="keywords" /><br />
<label>Site Logo</label>
<input id="logoUrl" type="text" class="form-control" placeholder="Path to a logo to display on forum header" data-field="brand:logo" /><br />
<input id="uploadLogoBtn" type="button" class="btn btn-default" value="Upload"></input> <br />
<input id="uploadLogoBtn" type="button" class="btn btn-default" value="Upload Logo"></input> <br />
<label>Imgur Client ID</label>
<input type="text" class="form-control" placeholder="Imgur ClientID for image uploads" data-field="imgurClientID" /><br />
<label>Maximum User Image Size</label>
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" />
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" /><br />
<label>Favicon</label><br />
<input id="faviconUrl" type="text" class="form-control" placeholder="favicon.ico" data-field="brand:favicon" /><br />
<input id="uploadFaviconBtn" type="button" class="btn btn-default" value="Upload Favicon"></input> <br />
</form>
</div>
@@ -26,6 +29,11 @@
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_topic"><br />
<strong>Manage Content</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_content"><br />
<div class="checkbox">
<label>
<input type="checkbox" data-field="privileges:disabled"> <strong>Disable Privilege Threshold System</strong>
</label>
</div>
</div>
</form>
@@ -55,15 +63,38 @@
</div>
</form>
<form>
<h3>Profile Settings</h3>
<div class="alert alert-warning">
<div class="checkbox">
<label>
<input type="checkbox" data-field="profile:convertProfileImageToPNG"> <strong>Convert profile image uploads to PNG</strong>
</label>
</div>
</div>
</form>
<form>
<h3>User Settings</h3>
<div class="alert alert-warning">
<div class="checkbox">
<label>
<input type="checkbox" data-field="allowRegistration" checked> <strong>Allow registration</strong>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-field="disableSignatures"> <strong>Disable signatures</strong>
</label>
</div>
<strong>Minimum Username Length</strong><br />
<input type="text" class="form-control" value="2" data-field="minimumUsernameLength"><br />
<strong>Maximum Username Length</strong><br />
<input type="text" class="form-control" value="16" data-field="maximumUsernameLength"><br />
<strong>Minimum Password Length</strong><br />
<input type="text" class="form-control" value="6" data-field="minimumPasswordLength"><br />
<strong>Maximum Signature Length</strong><br />
<input type="text" class="form-control" value="255" data-field="maximumSignatureLength"><br />
</div>
</form>
@@ -78,6 +109,11 @@
<input type="checkbox" data-field="allowGuestPosting"> <strong>Allow guests to post without logging in</strong>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-field="allowGuestSearching"> <strong>Allow guests to search without logging in</strong>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong>

View File

@@ -6,7 +6,7 @@
The following themes are currently installed in this NodeBB instance.
</p>
<ul class="themes" id="installed_themes">
<li><i class="icon-refresh icon-spin"></i> Checking for installed themes...</li>
<li><i class="fa fa-refresh fa-spin"></i> Checking for installed themes...</li>
</ul>
<h3>Bootswatch Themes</h3>
@@ -15,7 +15,7 @@
with Bootstrap as a base theme.
</p>
<ul class="themes" id="bootstrap_themes">
<li><i class="icon-refresh icon-spin"></i> Loading Themes</li>
<li><i class="fa fa-refresh fa-spin"></i> Loading Themes</li>
</ul>
<h3>Revert to Default</h3>

View File

@@ -1,24 +1,33 @@
<h1>Topics</h1>
<hr />
<ul class="topics">
<!-- BEGIN topics -->
<li data-tid="{topics.tid}" data-locked="{topics.locked}" data-pinned="{topics.pinned}" data-deleted="{topics.deleted}">
<div class="btn-group pull-right">
<button data-action="pin" class="btn"><i class="icon-pushpin"></i></button>
<button data-action="lock" class="btn"><i class="icon-lock"></i></button>
<button data-action="delete" class="btn"><i class="icon-trash"></i></button>
<button data-action="pin" class="btn"><i class="fa fa-thumb-tack"></i></button>
<button data-action="lock" class="btn"><i class="fa fa-lock"></i></button>
<button data-action="delete" class="btn"><i class="fa fa-trash-o"></i></button>
</div>
<a target="_blank" href="{relative_path}/topic/{topics.slug}">{topics.title}</a>
<ul>
<li><i class="icon-time"></i> Posted <span class="timeago" title="{topics.relativeTime}"></span> by {topics.username}</li>
<li><i class="icon-comments"></i> {topics.postcount} post(s)</li>
<li><i class="fa fa-clock-o"></i> Posted <span class="timeago" title="{topics.relativeTime}"></span> by {topics.username}</li>
<li><i class="fa fa-comments"></i> {topics.postcount} post(s)</li>
</ul>
<div class="clear"></div>
</li>
<!-- END topics -->
</ul>
<!-- IF notopics -->
<div class="alert alert-warning" id="category-no-topics">
<strong>There are no topics.</strong>
</div>
<!-- ELSE -->
<div class="text-center">
<button id="topics_loadmore" class="btn btn-primary btn-lg">Load More Topics</button>
</div>
<!-- ENDIF notopics -->

View File

@@ -1,4 +1,6 @@
<h1>Users</h1>
<button id="createUser" class="btn btn-primary">Create User</button>
<hr />
<ul class="nav nav-pills">
<li class='active'><a href='/admin/users/latest'>Latest Users</a></li>
@@ -10,7 +12,7 @@
<br />
<div class="search {search_display} well">
<input class="form-control" id="search-user" type="text" placeholder="Enter a username to search"/><br />
<i class="icon-spinner icon-spin none"></i>
<i class="fa fa-spinner fa-spin none"></i>
<span id="user-notfound-notify" class="label label-danger hide">User not found!</span><br/>
</div>
@@ -24,11 +26,11 @@
<a href="/user/{users.userslug}">{users.username}</a>
<br/>
<div title="reputation">
<i class='icon-star'></i>
<i class='fa fa-star'></i>
<span id='reputation'>{users.reputation}</span>
</div>
<div title="post count">
<i class='icon-pencil'></i>
<i class='fa fa-pencil'></i>
<span id='postcount'>{users.postcount}</span>
</div>
<div>
@@ -38,6 +40,47 @@
<!-- END users -->
</ul>
<div class="modal fade" id="create-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Create User</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger hide" id="create-modal-error"></div>
<form>
<div class="form-group">
<label for="group-name">User Name</label>
<input type="text" class="form-control" id="create-user-name" placeholder="User Name" />
</div>
<div class="form-group">
<label for="group-name">Email</label>
<input type="text" class="form-control" id="create-user-email" placeholder="Email of this user" />
</div>
<div class="form-group">
<label for="group-name">Password</label>
<input type="password" class="form-control" id="create-user-password" placeholder="Password" />
</div>
<div class="form-group">
<label for="group-name">Password Confirm</label>
<input type="password" class="form-control" id="create-user-password-again" placeholder="Password" />
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="create-modal-go">Create</button>
</div>
</div>
</div>
</div>
<div class="text-center {loadmore_display}">
<button id="load-more-users-btn" class="btn btn-primary">Load More</button>
</div>

View File

@@ -3,18 +3,18 @@
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
</li>
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">{category_name} <a target="_blank" href="../{category_id}.rss"><i class="icon-rss-sign"></i></a></span>
<span itemprop="title">{category_name} <a target="_blank" href="../{category_id}.rss"><i class="fa fa-rss-square"></i></a></span>
</li>
<div id="category_active_users"></div>
</ol>
<div>
<button id="new_post" class="btn btn-primary btn-lg {show_topic_button}">[[category:new_topic_button]]</button>
<button id="new_post" class="btn btn-primary {show_topic_button}">[[category:new_topic_button]]</button>
<div class="inline-block pull-right">
<a href="#" id="facebook-share"><i class="icon-facebook-sign icon-2x"></i></a>&nbsp;
<a href="#" id="twitter-intent"><i class="icon-twitter-sign icon-2x"></i></a>&nbsp;
<a href="#" id="google-share"><i class="icon-google-plus-sign icon-2x"></i></a>&nbsp;
<a href="#" id="facebook-share"><i class="fa fa-facebook-square fa-2x"></i></a>&nbsp;
<a href="#" id="twitter-intent"><i class="fa fa-twitter-square fa-2x"></i></a>&nbsp;
<a href="#" id="google-share"><i class="fa fa-google-plus-square fa-2x"></i></a>&nbsp;
</div>
</div>
@@ -38,38 +38,41 @@
<meta itemprop="name" content="{topics.title}">
<span class="topic-title">
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
<strong><i class="fa {topics.pin-icon}"></i> <i class="fa {topics.lock-icon}"></i></strong>
{topics.title}
</span>
</h3>
</a>
<small>
<span class="topic-stats">
posts
<strong>{topics.postcount}</strong>
[[category:posts]]
<strong class="human-readable-number" title="{topics.postcount}">{topics.postcount}</strong>
</span>
|
<span class="topic-stats">
views
<strong>{topics.viewcount}</strong>
[[category:views]]
<strong class="human-readable-number" title="{topics.viewcount}">{topics.viewcount}</strong>
</span>
|
<span>
<a href="/user/{topics.userslug}">
<img class="teaser-pic" src="{topics.picture}" title="{topics.username}"/>
</a>
posted <span class="timeago" title="{topics.relativeTime}"></span>
[[category:posted]] <span class="timeago" title="{topics.relativeTime}"></span>
</span>
<span class="pull-right hidden-xs">
<!-- IF topics.unreplied -->
[[category:no_replies]]
<!-- ELSE -->
<a href="/user/{topics.teaser_userslug}">
<img class="teaser-pic" src="{topics.teaser_userpicture}" title="{topics.teaser_username}"/>
</a>
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
replied
[[category:replied]]
</a>
<span class="timeago" title="{topics.teaser_timestamp}"></span>
<!-- ENDIF topics.unreplied -->
</span>
</small>
</div>
@@ -80,43 +83,35 @@
</ul>
</div>
<div class="col-md-3 {show_sidebar} category-sidebar">
<div class="sidebar-block img-thumbnail">
<div class="block-header">
[[category:sidebar.recent_replies]]
</div>
<div class="block-content recent-replies">
<div class="panel panel-default">
<div class="panel-heading">[[category:sidebar.recent_replies]]</div>
<div class="panel-body recent-replies">
<ul id="category_recent_replies"></ul>
</div>
</div>
<div class="sidebar-block img-thumbnail">
<div class="block-header">
[[category:sidebar.active_participants]]
</div>
<div class="block-content active-users">
<div class="panel panel-default">
<div class="panel-heading">[[category:sidebar.active_participants]]</div>
<div class="panel-body active-users">
<!-- BEGIN active_users -->
<a data-uid="{active_users.uid}" href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded" /></a>
<a data-uid="{active_users.uid}" href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded user-img" /></a>
<!-- END active_users -->
</div>
</div>
<div class="sidebar-block img-thumbnail {moderator_block_class}">
<div class="block-header">
[[category:sidebar.moderators]]
</div>
<div class="block-content">
<div class="panel panel-default {moderator_block_class}">
<div class="panel-heading">[[category:sidebar.moderators]]</div>
<div class="panel-body moderators">
<!-- BEGIN moderators -->
<a href="/user/{moderators.userslug}"><img title="{moderators.username}" src="{moderators.picture}" class="img-rounded" /></a>
<!-- END moderators -->
</div>
</div>
<!-- BEGIN sidebars -->
<div class="sidebar-block img-thumbnail {sidebars.block_class}">
<div class="block-header">
{sidebars.header}
</div>
<div class="block-content">
{sidebars.content}
</div>
<div class="panel panel-default">
<div class="panel panel-default {sidebars.block_class}">{sidebars.header}</div>
<div class="panel-body">{sidebars.content}</div>
</div>
<!-- END sidebars -->
</div>

View File

@@ -0,0 +1,31 @@
<div class="composer">
<div class="composer-container">
<input class="title" type="text" tabIndex="1" placeholder="Enter your topic title here..." />
<div class="btn-toolbar formatting-bar">
<div class="btn-group">
<span class="btn btn-link" tabindex="-1"><i class="fa fa-bold"></i></span>
<span class="btn btn-link" tabindex="-1"><i class="fa fa-italic"></i></span>
<span class="btn btn-link" tabindex="-1"><i class="fa fa-list"></i></span>
<span class="btn btn-link" tabindex="-1"><i class="fa fa-link"></i></span>
<span class="btn btn-link" tabindex="-1">
<input type="file" id="files" name="files[]" multiple class="hide"/>
<i class="fa fa-picture-o"></i>
</span>
</div>
<!-- <div class="btn btn-link pull-right">Preview</div> -->
</div>
<textarea tabIndex="2"></textarea>
<div class="preview"></div>
<div class="imagedrop"><div>Drag and Drop Images Here</div></div>
<div class="text-center upload-instructions hide">
<small>Upload images by dragging & dropping them</small>
</div>
<div class="btn-toolbar action-bar">
<div class="btn-group pull-right">
<button class="btn btn-default" data-action="discard" tabIndex="5"><i class="fa fa-times"></i> Discard</button>
<button data-action="post" class="btn btn-default" tabIndex="3"><i class="fa fa-check"></i> Submit</button>
</div>
</div>
<div class="resizer"><div class="trigger"><i class="fa fa-chevron-left"></i></div></div>
</div>
</div>

View File

@@ -4,7 +4,7 @@
"^admin/topics.*": "admin/topics",
"^admin/categories.*": "admin/categories",
"^admin/users.*": "admin/users",
"^admin/redis.*": "admin/redis",
"^admin/database.*": "admin/database",
"^admin/index.*": "admin/index",
"^admin/themes.*": "admin/themes",
"^admin/plugins/?$": "admin/plugins",

View File

@@ -2,6 +2,6 @@
<strong>{title}</strong>
<p>{text}</p>
<p>
<a href="/">NodeBB Home</a>
<a href="/">[[notification:back_to_home]]</a>
</p>
</div>

View File

@@ -1,21 +1,36 @@
<div class="well favourites">
<div class="account-username-box" data-userslug="{userslug}">
<span class="account-username">
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
<a href="/user/{userslug}/favourites">favourites</a>
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
<a href="/user/{userslug}/favourites">[[topic:favourites]]</a>
</span>
</div>
<div id="no-favourites-notice" class="alert alert-warning {show_nofavourites}">You don't have any favourites, favourite some posts to see them here!</div>
<!-- IF show_nofavourites -->
<div id="no-favourites-notice" class="alert alert-warning">[[topic:has_no_favourites]]</div>
<!-- ENDIF show_nofavourites -->
<div class="row">
<div class="col-md-12 user-favourite-posts">
<!-- BEGIN posts -->
<div class="topic-row img-thumbnail clearfix" topic-url="topic/{posts.tid}/#{posts.pid}">
<span><strong>{posts.username}</strong> : </span>
<span>{posts.content}</span>
<div class="topic-row img-thumbnail clearfix">
<a href="../../user/{posts.userslug}">
<img title="{posts.username}" class="img-rounded user-img" src="{posts.picture}">
</a>
<a href="../../topic/{posts.tid}/#{posts.pid}">
<strong><span>{posts.username}</span></strong>
<p>{posts.content}</p>
</a>
<div>
<span class="pull-right timeago" title="{posts.relativeTime}"></span>
<span class="pull-right">
posted in
<a href="../../category/{posts.categorySlug}">
<i class="fa {posts.categoryIcon}"></i> {posts.categoryName}
</a>
<span class="timeago" title="{posts.relativeTime}"></span>
</span>
</div>
</div>
<br/>

View File

@@ -1,10 +1,9 @@
<div class="well users">
<div class="well users account">
<div class="account-username-box" data-userslug="{userslug}">
<span class="account-username">
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
<a href="/user/{userslug}/followers">followers</a>
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
<a href="/user/{userslug}/followers">[[user:followers]]</a>
</span>
</div>
@@ -19,18 +18,18 @@
<a href="/user/{followers.userslug}">{followers.username}</a>
<br/>
<div title="reputation" class="reputation">
<i class='fa fa-star'></i>
<span class='formatted-number'>{followers.reputation}</span>
<i class='icon-star'></i>
</div>
<div title="post count" class="post-count">
<i class='fa fa-pencil'></i>
<span class='formatted-number'>{followers.postcount}</span>
<i class='icon-pencil'></i>
</div>
</div>
</div>
<!-- END followers -->
</div>
<div id="no-followers-notice" class="alert alert-warning hide">This user doesn't have any followers :(</div>
<div id="no-followers-notice" class="alert alert-warning hide">[[user:has_no_follower]]</div>
</div>
<input type="hidden" template-variable="yourid" value="{yourid}" />

View File

@@ -1,10 +1,9 @@
<div class="well users">
<div class="well users account">
<div class="account-username-box" data-userslug="{userslug}">
<span class="account-username">
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
<a href="/user/{userslug}/following">following</a>
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
<a href="/user/{userslug}/following">[[user:following]]</a>
</span>
</div>
@@ -20,18 +19,18 @@
<br/>
<div title="reputation" class="reputation">
<span class='formatted-number'>{following.reputation}</span>
<i class='icon-star'></i>
<i class='fa fa-star'></i>
</div>
<div title="post count" class="post-count">
<span class='formatted-number'>{following.postcount}</span>
<i class='icon-pencil'></i>
<i class='fa fa-pencil'></i>
</div>
</div>
</div>
<!-- END following -->
</div>
<div id="no-following-notice" class="alert alert-warning hide">This user isn't following anyone :(</div>
<div id="no-following-notice" class="alert alert-warning hide">[[user:follows_no_one]]</div>
</div>
<input type="hidden" template-variable="yourid" value="{yourid}" />

View File

@@ -26,21 +26,21 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Upload Picture</h3>
<h3 id="myModalLabel">[[user:upload_picture]]</h3>
</div>
<div class="modal-body">
<form id="uploadForm" action="" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="userPhoto">Upload a picture</label>
<label for="userPhoto">[[user:upload_a_picture]]</label>
<input type="file" id="userPhotoInput" name="userPhoto">
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
<p class="help-block">[[user:image_spec]]</p>
</div>
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
</form>
<div id="upload-progress-box" class="progress progress-striped">
<div id="upload-progress-bar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0">
<span class="sr-only"> success</span>
<span class="sr-only"> [[footer:success]]</span>
</div>
</div>
@@ -50,7 +50,7 @@
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
<button id="pictureUploadSubmitBtn" class="btn btn-primary">[[user:upload_picture]]</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
@@ -59,8 +59,11 @@
<div id="alert_window"></div>
<footer id="footer" class="container footer">
<div class="copyright">Copyright &copy; 2013 <a target="_blank" href="http://www.nodebb.org">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></div>
<footer id="footer" class="container footer hide">
{footerHTML}
<div class="copyright">
Copyright &copy; 2013 <a target="_blank" href="http://www.nodebb.com">NodeBB Forums</a> | <a target="_blank" href="//github.com/designcreateplay/NodeBB/graphs/contributors">Contributors</a>
</div>
</footer>
<script>

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