Compare commits

...

259 Commits

Author SHA1 Message Date
Julian Lam
15ac9cb5c4 updated shrinkwrap file 2015-08-27 16:55:47 -04:00
Julian Lam
78d126a34e Merge remote-tracking branch 'origin/master' into v0.8.x 2015-08-27 16:52:34 -04:00
psychobunny
00eea65a70 up'd persona, welcome to 0.8.0 2015-08-27 16:51:21 -04:00
Julian Lam
85a609cae3 Merge branch 'master' into v0.8.x 2015-08-27 16:49:49 -04:00
barisusakli
e171b544e9 fix 404 title on api calls 2015-08-27 16:43:14 -04:00
psychobunny
dbc9c07b55 403 browser title 2015-08-27 16:34:01 -04:00
psychobunny
0eca875f6e add site title to 404, on cold load anyways 2015-08-27 16:30:43 -04:00
Julian Lam
141999a97c Merge remote-tracking branch 'origin/master' into v0.8.x 2015-08-27 16:20:25 -04:00
psychobunny
4b91d7ec3d req.route is not defined if you go to some bogus url 2015-08-27 16:18:55 -04:00
psychobunny
54ec105986 random attempt to fix bad dep check 2015-08-27 16:09:35 -04:00
Julian Lam
f11446e0bc added shrinkwrap file 2015-08-27 16:08:33 -04:00
psychobunny
8dbc7fdd9c up'd person 2015-08-27 15:56:49 -04:00
Julian Lam
dd7d2615dd latest translations 2015-08-27 15:57:00 -04:00
Julian Lam
3fcfa340ee updated plugin and theme dependency versions 2015-08-27 15:45:55 -04:00
barisusakli
6810b529c9 prevent infinite loop on topic scroll to bottom 2015-08-27 15:32:33 -04:00
psychobunny
822b45e193 Merge branch 'v0.8.x' 2015-08-27 15:29:26 -04:00
psychobunny
4b5f67eb4d use [[pages:home]] instead 2015-08-27 15:28:46 -04:00
psychobunny
5dae60faff closes #3502 2015-08-27 15:26:53 -04:00
psychobunny
61cc0ee597 /categories: og:title and <title> should be the same 2015-08-27 15:07:26 -04:00
psychobunny
53c8d54d57 upping themes 2015-08-27 14:59:22 -04:00
psychobunny
82d39753b7 hint 2015-08-27 14:53:53 -04:00
psychobunny
b10a7d4410 notifications/icon component 2015-08-27 14:52:39 -04:00
psychobunny
80218961aa Merge branch 'master' into v0.8.x 2015-08-27 14:28:12 -04:00
psychobunny
8cc91ea6e7 fix crash in middleware.renderHeader 2015-08-27 14:27:45 -04:00
psychobunny
b66a58dd52 user/status: don't touch the other classes
fixes that 2px thing @julianlam
2015-08-27 14:07:24 -04:00
psychobunny
b7c8d4e5af 0.8.0 2015-08-27 14:00:15 -04:00
psychobunny
541080777f Merge branch 'persona-2.1' into v0.8.x 2015-08-27 13:59:44 -04:00
psychobunny
25a419e458 Merge branch 'master' into v0.8.x 2015-08-27 13:59:12 -04:00
psychobunny
12015c1728 persona 2.1.4 2015-08-27 13:19:04 -04:00
psychobunny
d923fa3997 up'd persona 2015-08-27 12:46:06 -04:00
psychobunny
b5c7a34aa5 persona 2.1.1 2015-08-27 12:34:44 -04:00
psychobunny
54d996ca6a fixed user/logout component + vanilla 3.1.2 2015-08-27 12:24:58 -04:00
psychobunny
b19120f822 user/logout componen 2015-08-27 12:20:45 -04:00
psychobunny
e9a42cdecb fixed notifications on deskto 2015-08-27 11:48:08 -04:00
psychobunny
1947a4aea6 vanilla 3.1.0 2015-08-26 17:58:35 -04:00
psychobunny
71f144eb49 nbb 0.7.4 2015-08-26 17:53:23 -04:00
psychobunny
a44f467ebc Notifications.loadNotifications() 2015-08-26 17:52:36 -04:00
psychobunny
2301362f59 component="header/usercontrol"; also fixes user status bug 2015-08-26 17:12:34 -04:00
psychobunny
a663f95669 chats.loadChats() 2015-08-26 16:32:32 -04:00
psychobunny
63be875daa header/userpicture, header/profilelink, header/username components 2015-08-26 16:28:10 -04:00
psychobunny
2e33ae2742 Merge branch 'master' into persona-2.1 2015-08-26 16:25:57 -04:00
psychobunny
6e714a5344 Revert "header/userpicture, header/profilelink, header/username components"
This reverts commit d1effa65d0.
2015-08-26 16:25:05 -04:00
psychobunny
d1effa65d0 header/userpicture, header/profilelink, header/username components 2015-08-26 16:19:08 -04:00
psychobunny
306964b4ea chat/dropdown and chat/list component 2015-08-26 15:58:53 -04:00
barisusakli
0bf8b279de fix typo 2015-08-26 15:58:51 -04:00
barisusakli
5c19bf31c9 removed breaking change 2015-08-26 15:58:27 -04:00
barisusakli
eaefd9d24c remove meta/title.js and meta.title.build #3481 2015-08-26 15:55:00 -04:00
psychobunny
098c56a106 global:header.navigation 2015-08-26 15:38:09 -04:00
psychobunny
4aec30788c closes #3499 2015-08-26 15:08:48 -04:00
psychobunny
d75f5574e0 #3499 2015-08-26 15:06:16 -04:00
psychobunny
a217b42cb1 bonus two for #3481 - chats/username route 2015-08-26 14:09:22 -04:00
psychobunny
22fc257e36 bonus for #3481 - groups/group route 2015-08-26 14:06:53 -04:00
psychobunny
89b8622cfa other routes done, closes #3481 2015-08-26 13:56:28 -04:00
psychobunny
671f96f589 duplicate route removed: /users redirected to /users/online 2015-08-26 13:51:50 -04:00
psychobunny
0e0d8474a4 page titles for user pages #3481 2015-08-26 13:48:27 -04:00
psychobunny
51f05e3d22 persona 2.0.27 2015-08-26 13:38:59 -04:00
psychobunny
d96ef5264d upping persona 2015-08-26 12:28:30 -04:00
psychobunny
47a7347b54 better mobile support for appearance/themes and appearance/skins 2015-08-26 12:01:06 -04:00
psychobunny
0cb722b9fa prevent floating button from getting hidden behind other components 2015-08-26 11:56:18 -04:00
Julian Lam
92f9553033 Resolved transifex language issue 2015-08-26 11:21:55 -04:00
Julian Lam
e003fb38a3 Close #3497 2015-08-26 10:57:20 -04:00
barisusakli
d644542143 clearer text 2015-08-26 01:03:02 -04:00
barisusakli
958bb24d4e #3492 2015-08-25 23:50:41 -04:00
Julian Lam
ea9f5cbc61 adding in another deprecated hook to the warning list 2015-08-25 17:52:52 -04:00
Julian Lam
a1d5132777 Deprecated filter:user.delete hook
Please use static:user.delete instead.
2015-08-25 17:48:29 -04:00
psychobunny
6c44db9a0c closes #3490 2015-08-25 17:05:48 -04:00
psychobunny
8372b291e4 closes #3482 2015-08-25 16:41:09 -04:00
psychobunny
6edb920d6d closes #3488 2015-08-25 16:36:41 -04:00
psychobunny
cd7f9c7523 fix for disableCustomUserSkins 2015-08-25 16:27:58 -04:00
psychobunny
9323a37bd1 disableCustomUserSkins setting 2015-08-25 16:27:56 -04:00
barisusakli
5ef58d0434 up theme versions 2015-08-25 14:58:20 -04:00
barisusakli
3a3539aefb up composer version 2015-08-25 13:31:33 -04:00
barisusakli
cf36f7bc79 closes #3468 2015-08-25 13:29:44 -04:00
Julian Lam
edba11f388 If a plugin version is defined in package.json, suggest that as the latest version 2015-08-25 12:22:25 -04:00
Julian Lam
1772041b6e fixed invocation of clickdn in snackbar 2015-08-25 11:21:33 -04:00
psychobunny
7210ffdde9 only need to translate bootbox's footer 2015-08-24 17:43:42 -04:00
psychobunny
29859335a8 do md style dropdowns only on mobile @julianlam 2015-08-24 17:36:10 -04:00
psychobunny
3e1ddb1e2c for old people like @barisusakli 2015-08-24 17:30:44 -04:00
psychobunny
3145e75fc0 closes #3485 2015-08-24 17:16:29 -04:00
barisusakli
07d12e85ae closes https://github.com/NodeBB/nodebb-theme-persona/issues/124 2015-08-24 17:04:23 -04:00
barisusakli
c1ef884fce update password dep 2015-08-24 16:26:45 -04:00
barisusakli
6e23b3f258 update theme versions 2015-08-24 16:05:11 -04:00
barisusakli
5b3601994c Merge branch 'master' of https://github.com/NodeBB/NodeBB 2015-08-24 16:01:57 -04:00
barisusakli
def3e06ba3 closes #3483 2015-08-24 16:01:50 -04:00
psychobunny
19a3950928 don't blow up if no skin was selected 2015-08-24 16:01:35 -04:00
psychobunny
ae318c4286 fixed alignment on themes page 2015-08-24 15:29:38 -04:00
psychobunny
5a90de55d8 removed missing css file 2015-08-24 15:15:58 -04:00
Julian Lam
9289178a2e fixed incorrect label 2015-08-24 14:32:27 -04:00
Julian Lam
46af72336a updated ACP dropdown toggle so it's thicker 2015-08-24 13:52:13 -04:00
Julian Lam
a27c8f0321 Exposed package data for incompatible plugins to admin/plugins controller, #3480
ping @psychobunny
2015-08-24 13:41:25 -04:00
Julian Lam
902d11c6af Fix #3470 2015-08-24 11:34:09 -04:00
Julian Lam
7de782c78b Close #3476
Upgraded theme minimum versions, containing fixes for a "bug" where the container was a couple px too large due to a missing class.
2015-08-24 10:59:55 -04:00
Julian Lam
a682c98626 Merge pull request #3474 from FokkeZB/patch-5
Only use semver.satisfies on valid ranges
2015-08-24 09:58:02 -04:00
Fokke Zandbergen
36c27633b9 Only use semver.satisfies on valid ranges
So it doesn't alarm when you use a package straight from git e.g.
2015-08-24 15:22:08 +02:00
Barış Soner Uşaklı
1a6e576483 async 2015-08-23 22:16:48 -07:00
barisusakli
6ce6503970 mark register notif read when its rejected 2015-08-23 14:21:43 -04:00
barisusakli
db90d19b45 fix password confirm 2015-08-22 16:08:37 -04:00
barisusakli
2781939c50 Merge remote-tracking branch 'origin/master'
Conflicts:
	package.json
2015-08-22 15:17:37 -04:00
barisusakli
fc29028920 up persona 2015-08-22 15:16:34 -04:00
psychobunny
48cb671916 fixes #3465
temporary until stopforumspam supports ipv6
2015-08-22 12:50:55 -04:00
psychobunny
d1aaa9ca07 mobile fixes for homepage, languages, sounds 2015-08-22 12:39:52 -04:00
psychobunny
53ce7d48fa fixed padding issue on mobile acp 2015-08-22 12:36:42 -04:00
psychobunny
cd83dcf2e0 better styling for snackbar on mobile 2015-08-22 12:33:14 -04:00
psychobunny
7fa4057051 overrideTimeago only needs to be called once 2015-08-22 12:21:51 -04:00
psychobunny
0caa095ea4 closes #3457 2015-08-22 12:20:17 -04:00
psychobunny
12518e095f upping theme versions 2015-08-22 12:04:00 -04:00
psychobunny
36110db90c closes #3464 2015-08-22 12:03:34 -04:00
psychobunny
0cb8f2b80c closes #3463 2015-08-21 22:28:05 -04:00
psychobunny
6b054a6d14 new acp mobile menu, completed 2015-08-21 18:50:22 -04:00
psychobunny
cc299f89e2 mobile menu for ACP first pass 2015-08-21 18:40:59 -04:00
psychobunny
82429c10db slideout 2015-08-21 18:29:37 -04:00
psychobunny
1f9dbd3cf2 hamburger button 2015-08-21 18:26:44 -04:00
psychobunny
cb071f3772 md-like positioning for dropdown menu 2015-08-21 18:15:43 -04:00
psychobunny
acdfb87117 compact header on mobile 2015-08-21 18:15:32 -04:00
psychobunny
ea3fa0ff1d md snackbar for acp 2015-08-21 17:46:14 -04:00
psychobunny
a313bc69e2 fix alignment on checkboxes that are first in a form 2015-08-21 17:16:35 -04:00
Barış Soner Uşaklı
113a2aa398 composer 1.0.11 2015-08-21 14:16:29 -04:00
Barış Soner Uşaklı
76c0e33bcb filter links and children 2015-08-21 14:15:41 -04:00
Julian Lam
0e8482ebfe removing hash from url 2015-08-21 12:32:21 -04:00
Julian Lam
dbf8f5f70c Fix internal link to User Registration Settings from Registration Queue 2015-08-21 12:27:31 -04:00
psychobunny
28bd915a7b fixed settings pages 2015-08-21 12:22:48 -04:00
psychobunny
11e082989d fix route to admin/manage/registration page 2015-08-21 12:13:42 -04:00
Julian Lam
141174ac94 Fix ACP active state issue
Apparently, all this time, there was a bug that caused active
states to not properly be shown in subfolder installations. This
commit fixes that regression. ping @psychobunny
2015-08-21 10:53:47 -04:00
psychobunny
7420351eb7 Merge remote-tracking branch 'origin/master' 2015-08-21 10:36:08 -04:00
psychobunny
eb49898a9c mobile tweaks for settings pages 2015-08-21 10:35:55 -04:00
Julian Lam
5f9990299f Pass a notification path when a user follows another
When a user followed another, a notification is created, but with
no path, so on plugins like pushbullet, it would default to trying
to build a topic url, but the required values were null, leading to
a broken url.
2015-08-21 10:32:14 -04:00
psychobunny
fdb3046224 tablet mode fix 2015-08-21 10:24:16 -04:00
psychobunny
2317779a2b really basic mobile support, until we get a slideout menu in 2015-08-21 10:22:54 -04:00
psychobunny
cdc351bc02 fixed acp search 2015-08-21 10:11:19 -04:00
psychobunny
e4c9b379b2 customise - checkboxes 2015-08-21 10:01:13 -04:00
psychobunny
d9040f18e6 use branding for checkbox 2015-08-21 09:59:07 -04:00
psychobunny
c97631b060 settings checkboxes - webcrawler, tags, advanced 2015-08-21 09:53:33 -04:00
psychobunny
4bca984b67 settings/pagination checkbox 2015-08-20 23:42:02 -04:00
psychobunny
0fcdfe318a settings/post checkboxes 2015-08-20 23:41:31 -04:00
psychobunny
520351c3cc fixed race condition onload for settings (surprised nobody qq'd about this before) 2015-08-20 23:39:33 -04:00
psychobunny
fc858b7cbc settings/guest checkboxes 2015-08-20 23:38:23 -04:00
psychobunny
656476620e fix new checkboxes on ajaxify 2015-08-20 23:36:59 -04:00
psychobunny
bf7896a264 settings/group checkboxes 2015-08-20 23:31:09 -04:00
psychobunny
4d78f8a68d settings/user checkbox 2015-08-20 23:28:27 -04:00
psychobunny
980d44975a settings/email checkboxes 2015-08-20 23:24:39 -04:00
psychobunny
c38bf4bc6f settings/reputation checkboxes 2015-08-20 23:23:15 -04:00
psychobunny
5ede82e246 setting/general checkboxes 2015-08-20 23:22:19 -04:00
psychobunny
6dbd7cad84 done with this stupid checkbox experiment 2015-08-20 23:16:54 -04:00
psychobunny
f234f653f8 fix bug where menu items weren't clickable 2015-08-20 19:58:37 -04:00
psychobunny
0b683ff8dd search bar placement tweak 2015-08-20 19:55:18 -04:00
psychobunny
d091729de3 search bar and restart menu completed 2015-08-20 19:39:44 -04:00
psychobunny
98a10bba89 header dropdown menu 2015-08-20 19:12:34 -04:00
psychobunny
6b37ec74cc styled flags 2015-08-20 16:34:22 -04:00
psychobunny
cd38f2da9c moved registration queue to its own page; styled 2015-08-20 16:31:23 -04:00
psychobunny
d72ffb3078 added authentication section to settings/user 2015-08-20 16:25:37 -04:00
psychobunny
21e4a00f0e fix pill flicker on manage/users 2015-08-20 16:19:49 -04:00
psychobunny
52d05da725 manage/tags buttons 2015-08-20 16:17:07 -04:00
psychobunny
e7fe088720 navigation save button 2015-08-20 16:14:39 -04:00
psychobunny
2dd612bb19 styled general/homepage 2015-08-20 16:11:56 -04:00
psychobunny
52871fe746 custom css save button 2015-08-20 16:08:39 -04:00
psychobunny
3353fc8b0e Merge branch 'master' into acp-paper
Conflicts:
	package.json
2015-08-20 16:05:08 -04:00
psychobunny
1ce464c7c0 themes page, done 2015-08-20 16:04:33 -04:00
psychobunny
fd46b31d6e fixed selection of skins 2015-08-20 16:00:25 -04:00
barisusakli
67bf130e6a up widget essentials 2015-08-20 15:59:21 -04:00
barisusakli
7fbab5402a closes #3381 2015-08-20 15:56:47 -04:00
psychobunny
181bb9a6a7 theme selection buttons 2015-08-20 15:49:44 -04:00
psychobunny
88c466bf3f fixed theme selection 2015-08-20 15:38:45 -04:00
psychobunny
b62cf2ad14 fix selection of skins 2015-08-20 15:37:16 -04:00
psychobunny
867c09bab6 revert theme: default theme is now persona 2015-08-20 15:35:29 -04:00
psychobunny
1e2fb5cd4c undo button for skins and themes 2015-08-20 15:35:09 -04:00
psychobunny
9af6a122ff general/sonuds 2015-08-20 15:27:38 -04:00
psychobunny
86d1494467 general/languages 2015-08-20 15:24:48 -04:00
psychobunny
9dcaafdb1b widgets save button 2015-08-20 15:21:35 -04:00
psychobunny
dfa4f47289 save / create buttons for categories/category 2015-08-20 15:19:43 -04:00
psychobunny
f3c70473c3 save button on settings page 2015-08-20 15:12:17 -04:00
psychobunny
96a19f47b7 Merge branch 'master' into acp-paper 2015-08-20 14:59:01 -04:00
psychobunny
969522c2d2 manage/categories 2015-08-20 14:58:58 -04:00
psychobunny
48d61b8048 Merge branch 'master' into acp-paper 2015-08-20 14:47:53 -04:00
psychobunny
ccce0994bf updated themes 2015-08-20 14:47:51 -04:00
barisusakli
4e3e603ee7 closes #3456 2015-08-20 14:43:34 -04:00
psychobunny
a2fd970792 fix skin screenshots 2015-08-20 14:34:17 -04:00
psychobunny
e4fa7c136a updated theme versions 2015-08-20 14:31:09 -04:00
barisusakli
49afe544e1 recursive #3227 2015-08-20 14:23:29 -04:00
psychobunny
d5b88e9c35 fixed markup on /group page 2015-08-20 14:20:13 -04:00
psychobunny
26858436b6 fix for acp subpage nav 2015-08-20 14:13:21 -04:00
psychobunny
e04495b012 underped tags page 2015-08-20 14:06:41 -04:00
psychobunny
cbb2453c08 minor styling to tags page 2015-08-20 14:00:56 -04:00
psychobunny
646cdf9c57 manage/category 2015-08-20 13:55:59 -04:00
psychobunny
bd494207eb got rid of that fancy edit for cat name/desc + improved layout for settings 2015-08-20 13:40:22 -04:00
psychobunny
ffd38b8cc3 some UX tweaks to manage/category 2015-08-20 13:31:27 -04:00
psychobunny
28e2297e63 fixed categories layout 2015-08-20 13:24:54 -04:00
psychobunny
c6282e289a main header title + better logic 2015-08-20 13:21:12 -04:00
psychobunny
744a7d4210 extend/widgets 2015-08-20 12:41:16 -04:00
psychobunny
d1f45b6d79 extend/plugin 2015-08-20 12:35:38 -04:00
psychobunny
ec335b55cd fixed active state for install plugins submenu 2015-08-20 12:24:24 -04:00
psychobunny
4fd99e8aae removed activateMobile 2015-08-20 12:22:20 -04:00
psychobunny
cd5bb427cc appearance/customise 2015-08-20 12:20:58 -04:00
psychobunny
c35ef74c5c header tweaks 2015-08-20 12:12:55 -04:00
psychobunny
12539a158d settings - advanced, header, sockets 2015-08-20 12:10:50 -04:00
psychobunny
0eb3d05db8 settings/web-crawler 2015-08-20 12:09:08 -04:00
psychobunny
46bb289950 settings - notifications, pagination, tags 2015-08-20 12:05:44 -04:00
psychobunny
623dbaa608 settings/post 2015-08-20 12:01:33 -04:00
psychobunny
fe98624609 settings/group and settings/guest 2015-08-20 11:54:46 -04:00
psychobunny
4fdf3d19a0 settings/user 2015-08-20 11:50:48 -04:00
psychobunny
d53ae8769f settings/email 2015-08-20 11:43:40 -04:00
psychobunny
dc6950d094 settings/reputation 2015-08-20 11:41:25 -04:00
psychobunny
3c43e58d85 Merge branch 'master' into acp-paper 2015-08-20 11:39:20 -04:00
psychobunny
30970d618c dynamic title for settings pages 2015-08-20 11:39:14 -04:00
Julian Lam
e382dcab13 Reduce verbosity of plugin incompatibility errors
Instead of showing a 4-5 line warning for each potentially incompatible
plugin, we'll show the warning and then a list of plugins.
2015-08-20 11:01:59 -04:00
Julian Lam
23bb45b480 fixing plugin version checker to use satisfies again 2015-08-20 10:29:58 -04:00
Julian Lam
3464141b0f updating soundpack version min 2015-08-20 10:29:38 -04:00
Julian Lam
3c5df8a8ec removing the -dev flag from this branch 2015-08-20 10:10:28 -04:00
barisusakli
274844a07f check _resolved 2015-08-19 18:28:31 -04:00
psychobunny
2da3b34798 Merge branch 'master' into acp-paper 2015-08-19 18:20:33 -04:00
Barış Soner Uşaklı
f4da333b42 Merge pull request #3351 from yariplus/catsfixes
Fixing some issues with acp category page
2015-08-19 17:51:31 -04:00
Barış Soner Uşaklı
79e7ca50c1 Merge pull request #3160 from Alpacatty/master
General-Purpose Dockerfile
2015-08-19 17:40:24 -04:00
barisusakli
5d68a61b46 latest persona 2015-08-19 17:32:42 -04:00
barisusakli
fee08cd665 closes https://github.com/NodeBB/NodeBB/pull/3250 2015-08-19 17:14:22 -04:00
Barış Soner Uşaklı
5e9a123e70 Merge pull request #3360 from jsdream/renderHeaderHook
Add 'filter:middleware.renderHeader' hook
2015-08-19 16:58:24 -04:00
Barış Soner Uşaklı
a2bf7d4230 Merge pull request #2895 from EvSpirit/master
#2893 increment --debug-brk port value when forking js-minifier child pr...
2015-08-19 16:46:47 -04:00
Barış Soner Uşaklı
eb0fb07f05 Merge pull request #3339 from mani95lisa/patch-4
allow use github module
2015-08-19 16:15:23 -04:00
barisusakli
7db41275a3 closes #3227 2015-08-19 15:53:37 -04:00
psychobunny
ba58c83b97 acp active states for main menu 2015-08-19 15:52:31 -04:00
jsdream
103055b262 Add error check in 'filter:middleware.renderHeader' hook callback 2015-08-19 22:50:04 +03:00
psychobunny
656589f71f acp skins first pass 2015-08-19 15:43:19 -04:00
psychobunny
9389c0773e acp themes redesign first pass 2015-08-19 15:31:15 -04:00
psychobunny
30cd8d2af9 cleaned up the widgets page 👍 2015-08-19 15:09:16 -04:00
psychobunny
f0bed5a1ef new menu completed 2015-08-19 14:58:48 -04:00
Julian Lam
6f23e4bab1 changing the default base theme to persona, from vanilla 2015-08-19 14:57:49 -04:00
Julian Lam
ac46356cad Revert "changed base templates path to Persona, from Vanilla."
This reverts commit fe7f5402a8.
2015-08-19 14:54:39 -04:00
psychobunny
cc05a0a049 header menu first pass 2015-08-19 14:46:40 -04:00
barisusakli
91aa1d55dc t.js 0.2.10 2015-08-19 14:28:48 -04:00
barisusakli
2bb6631078 update t.js ver 2015-08-19 14:28:04 -04:00
barisusakli
85ae56e41d closes #3452 2015-08-19 14:17:21 -04:00
yariplus
67e450a05b Fix issues with acp category page
strange name for background size variable
invalid class selectors
hijacking of background style
2015-08-19 13:47:15 -04:00
barisusakli
878690e5f7 removed extra param 2015-08-19 13:37:48 -04:00
psychobunny
d464cb2f0d settings - automated table of contents 2015-08-19 13:27:30 -04:00
psychobunny
acb1e8a495 added a tweaked mdl.css that works with BS 2015-08-19 12:48:33 -04:00
barisusakli
aec4ee5392 crash fix 2015-08-19 12:47:57 -04:00
psychobunny
51db2012c8 removed nanoscroller 2015-08-19 12:38:54 -04:00
psychobunny
60826b1c94 temporarily disabling header 2015-08-19 12:37:48 -04:00
psychobunny
e434942a28 first pass on settings design 2015-08-19 12:36:42 -04:00
psychobunny
fed87dded6 sayonara, acp menu 2015-08-19 12:02:38 -04:00
psychobunny
685b3ce004 added bootswatch paper 3.3.5 2015-08-19 11:55:51 -04:00
barisusakli
d07fca6907 update theme versions 2015-08-19 01:21:12 -04:00
barisusakli
7a8cdfc095 added core field 2015-08-19 01:16:30 -04:00
barisusakli
537d539512 fix custom homepage 2015-08-18 18:43:14 -04:00
barisusakli
5ababdbdf0 prevent crash if data.enter is not string 2015-08-18 17:05:34 -04:00
Julian Lam
c45e182bab Fix ./nodebb upgrade process to not use programmatic npm
- Closes #3451
- Apparently, programmatically invoking npm is like opening Pandora's
box. No thanks.
2015-08-18 16:46:51 -04:00
barisusakli
830d27caef dont ignore error 2015-08-18 15:17:07 -04:00
barisusakli
7bd98a2516 closes #3427 2015-08-18 15:01:36 -04:00
barisusakli
5b87af4389 closes #3447
recursively get all children
calculate topic/post count from children
new sorted set `cid:<id>:children`
fix search query params
2015-08-18 14:17:25 -04:00
Julian Lam
4f57227505 Merge branch 'master' into v0.8.x 2015-07-28 12:17:13 -04:00
barisusakli
5d56e4f835 Merge remote-tracking branch 'origin/master' into v0.8.x 2015-07-24 14:03:20 -04:00
barisusakli
26a9530686 fix sorting on users/map 2015-07-24 13:58:46 -04:00
jsdream
29fcbf6750 Add 'filter:middleware.renderHeader' hook 2015-07-24 18:18:22 +03:00
Julian Lam
791e0893ab added new hook "filter:digest.subscribers" to allow plugins to override digest subscriptions 2015-07-22 15:07:12 -04:00
barisusakli
766e233b87 closes #3353 2015-07-22 14:51:20 -04:00
Julian Lam
fe7f5402a8 changed base templates path to Persona, from Vanilla.
This breaks all themes relying on templates from Vanilla!! See: https://community.nodebb.org/topic/6098/on-changing-the-default-theme-to-persona
2015-07-22 11:30:14 -04:00
Mani Wang
92968dfd8d avoid outdated error
when use github address as module
2015-07-22 19:49:15 +08:00
Mani Wang
c13589735d allow use github module
avoid `outdated` error when use github address as module.
2015-07-20 16:57:35 +08:00
A Catty Alpaca
550140ada7 General-Purpose Dockerfile 2015-05-21 01:10:56 +02:00
EvSpirit
8a6c189d80 #2893 increment --debug-brk port value when forking js-minifier child process 2015-03-25 20:40:42 +03:00
EvSpirit
3bd2f53056 #2893 increment --debug-brk port value when forking js-minifier child process 2015-03-25 20:18:15 +03:00
164 changed files with 16786 additions and 2255 deletions

View File

@@ -485,7 +485,7 @@ trans.zh_CN = public/language/zh_CN/users.json
trans.zh_TW = public/language/zh_TW/users.json trans.zh_TW = public/language/zh_TW/users.json
type = KEYVALUEJSON type = KEYVALUEJSON
[nodebb.language] [nodebb.language-1]
file_filter = public/language/<lang>/language.json file_filter = public/language/<lang>/language.json
source_file = public/language/en_GB/language.json source_file = public/language/en_GB/language.json
source_lang = en_GB source_lang = en_GB

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM node:0.10-onbuild
ENV NODE_ENV=production \
daemon=false \
silent=false
CMD node app --setup && npm start
EXPOSE 4567

4
app.js
View File

@@ -95,7 +95,7 @@ function loadConfig() {
// Ensure themes_path is a full filepath // Ensure themes_path is a full filepath
nconf.set('themes_path', path.resolve(__dirname, nconf.get('themes_path'))); nconf.set('themes_path', path.resolve(__dirname, nconf.get('themes_path')));
nconf.set('core_templates_path', path.join(__dirname, 'src/views')); nconf.set('core_templates_path', path.join(__dirname, 'src/views'));
nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-vanilla/templates')); nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-persona/templates'));
if (!process.send) { if (!process.send) {
// If run using `node app`, log GNU copyright info along with server info // If run using `node app`, log GNU copyright info along with server info
@@ -348,7 +348,7 @@ function resetThemes(callback) {
type: 'local', type: 'local',
id: 'nodebb-theme-persona' id: 'nodebb-theme-persona'
}, function(err) { }, function(err) {
winston.info('[reset] Theme reset to Vanilla'); winston.info('[reset] Theme reset to Persona');
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(err); callback(err);
} else { } else {

18
nodebb
View File

@@ -5,8 +5,7 @@ var colors = require('colors'),
argv = require('minimist')(process.argv.slice(2)), argv = require('minimist')(process.argv.slice(2)),
fs = require('fs'), fs = require('fs'),
async = require('async'), async = require('async'),
touch = require('touch'), touch = require('touch');
npm = require('npm');
var getRunningPid = function(callback) { var getRunningPid = function(callback) {
fs.readFile(__dirname + '/pidfile', { fs.readFile(__dirname + '/pidfile', {
@@ -119,15 +118,12 @@ switch(process.argv[2]) {
case 'upgrade': case 'upgrade':
async.series([ async.series([
function(next) { function(next) {
process.stdout.write('1. '.bold + 'Bringing base dependencies up to date\n'.yellow); process.stdout.write('1. '.bold + 'Bringing base dependencies up to date... '.yellow);
npm.load({ require('child_process').execFile('/usr/bin/env', ['npm', 'i', '--production'], next);
loglevel: 'silent'
}, function() {
npm.commands.install(next);
});
}, },
function(next) { function(next) {
process.stdout.write('2. '.bold + 'Updating NodeBB data store schema\n'.yellow); process.stdout.write('OK\n'.green);
process.stdout.write('2. '.bold + 'Updating NodeBB data store schema.\n'.yellow);
var upgradeProc = cproc.fork('app.js', ['--upgrade'], { var upgradeProc = cproc.fork('app.js', ['--upgrade'], {
cwd: __dirname, cwd: __dirname,
silent: false silent: false
@@ -136,7 +132,7 @@ switch(process.argv[2]) {
upgradeProc.on('close', next) upgradeProc.on('close', next)
}, },
function(next) { function(next) {
process.stdout.write('3. '.bold + 'Storing upgrade date in "package.json"\n'.yellow); process.stdout.write('3. '.bold + 'Storing upgrade date in "package.json"... '.yellow);
touch(__dirname + '/package.json', {}, next); touch(__dirname + '/package.json', {}, next);
} }
], function(err) { ], function(err) {
@@ -145,6 +141,8 @@ switch(process.argv[2]) {
} else { } else {
var message = 'NodeBB Upgrade Complete!', var message = 'NodeBB Upgrade Complete!',
spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' '); spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' ');
process.stdout.write('OK\n'.green);
process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset); process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset);
} }
}); });

3627
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "nodebb", "name": "nodebb",
"license": "GPL-3.0", "license": "GPL-3.0",
"description": "NodeBB Forum", "description": "NodeBB Forum",
"version": "0.7.3-dev", "version": "0.8.0",
"homepage": "http://www.nodebb.org", "homepage": "http://www.nodebb.org",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -14,14 +14,14 @@
"test": "mocha ./tests -t 10000" "test": "mocha ./tests -t 10000"
}, },
"dependencies": { "dependencies": {
"async": "~0.9.0", "async": "~1.4.2",
"bcryptjs": "~2.1.0", "bcryptjs": "~2.2.1",
"body-parser": "^1.9.0", "body-parser": "^1.9.0",
"colors": "^1.1.0", "colors": "^1.1.0",
"compression": "^1.1.0", "compression": "^1.1.0",
"connect-ensure-login": "^0.1.1", "connect-ensure-login": "^0.1.1",
"connect-flash": "^0.1.1", "connect-flash": "^0.1.1",
"connect-multiparty": "^1.2.4", "connect-multiparty": "^2.0.0",
"cookie-parser": "^1.3.3", "cookie-parser": "^1.3.3",
"cron": "^1.0.5", "cron": "^1.0.5",
"csurf": "^1.6.1", "csurf": "^1.6.1",
@@ -40,40 +40,40 @@
"mmmagic": "^0.3.13", "mmmagic": "^0.3.13",
"morgan": "^1.3.2", "morgan": "^1.3.2",
"nconf": "~0.7.1", "nconf": "~0.7.1",
"nodebb-plugin-composer-default": "1.0.9", "nodebb-plugin-composer-default": "1.0.13",
"nodebb-plugin-dbsearch": "0.2.15", "nodebb-plugin-dbsearch": "0.2.16",
"nodebb-plugin-emoji-extended": "0.4.9", "nodebb-plugin-emoji-extended": "0.4.9",
"nodebb-plugin-markdown": "4.0.2", "nodebb-plugin-markdown": "4.0.5",
"nodebb-plugin-mentions": "1.0.0", "nodebb-plugin-mentions": "1.0.1",
"nodebb-plugin-soundpack-default": "0.1.2", "nodebb-plugin-soundpack-default": "0.1.4",
"nodebb-plugin-spam-be-gone": "0.4.1", "nodebb-plugin-spam-be-gone": "0.4.1",
"nodebb-rewards-essentials": "0.0.3", "nodebb-rewards-essentials": "0.0.5",
"nodebb-theme-lavender": "1.0.49", "nodebb-theme-lavender": "1.0.52",
"nodebb-theme-persona": "2.0.13", "nodebb-theme-persona": "2.1.8",
"nodebb-theme-vanilla": "3.0.7", "nodebb-theme-vanilla": "3.1.3",
"nodebb-widget-essentials": "1.0.4", "nodebb-widget-essentials": "1.0.6",
"npm": "^2.1.4", "npm": "^2.1.4",
"passport": "^0.2.1", "passport": "^0.3.0",
"passport-local": "1.0.0", "passport-local": "1.0.0",
"prompt": "^0.2.14", "prompt": "^0.2.14",
"request": "^2.44.0", "request": "^2.44.0",
"rimraf": "~2.3.2", "rimraf": "~2.4.2",
"rss": "^1.0.0", "rss": "^1.0.0",
"semver": "^4.3.3", "semver": "^5.0.1",
"serve-favicon": "^2.1.5", "serve-favicon": "^2.1.5",
"sitemap": "^0.8.1", "sitemap": "^1.0.0",
"socket.io": "^1.2.1", "socket.io": "^1.2.1",
"socket.io-client": "^1.2.1", "socket.io-client": "^1.2.1",
"socket.io-redis": "^0.1.3", "socket.io-redis": "^0.1.3",
"socketio-wildcard": "~0.1.1", "socketio-wildcard": "~0.1.1",
"string": "^3.0.0", "string": "^3.0.0",
"templates.js": "0.2.8", "templates.js": "0.2.10",
"touch": "0.0.3", "touch": "1.0.0",
"uglify-js": "^2.4.23", "uglify-js": "^2.4.23",
"underscore": "~1.8.3", "underscore": "~1.8.3",
"underscore.deep": "^0.5.1", "underscore.deep": "^0.5.1",
"validator": "^3.30.0", "validator": "^4.0.5",
"winston": "^0.9.0", "winston": "^1.0.1",
"xregexp": "~2.0.0" "xregexp": "~2.0.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,12 +1,12 @@
{ {
"category": "Category", "category": "فئة",
"subcategories": "Subcategories", "subcategories": "فئة فرعية",
"new_topic_button": "موضوع جديد", "new_topic_button": "موضوع جديد",
"guest-login-post": "يجب عليك تسجيل الدخول للرد", "guest-login-post": "يجب عليك تسجيل الدخول للرد",
"no_topics": "<strong>لا توجد مواضيع في هذه الفئة</strong>لم لا تحاول إنشاء موضوع؟<br />", "no_topics": "<strong>لا توجد مواضيع في هذه الفئة</strong>لم لا تحاول إنشاء موضوع؟<br />",
"browsing": "تصفح", "browsing": "تصفح",
"no_replies": "لا توجد ردود.", "no_replies": "لا توجد ردود.",
"no_new_posts": "No new posts.", "no_new_posts": "لا يوجد مشاركات جديدة.",
"share_this_category": "انشر هذه الفئة", "share_this_category": "انشر هذه الفئة",
"watch": "متابعة", "watch": "متابعة",
"ignore": "تجاهل", "ignore": "تجاهل",

View File

@@ -6,7 +6,7 @@
"greeting_with_name": "مرحبًا بك يا %1", "greeting_with_name": "مرحبًا بك يا %1",
"welcome.text1": "شكرًا على تسجيلك في %1!", "welcome.text1": "شكرًا على تسجيلك في %1!",
"welcome.text2": "لتفعيل حسابك، نحتاج إلى التأكد من صحة عنوان البريد الإلكتروني الذي سجلت به.", "welcome.text2": "لتفعيل حسابك، نحتاج إلى التأكد من صحة عنوان البريد الإلكتروني الذي سجلت به.",
"welcome.text3": "An administrator has accepted your registration application. You can login with your username/password now.", "welcome.text3": "تم قبول نتسجيلك ، يمكنك الدخول باتسخدام اسم المستخدم و كلمة المرور.",
"welcome.cta": "انقر هنا لتفعيل عنوان بريدك الإلكتروني", "welcome.cta": "انقر هنا لتفعيل عنوان بريدك الإلكتروني",
"invitation.text1": "%1 قام بدعوتك للانضمام لـ %2", "invitation.text1": "%1 قام بدعوتك للانضمام لـ %2",
"invitation.ctr": "إضغط هنا لإنشاء حسابك", "invitation.ctr": "إضغط هنا لإنشاء حسابك",

View File

@@ -6,12 +6,12 @@
"no_groups_found": "لاوجدود لمجموعات يمكن معاينتها", "no_groups_found": "لاوجدود لمجموعات يمكن معاينتها",
"pending.accept": "موافق", "pending.accept": "موافق",
"pending.reject": "رفض", "pending.reject": "رفض",
"pending.accept_all": "Accept All", "pending.accept_all": "قبول الكل",
"pending.reject_all": "Reject All", "pending.reject_all": "رفض الكل",
"pending.none": "There are no pending members at this time", "pending.none": "لايوجد أعضاء ينتظرون التفعيل حالياً",
"invited.none": "There are no invited members at this time", "invited.none": "لايوجد أعضاء مدعوون في حالياً",
"invited.uninvite": "Rescind Invitation", "invited.uninvite": "إلغ الدعوة",
"invited.search": "Search for a user to invite to this group", "invited.search": "ابحث عن أعضاء لدعوتهم للمجموعة",
"cover-instructions": "اسحب وأسقِط صورة، اسحبها للموضع المرغوب، وانقر على <strong>حفظ</strong>", "cover-instructions": "اسحب وأسقِط صورة، اسحبها للموضع المرغوب، وانقر على <strong>حفظ</strong>",
"cover-change": "تغيير", "cover-change": "تغيير",
"cover-save": "حفظ", "cover-save": "حفظ",
@@ -19,7 +19,7 @@
"details.title": "تفاصيل المجموعة", "details.title": "تفاصيل المجموعة",
"details.members": "لائحة الأعضاء", "details.members": "لائحة الأعضاء",
"details.pending": "المستخدمون في الانتظار", "details.pending": "المستخدمون في الانتظار",
"details.invited": "Invited Members", "details.invited": "اﻷعضار المدعوون",
"details.has_no_posts": "أعضاء هذه المجموعة لم يضيفوا أية مشاركة", "details.has_no_posts": "أعضاء هذه المجموعة لم يضيفوا أية مشاركة",
"details.latest_posts": "آخر المشاركات", "details.latest_posts": "آخر المشاركات",
"details.private": "خاص", "details.private": "خاص",
@@ -37,14 +37,14 @@
"details.userTitleEnabled": "إظهار الوسام", "details.userTitleEnabled": "إظهار الوسام",
"details.private_help": "في حالة تفعيل الخيار، الانضمام إلى المجموعة يستلزم قبول مالكها", "details.private_help": "في حالة تفعيل الخيار، الانضمام إلى المجموعة يستلزم قبول مالكها",
"details.hidden": "مخفي", "details.hidden": "مخفي",
"details.hidden_help": "في حالة تفعيل الخيار، لن تظهر المجموعة للعموم والإنضمام إليها سيتلزم دعوة يدوية.", "details.hidden_help": "في حالة تفعيل الخيار، لن تظهر المجموعة للعموم والإنضمام إليها سيتلزم دعوة.",
"details.delete_group": "حذف المجموعة", "details.delete_group": "حذف المجموعة",
"event.updated": "تم تحديث بيانات المجموعة", "event.updated": "تم تحديث بيانات المجموعة",
"event.deleted": "تم حذف المجموعة %1", "event.deleted": "تم حذف المجموعة %1",
"membership.accept-invitation": "Accept Invitation", "membership.accept-invitation": "اقبل الدعوة",
"membership.invitation-pending": "Invitation Pending", "membership.invitation-pending": "الدعوة بانتظار القبول",
"membership.join-group": "Join Group", "membership.join-group": "انظم للمجموعة",
"membership.leave-group": "Leave Group", "membership.leave-group": "غادر المجموعة",
"membership.reject": "Reject", "membership.reject": "رفض",
"new-group.group_name": "Group Name:" "new-group.group_name": "اسم المجموعة"
} }

View File

@@ -7,7 +7,7 @@
"email": "البريد الإلكتروني", "email": "البريد الإلكتروني",
"confirm_email": "تأكيد عنوان البريد الإلكتروني", "confirm_email": "تأكيد عنوان البريد الإلكتروني",
"ban_account": "Ban Account", "ban_account": "Ban Account",
"ban_account_confirm": "Do you really want to ban this user?", "ban_account_confirm": "هل تريد حقاً حظر هاذا العضو؟",
"unban_account": "Unban Account", "unban_account": "Unban Account",
"delete_account": "حذف الحساب", "delete_account": "حذف الحساب",
"delete_account_confirm": "هل أن متأكد أنك تريد حذف حسابك؟<br /><strong> هذه العملية غير قابلة للإلغاء ولن يكون بالإمكان استعادة بياناتك</strong><br /><br />أدخل اسم المستخدم الخاص بك لتأكيد عملية الحذف", "delete_account_confirm": "هل أن متأكد أنك تريد حذف حسابك؟<br /><strong> هذه العملية غير قابلة للإلغاء ولن يكون بالإمكان استعادة بياناتك</strong><br /><br />أدخل اسم المستخدم الخاص بك لتأكيد عملية الحذف",

View File

@@ -1,12 +1,12 @@
{ {
"category": "Category", "category": "Kategorie",
"subcategories": "Subcategories", "subcategories": "Unterkategorien",
"new_topic_button": "Neues Thema", "new_topic_button": "Neues Thema",
"guest-login-post": "Anmelden um einen Beitrag zu erstellen", "guest-login-post": "Anmelden um einen Beitrag zu erstellen",
"no_topics": "<strong>Es gibt noch keine Themen in dieser Kategorie.</strong><br />Warum beginnst du nicht eins?", "no_topics": "<strong>Es gibt noch keine Themen in dieser Kategorie.</strong><br />Warum beginnst du nicht eins?",
"browsing": "Aktiv", "browsing": "Aktiv",
"no_replies": "Niemand hat geantwortet", "no_replies": "Niemand hat geantwortet",
"no_new_posts": "No new posts.", "no_new_posts": "Keine neue Beiträge.",
"share_this_category": "Teile diese Kategorie", "share_this_category": "Teile diese Kategorie",
"watch": "Beobachten", "watch": "Beobachten",
"ignore": "Ignorieren", "ignore": "Ignorieren",

View File

@@ -46,8 +46,8 @@
"too-many-posts-newbie": "Als neuer Benutzer können Sie nur einen Beitrag innerhalb von %1 Sekunden erstellen - Bitte warten Sie bevor Sie erneut einen Beitrag erstellen.", "too-many-posts-newbie": "Als neuer Benutzer können Sie nur einen Beitrag innerhalb von %1 Sekunden erstellen - Bitte warten Sie bevor Sie erneut einen Beitrag erstellen.",
"tag-too-short": "Bitte geben Sie ein längeres Schlagwort ein. Tags sollten mindestens %1 Zeichen enthalten.", "tag-too-short": "Bitte geben Sie ein längeres Schlagwort ein. Tags sollten mindestens %1 Zeichen enthalten.",
"tag-too-long": "Bitte geben Sie ein kürzeres Schlagwort ein. Tags können nicht länger als %1 Zeichen sein.", "tag-too-long": "Bitte geben Sie ein kürzeres Schlagwort ein. Tags können nicht länger als %1 Zeichen sein.",
"not-enough-tags": "Not enough tags. Topics must have at least %1 tag(s)", "not-enough-tags": "Nicht genügend Tags. Themen müssen mindestens %1 Tag(s) enthalten",
"too-many-tags": "Too many tags. Topics can't have more than %1 tag(s)", "too-many-tags": "Zu viele Tags. Themen dürfen nicht mehr als %1 Tag(s) enthalten",
"file-too-big": "Die maximale Dateigröße ist %1 kB, bitte laden Sie eine kleinere Datei hoch.", "file-too-big": "Die maximale Dateigröße ist %1 kB, bitte laden Sie eine kleinere Datei hoch.",
"cant-vote-self-post": "Du kannst deinen eigenen Beitrag nicht bewerten", "cant-vote-self-post": "Du kannst deinen eigenen Beitrag nicht bewerten",
"already-favourited": "Dieser Beitrag ist bereits in deinen Favoriten enthalten", "already-favourited": "Dieser Beitrag ist bereits in deinen Favoriten enthalten",

View File

@@ -22,7 +22,7 @@
"pagination.out_of": "%1 von %2", "pagination.out_of": "%1 von %2",
"pagination.enter_index": "Seitenzahl eingeben", "pagination.enter_index": "Seitenzahl eingeben",
"header.admin": "Admin", "header.admin": "Admin",
"header.categories": "Categories", "header.categories": "Kategorien",
"header.recent": "Aktuell", "header.recent": "Aktuell",
"header.unread": "Ungelesen", "header.unread": "Ungelesen",
"header.tags": "Tags", "header.tags": "Tags",

View File

@@ -38,13 +38,13 @@
"details.private_help": "Wenn aktiviert, setzt ein Gruppenbeitritt die Zustimmung eines Gruppenbesitzers voraus", "details.private_help": "Wenn aktiviert, setzt ein Gruppenbeitritt die Zustimmung eines Gruppenbesitzers voraus",
"details.hidden": "Versteckt", "details.hidden": "Versteckt",
"details.hidden_help": "Wenn aktiviert, wird diese Gruppe in der Gruppenliste nicht zu finden sein, und Benutzer werden manuell eingeladen werden müssen.", "details.hidden_help": "Wenn aktiviert, wird diese Gruppe in der Gruppenliste nicht zu finden sein, und Benutzer werden manuell eingeladen werden müssen.",
"details.delete_group": "Delete Group", "details.delete_group": "Gruppe löschen",
"event.updated": "Gruppendetails wurden aktualisiert", "event.updated": "Gruppendetails wurden aktualisiert",
"event.deleted": "Die Gruppe \"%1\" wurde gelöscht.", "event.deleted": "Die Gruppe \"%1\" wurde gelöscht.",
"membership.accept-invitation": "Accept Invitation", "membership.accept-invitation": "Einladung akzeptieren",
"membership.invitation-pending": "Invitation Pending", "membership.invitation-pending": "Einladung ausstehend",
"membership.join-group": "Join Group", "membership.join-group": "Gruppe beitreten",
"membership.leave-group": "Leave Group", "membership.leave-group": "Gruppe verlassen",
"membership.reject": "Reject", "membership.reject": "Ablehnen",
"new-group.group_name": "Group Name:" "new-group.group_name": "Gruppenname:"
} }

View File

@@ -39,6 +39,7 @@
"header.notifications": "Notifications", "header.notifications": "Notifications",
"header.search": "Search", "header.search": "Search",
"header.profile": "Profile", "header.profile": "Profile",
"header.navigation": "Navigation",
"notifications.loading": "Loading Notifications", "notifications.loading": "Loading Notifications",
"chats.loading": "Loading Chats", "chats.loading": "Loading Chats",
@@ -87,7 +88,7 @@
"online": "Online", "online": "Online",
"away": "Away", "away": "Away",
"dnd": "Do not Disturb", "dnd": "Do not disturb",
"invisible": "Invisible", "invisible": "Invisible",
"offline": "Offline", "offline": "Offline",

View File

@@ -5,7 +5,7 @@
"chat.no_active": "You have no active chats.", "chat.no_active": "You have no active chats.",
"chat.user_typing": "%1 is typing ...", "chat.user_typing": "%1 is typing ...",
"chat.user_has_messaged_you": "%1 has messaged you.", "chat.user_has_messaged_you": "%1 has messaged you.",
"chat.see_all": "See all Chats", "chat.see_all": "See all chats",
"chat.no-messages": "Please select a recipient to view chat message history", "chat.no-messages": "Please select a recipient to view chat message history",
"chat.recent-chats": "Recent Chats", "chat.recent-chats": "Recent Chats",
"chat.contacts": "Contacts", "chat.contacts": "Contacts",
@@ -23,5 +23,9 @@
"composer.user_said": "%1 said:", "composer.user_said": "%1 said:",
"composer.discard": "Are you sure you wish to discard this post?", "composer.discard": "Are you sure you wish to discard this post?",
"composer.submit_and_lock": "Submit and Lock", "composer.submit_and_lock": "Submit and Lock",
"composer.toggle_dropdown": "Toggle Dropdown" "composer.toggle_dropdown": "Toggle Dropdown",
"bootbox.ok": "OK",
"bootbox.cancel": "Cancel",
"bootbox.confirm": "Confirm"
} }

View File

@@ -1,7 +1,7 @@
{ {
"title": "Notifications", "title": "Notifications",
"no_notifs": "You have no new notifications", "no_notifs": "You have no new notifications",
"see_all": "See all Notifications", "see_all": "See all notifications",
"mark_all_read": "Mark all notifications read", "mark_all_read": "Mark all notifications read",
"back_to_home": "Back to %1", "back_to_home": "Back to %1",

View File

@@ -1,21 +1,42 @@
{ {
"home": "Home", "home": "Home",
"unread": "Unread Topics", "unread": "Unread Topics",
"popular": "Popular Topics", "popular-day": "Popular topics today",
"popular-week": "Popular topics this week",
"popular-month": "Popular topics this month",
"popular-alltime": "All time popular topics",
"recent": "Recent Topics", "recent": "Recent Topics",
"users": "Registered Users",
"users/online": "Online Users",
"users/latest": "Latest Users",
"users/sort-posts": "Users with the most posts",
"users/sort-reputation": "Users with the most reputation",
"users/map": "User Map",
"users/search": "User Search",
"notifications": "Notifications", "notifications": "Notifications",
"tags": "Tags", "tags": "Tags",
"tag": "Topics tagged under \"%1\"", "tag": "Topics tagged under \"%1\"",
"user.edit": "Editing \"%1\"", "register": "Register an account",
"user.following": "People %1 Follows", "login": "Login to your account",
"user.followers": "People who Follow %1", "reset": "Reset your account password",
"user.posts": "Posts made by %1", "categories": "Categories",
"user.topics": "Topics created by %1",
"user.groups": "%1's Groups", "groups": "Groups",
"user.favourites": "%1's Favourite Posts", "group": "%1 group",
"user.settings": "User Settings",
"user.watched": "Topics watched by %1", "chats": "Chats",
"chat": "Chatting with %1",
"account/edit": "Editing \"%1\"",
"account/following": "People %1 follows",
"account/followers": "People who follow %1",
"account/posts": "Posts made by %1",
"account/topics": "Topics created by %1",
"account/groups": "%1's Groups",
"account/favourites": "%1's Favourite Posts",
"account/settings": "User Settings",
"account/watched": "Topics watched by %1",
"maintenance.text": "%1 is currently undergoing maintenance. Please come back another time.", "maintenance.text": "%1 is currently undergoing maintenance. Please come back another time.",
"maintenance.messageIntro": "Additionally, the administrator has left this message:" "maintenance.messageIntro": "Additionally, the administrator has left this message:"

View File

@@ -50,8 +50,8 @@
"too-many-tags": "Too many tags. Topics can't have more than %1 tag(s)", "too-many-tags": "Too many tags. Topics can't have more than %1 tag(s)",
"file-too-big": "Maximum allowed file size is %1 kB - please upload a smaller file", "file-too-big": "Maximum allowed file size is %1 kB - please upload a smaller file",
"cant-vote-self-post": "You cannot vote for your own post", "cant-vote-self-post": "You cannot vote for your own post",
"already-favourited": "You have already favourited this post", "already-favourited": "You have already favorited this post",
"already-unfavourited": "You have already unfavourited this post", "already-unfavourited": "You have already unfavorited this post",
"cant-ban-other-admins": "You can't ban other admins!", "cant-ban-other-admins": "You can't ban other admins!",
"cant-remove-last-admin": "You are the only administrator. Add another user as an administrator before removing yourself as admin", "cant-remove-last-admin": "You are the only administrator. Add another user as an administrator before removing yourself as admin",
"invalid-image-type": "Invalid image type. Allowed types are: %1", "invalid-image-type": "Invalid image type. Allowed types are: %1",

View File

@@ -32,7 +32,7 @@
"details.description": "Description", "details.description": "Description",
"details.badge_preview": "Badge Preview", "details.badge_preview": "Badge Preview",
"details.change_icon": "Change Icon", "details.change_icon": "Change Icon",
"details.change_colour": "Change Colour", "details.change_colour": "Change Color",
"details.badge_text": "Badge Text", "details.badge_text": "Badge Text",
"details.userTitleEnabled": "Show Badge", "details.userTitleEnabled": "Show Badge",
"details.private_help": "If enabled, joining of groups requires approval from a group owner", "details.private_help": "If enabled, joining of groups requires approval from a group owner",

View File

@@ -14,7 +14,7 @@
"upvoted_your_post_in": "<strong>%1</strong> has upvoted your post in <strong>%2</strong>.", "upvoted_your_post_in": "<strong>%1</strong> has upvoted your post in <strong>%2</strong>.",
"moved_your_post": "<strong>%1</strong> has moved your post.", "moved_your_post": "<strong>%1</strong> has moved your post.",
"moved_your_topic": "<strong>%1</strong> has moved your topic.", "moved_your_topic": "<strong>%1</strong> has moved your topic.",
"favourited_your_post_in": "<strong>%1</strong> has favourited your post in <strong>%2</strong>.", "favourited_your_post_in": "<strong>%1</strong> has favorited your post in <strong>%2</strong>.",
"user_flagged_post_in": "<strong>%1</strong> flagged a post in <strong>%2</strong>", "user_flagged_post_in": "<strong>%1</strong> flagged a post in <strong>%2</strong>",
"user_posted_to": "<strong>%1</strong> has posted a reply to: <strong>%2</strong>", "user_posted_to": "<strong>%1</strong> has posted a reply to: <strong>%2</strong>",
"user_posted_topic": "<strong>%1</strong> has posted a new topic: <strong>%2</strong>", "user_posted_topic": "<strong>%1</strong> has posted a new topic: <strong>%2</strong>",

View File

@@ -1,12 +1,12 @@
{ {
"category": "Category", "category": "Categoría",
"subcategories": "Subcategories", "subcategories": "Subcategorías",
"new_topic_button": "Nuevo tema", "new_topic_button": "Nuevo tema",
"guest-login-post": "Acceder para poder escribir un mensaje", "guest-login-post": "Acceder para poder escribir un mensaje",
"no_topics": "<strong>No hay temas en esta categoría.</strong><br />¿Por qué no te animas y publicas uno?", "no_topics": "<strong>No hay temas en esta categoría.</strong><br />¿Por qué no te animas y publicas uno?",
"browsing": "viendo ahora", "browsing": "viendo ahora",
"no_replies": "Nadie ha respondido aún", "no_replies": "Nadie ha respondido aún",
"no_new_posts": "No new posts.", "no_new_posts": "No hay mensajes nuevos.",
"share_this_category": "Compartir esta categoría", "share_this_category": "Compartir esta categoría",
"watch": "Seguir", "watch": "Seguir",
"ignore": "Ignorar", "ignore": "Ignorar",

View File

@@ -46,5 +46,5 @@
"membership.join-group": "Unirse al grupo", "membership.join-group": "Unirse al grupo",
"membership.leave-group": "Dejar el grupo", "membership.leave-group": "Dejar el grupo",
"membership.reject": "Rechazar", "membership.reject": "Rechazar",
"new-group.group_name": "Group Name:" "new-group.group_name": "Nombre de Grupo:"
} }

View File

@@ -2,7 +2,7 @@
"title": "Notificaciones", "title": "Notificaciones",
"no_notifs": "No tienes nuevas notificaciones", "no_notifs": "No tienes nuevas notificaciones",
"see_all": "Ver todas las notificaciones", "see_all": "Ver todas las notificaciones",
"mark_all_read": "Marcar todas las notificaciones cómo leídas", "mark_all_read": "Marcar todas las notificaciones como leídas",
"back_to_home": "Volver a %1", "back_to_home": "Volver a %1",
"outgoing_link": "Enlace externo", "outgoing_link": "Enlace externo",
"outgoing_link_message": "Ahora estás saliendo de %1.", "outgoing_link_message": "Ahora estás saliendo de %1.",

View File

@@ -1,15 +1,15 @@
{ {
"category": "Category", "category": "شاخه",
"subcategories": "Subcategories", "subcategories": "زیر شاخه ها",
"new_topic_button": "جستار تازه", "new_topic_button": "جستار تازه",
"guest-login-post": "برای ثبت نظر وارد شوید", "guest-login-post": "برای ثبت نظر وارد شوید",
"no_topics": "<strong>هیچ پستی در این دسته نیست.</strong><br />چرا شما یکی نفرستید؟", "no_topics": "<strong>هیچ پستی در این دسته نیست.</strong><br />چرا شما یکی نفرستید؟",
"browsing": "بیننده‌ها", "browsing": "بیننده‌ها",
"no_replies": "هیچ کسی پاسخ نداده است.", "no_replies": "هیچ کسی پاسخ نداده است.",
"no_new_posts": "No new posts.", "no_new_posts": "هیچ پست جدیدی موجود نیست.",
"share_this_category": "به اشتراک‌گذاری این دسته", "share_this_category": "به اشتراک‌گذاری این شاخه",
"watch": "نظارت کردن", "watch": "نظارت کردن",
"ignore": "نادیده گرفتن", "ignore": "نادیده گرفتن",
"watch.message": "در حال حاظر شما به روز رسانی های این دسته را دنبال می کنید", "watch.message": "در حال حاظر شما به روز رسانی های این شاخه را دنبال می کنید",
"ignore.message": "در حال حاظر شما به روز رسانی های این دسته را نادیده میگیرد" "ignore.message": "در حال حاظر شما به روز رسانی های این شاخه را نادیده میگیرد"
} }

View File

@@ -2,7 +2,7 @@
"invalid-data": "داده(های) نامعتبر", "invalid-data": "داده(های) نامعتبر",
"not-logged-in": "به نظر میرسد که با حساب کاربری وارد نشده اید.", "not-logged-in": "به نظر میرسد که با حساب کاربری وارد نشده اید.",
"account-locked": "حساب کاربری شما موقتاً مسدود شده است.", "account-locked": "حساب کاربری شما موقتاً مسدود شده است.",
"search-requires-login": "Searching requires an account - please login or register.", "search-requires-login": "استفاده از جستجو نیازمند ورود با نام کاربری و رمز عبور است. لطفا ابتدا وارد شوید. ",
"invalid-cid": "شناسه دسته نامعتبر است.", "invalid-cid": "شناسه دسته نامعتبر است.",
"invalid-tid": "شناسه جستار نامعتبر است.", "invalid-tid": "شناسه جستار نامعتبر است.",
"invalid-pid": "شناسه دیدگاه نامعتبر است.", "invalid-pid": "شناسه دیدگاه نامعتبر است.",
@@ -39,7 +39,7 @@
"post-edit-duration-expired": "شما تنها می توانید %1 ثانیه پس از فرستادن دیدگاه آن‌را ویرایش کنید", "post-edit-duration-expired": "شما تنها می توانید %1 ثانیه پس از فرستادن دیدگاه آن‌را ویرایش کنید",
"still-uploading": "خواهشمندیم تا پایان بارگذاری‌ها شکیبا باشید.", "still-uploading": "خواهشمندیم تا پایان بارگذاری‌ها شکیبا باشید.",
"content-too-short": "خواهشمندیم دیدگاه بلندتری بنویسید. دیدگاه‌ها دست‌کم باید 1% نویسه داشته باشند.", "content-too-short": "خواهشمندیم دیدگاه بلندتری بنویسید. دیدگاه‌ها دست‌کم باید 1% نویسه داشته باشند.",
"content-too-long": "Please enter a shorter post. Posts can't be longer than %1 character(s).", "content-too-long": "لطفا طول مطلب را کوتاه تر کنید. طول پست نمیتواند بیشتر از %1 کاراکتر باشد.",
"title-too-short": "Please enter a longer title. Titles should contain at least %1 character(s).", "title-too-short": "Please enter a longer title. Titles should contain at least %1 character(s).",
"title-too-long": "Please enter a shorter title. Titles can't be longer than %1 character(s).", "title-too-long": "Please enter a shorter title. Titles can't be longer than %1 character(s).",
"too-many-posts": "You can only post once every %1 second(s) - please wait before posting again", "too-many-posts": "You can only post once every %1 second(s) - please wait before posting again",

View File

@@ -22,7 +22,7 @@
"pagination.out_of": "%1 از %2", "pagination.out_of": "%1 از %2",
"pagination.enter_index": "شماره را وارد کنید", "pagination.enter_index": "شماره را وارد کنید",
"header.admin": "مدیر", "header.admin": "مدیر",
"header.categories": "Categories", "header.categories": "شاخه ها",
"header.recent": "تازه‌ها", "header.recent": "تازه‌ها",
"header.unread": "نخوانده‌ها", "header.unread": "نخوانده‌ها",
"header.tags": "برچسب‌ها", "header.tags": "برچسب‌ها",
@@ -51,7 +51,7 @@
"views": "بازدیدها", "views": "بازدیدها",
"reputation": "اعتبار", "reputation": "اعتبار",
"read_more": "بیشتر بخوانید", "read_more": "بیشتر بخوانید",
"more": "More", "more": "بیشتر",
"posted_ago_by_guest": "ارسال شده در %1 توسط مهمان", "posted_ago_by_guest": "ارسال شده در %1 توسط مهمان",
"posted_ago_by": "ارسال شده در %1 توسط %2", "posted_ago_by": "ارسال شده در %1 توسط %2",
"posted_ago": "ارسال شده در %1", "posted_ago": "ارسال شده در %1",

View File

@@ -6,20 +6,20 @@
"no_groups_found": "گروهی برای دیدن وجود ندارد", "no_groups_found": "گروهی برای دیدن وجود ندارد",
"pending.accept": "قبول", "pending.accept": "قبول",
"pending.reject": "رد", "pending.reject": "رد",
"pending.accept_all": "Accept All", "pending.accept_all": "پذیرش همه",
"pending.reject_all": "Reject All", "pending.reject_all": "رد همه",
"pending.none": "There are no pending members at this time", "pending.none": "در حال حاضر هیچ عضوی در انتظار نیست",
"invited.none": "There are no invited members at this time", "invited.none": "در حال حاضر هیچ کسی دعوت نشده است",
"invited.uninvite": "Rescind Invitation", "invited.uninvite": "لغو دعوت",
"invited.search": "Search for a user to invite to this group", "invited.search": "جستجو به دنبال کاربرانی به جهت دعوت به این گروه",
"cover-instructions": "کشیدن و انداختن عکس، به محل بکشید، و <strong>ذخیره</strong> را بزنید", "cover-instructions": "عکس را با کلیک موس بگیرید و بکشید به محل و رها کنید، سپس <strong>ذخیره</strong> را بزنید",
"cover-change": "تغییر", "cover-change": "تغییر",
"cover-save": "ذخیره", "cover-save": "ذخیره",
"cover-saving": "در حال ذخیره کردن", "cover-saving": "در حال ذخیره کردن",
"details.title": "جزئیات گروه", "details.title": "جزئیات گروه",
"details.members": "لیست اعضا", "details.members": "لیست اعضا",
"details.pending": "اعضای در انتظار", "details.pending": "اعضای در انتظار",
"details.invited": "Invited Members", "details.invited": "اعضای دعوت شده",
"details.has_no_posts": "اعضای این گروه هیچ دیدگاهی ایجاد نکرده اند", "details.has_no_posts": "اعضای این گروه هیچ دیدگاهی ایجاد نکرده اند",
"details.latest_posts": "آخرین دیدگاه ها", "details.latest_posts": "آخرین دیدگاه ها",
"details.private": "خصوصی", "details.private": "خصوصی",
@@ -38,13 +38,13 @@
"details.private_help": "اگر فعال باشد، پیوستن به گروه مستلزم موافقت صاحب گروه است", "details.private_help": "اگر فعال باشد، پیوستن به گروه مستلزم موافقت صاحب گروه است",
"details.hidden": "پنهان", "details.hidden": "پنهان",
"details.hidden_help": "اگر فعال باشد، این گروه در فهرست گروه‌ها پیدا نمی‌شود و کاربران باید دستی فراخوانده شوند", "details.hidden_help": "اگر فعال باشد، این گروه در فهرست گروه‌ها پیدا نمی‌شود و کاربران باید دستی فراخوانده شوند",
"details.delete_group": "Delete Group", "details.delete_group": "حذف گروه",
"event.updated": "جزییات گروه با موفقیت به روز گردید", "event.updated": "جزییات گروه با موفقیت به روز گردید",
"event.deleted": "گروه \"%1\" حدف شد", "event.deleted": "گروه \"%1\" حدف شد",
"membership.accept-invitation": "Accept Invitation", "membership.accept-invitation": "دعوت را قبول میکنم",
"membership.invitation-pending": "Invitation Pending", "membership.invitation-pending": "در انتظار تایید",
"membership.join-group": "Join Group", "membership.join-group": "ورود به گروه",
"membership.leave-group": "Leave Group", "membership.leave-group": "خروج از گروه",
"membership.reject": "Reject", "membership.reject": "رد",
"new-group.group_name": "Group Name:" "new-group.group_name": "نام گروه"
} }

View File

@@ -1,7 +1,7 @@
{ {
"topic": "جُستار", "topic": "جُستار",
"topic_id": "ID جستار", "topic_id": "شناسه جستار",
"topic_id_placeholder": "ID جستار را بنویسید", "topic_id_placeholder": "شناسه جستار را بنویسید",
"no_topics_found": "هیچ جستاری یافت نشد!", "no_topics_found": "هیچ جستاری یافت نشد!",
"no_posts_found": "دیدگاهی یافت نشد!", "no_posts_found": "دیدگاهی یافت نشد!",
"post_is_deleted": "این دیدگاه پاک شده!", "post_is_deleted": "این دیدگاه پاک شده!",

View File

@@ -6,19 +6,19 @@
"postcount": "تعداد دیدگاه ها", "postcount": "تعداد دیدگاه ها",
"email": "رایانامه", "email": "رایانامه",
"confirm_email": "تأیید رایانامه", "confirm_email": "تأیید رایانامه",
"ban_account": "Ban Account", "ban_account": "مسدود کردن حساب کاربری",
"ban_account_confirm": "Do you really want to ban this user?", "ban_account_confirm": "از مسدود کردن این کاربر اطمینان دارید؟",
"unban_account": "Unban Account", "unban_account": "آزاد کردن حساب کاربری",
"delete_account": "حذف حساب کاربری", "delete_account": "حذف حساب کاربری",
"delete_account_confirm": "آیا مطمئنید که میخواهید حساب کاربری خود را حذف کنید؟ <br /><strong>این عمل غیر قابل بازگشت است و شما قادر نخواهید بود هیچ کدام از اطلاعات خود را بازیابی کنید./strong><br /><br /> برای تایید حذف این حساب کاربری، نام کاربری خود را وارد کنید", "delete_account_confirm": "آیا مطمئنید که میخواهید حساب کاربری خود را حذف کنید؟ <br /><strong>این عمل غیر قابل بازگشت است و شما قادر نخواهید بود هیچ کدام از اطلاعات خود را بازیابی کنید./strong><br /><br /> برای تایید حذف این حساب کاربری، نام کاربری خود را وارد کنید",
"delete_this_account_confirm": "Are you sure you want to delete this account? <br /><strong>This action is irreversible and you will not be able to recover any data</strong><br /><br />", "delete_this_account_confirm": " آیا مطمئنید که میخواهید این حساب کاربری را حذف کنید؟<br/><strong>این عمل غیر قابل بازگشت است و شما قادر نخواهید بود هیچ کدام از اطلاعات را بازیابی کنید.</strong><br/><br/> ",
"fullname": "نام کامل", "fullname": "نام و نام خانوادگی",
"website": "تارنما", "website": "تارنما",
"location": "محل سکونت", "location": "محل سکونت",
"age": "سن", "age": "سن",
"joined": "عضو شده", "joined": "عضو شده",
"lastonline": "آخرین حضور", "lastonline": "آخرین حضور",
"profile": "نمایه", "profile": "پروفایل",
"profile_views": "بازدیدهای نمایه", "profile_views": "بازدیدهای نمایه",
"reputation": "اعتبار", "reputation": "اعتبار",
"favourites": "پسندها", "favourites": "پسندها",
@@ -73,7 +73,7 @@
"has_no_watched_topics": "این کاربر تا به حال هیچ جستاری را نپاییده است", "has_no_watched_topics": "این کاربر تا به حال هیچ جستاری را نپاییده است",
"email_hidden": "رایانامه پنهان شده", "email_hidden": "رایانامه پنهان شده",
"hidden": "پنهان", "hidden": "پنهان",
"paginate_description": "Paginate topics and posts instead of using infinite scroll", "paginate_description": "صفحه بندی و نمایش جستارها و دیدگاه‌ها به جای نمایش بر اساس اسکرول موس",
"topics_per_page": "شمار جستارها در هر برگه", "topics_per_page": "شمار جستارها در هر برگه",
"posts_per_page": "شمار دیدگاه‌ها در هر برگه", "posts_per_page": "شمار دیدگاه‌ها در هر برگه",
"notification_sounds": "پخش صدا زمانی که یک آگاه سازی دریافت میکنید", "notification_sounds": "پخش صدا زمانی که یک آگاه سازی دریافت میکنید",

View File

@@ -1,12 +1,12 @@
{ {
"category": "Category", "category": "Kategori",
"subcategories": "Subcategories", "subcategories": "Underkategorier",
"new_topic_button": "Nytt emne", "new_topic_button": "Nytt emne",
"guest-login-post": "Logg inn til innlegg", "guest-login-post": "Logg inn til innlegg",
"no_topics": "<strong>Det er ingen emner i denne kategorien</strong><br />Hvorfor ikke lage et?", "no_topics": "<strong>Det er ingen emner i denne kategorien</strong><br />Hvorfor ikke lage et?",
"browsing": "leser", "browsing": "leser",
"no_replies": "Ingen har svart", "no_replies": "Ingen har svart",
"no_new_posts": "No new posts.", "no_new_posts": "Ingen nye innlegg.",
"share_this_category": "Del denne kategorien", "share_this_category": "Del denne kategorien",
"watch": "Overvåk", "watch": "Overvåk",
"ignore": "Ignorer", "ignore": "Ignorer",

View File

@@ -1,14 +1,14 @@
{ {
"password-reset-requested": "Tilbakestilling av passord - %1!", "password-reset-requested": "Tilbakestilling av passord - %1!",
"welcome-to": "Velkommen til %1", "welcome-to": "Velkommen til %1",
"invite": "Invitation from %1", "invite": "Invitasjon fra %1",
"greeting_no_name": "Hallo", "greeting_no_name": "Hallo",
"greeting_with_name": "Hallo, %1", "greeting_with_name": "Hallo, %1",
"welcome.text1": "Takk for at du registrerte deg hos %1!", "welcome.text1": "Takk for at du registrerte deg hos %1!",
"welcome.text2": "For å aktivere kontoen din må vi verifisere at du eier e-postadressen du registrerte med.", "welcome.text2": "For å aktivere kontoen din må vi verifisere at du eier e-postadressen du registrerte med.",
"welcome.text3": "An administrator has accepted your registration application. You can login with your username/password now.", "welcome.text3": "En administrator har akseptert din søknad om registering. Du kan nå logge inn med ditt brukernavn og passord.",
"welcome.cta": "Klikk her for å verifisere e-postadressen din", "welcome.cta": "Klikk her for å verifisere e-postadressen din",
"invitation.text1": "%1 has invited you to join %2", "invitation.text1": "%1 har invitert deg til å bli med i %2",
"invitation.ctr": "Click here to create your account.", "invitation.ctr": "Click here to create your account.",
"reset.text1": "Vi har blir bedt om å tilbakestille passordet ditt, muligens fordi du har glemt det. Hvis dette ikke stemmer kan du ignorere denne eposten.", "reset.text1": "Vi har blir bedt om å tilbakestille passordet ditt, muligens fordi du har glemt det. Hvis dette ikke stemmer kan du ignorere denne eposten.",
"reset.text2": "For å fortsette med tilbakestillingen, vennligst klikk på følgende lenke:", "reset.text2": "For å fortsette med tilbakestillingen, vennligst klikk på følgende lenke:",

View File

@@ -8,10 +8,10 @@
"pending.reject": "Avslå", "pending.reject": "Avslå",
"pending.accept_all": "Aksepter al", "pending.accept_all": "Aksepter al",
"pending.reject_all": "Avslå alle", "pending.reject_all": "Avslå alle",
"pending.none": "There are no pending members at this time", "pending.none": "Det er ingen ventende medlemmer på dette tidspunktet",
"invited.none": "There are no invited members at this time", "invited.none": "Det er ingen inviterte medlemmer på dette tidspunktet",
"invited.uninvite": "Rescind Invitation", "invited.uninvite": "Trekk tilbake invitasjon",
"invited.search": "Search for a user to invite to this group", "invited.search": "Søk etter en bruker å invitere til denne gruppen",
"cover-instructions": "Dra og slipp et bilde, dra til posisjon, og trykk <strong>Lagre</strong>", "cover-instructions": "Dra og slipp et bilde, dra til posisjon, og trykk <strong>Lagre</strong>",
"cover-change": "Endre", "cover-change": "Endre",
"cover-save": "Lagre", "cover-save": "Lagre",
@@ -19,7 +19,7 @@
"details.title": "Gruppedetaljer", "details.title": "Gruppedetaljer",
"details.members": "Medlemsliste", "details.members": "Medlemsliste",
"details.pending": "Ventende meldemmer", "details.pending": "Ventende meldemmer",
"details.invited": "Invited Members", "details.invited": "Inviterte medlemmer",
"details.has_no_posts": "Medlemmene i denne gruppen har ikke skrevet noen innlegg.", "details.has_no_posts": "Medlemmene i denne gruppen har ikke skrevet noen innlegg.",
"details.latest_posts": "Seneste innlegg", "details.latest_posts": "Seneste innlegg",
"details.private": "Privat", "details.private": "Privat",
@@ -38,13 +38,13 @@
"details.private_help": "Hvis aktivert, vil medlemskap i grupper kreve godkjennelse fra en gruppe-eier", "details.private_help": "Hvis aktivert, vil medlemskap i grupper kreve godkjennelse fra en gruppe-eier",
"details.hidden": "Skjult", "details.hidden": "Skjult",
"details.hidden_help": "vis aktivert, vil denne gruppen ikke bli funnet i gruppelista, og brukere må inviteres manuellt", "details.hidden_help": "vis aktivert, vil denne gruppen ikke bli funnet i gruppelista, og brukere må inviteres manuellt",
"details.delete_group": "Delete Group", "details.delete_group": "Slett gruppe",
"event.updated": "Gruppedetaljer har blitt oppgradert", "event.updated": "Gruppedetaljer har blitt oppgradert",
"event.deleted": "Gruppen \"%1\" har blitt slettet", "event.deleted": "Gruppen \"%1\" har blitt slettet",
"membership.accept-invitation": "Accept Invitation", "membership.accept-invitation": "Aksepter invitasjon",
"membership.invitation-pending": "Invitation Pending", "membership.invitation-pending": "Invitasjon venter",
"membership.join-group": "Join Group", "membership.join-group": "Bli med i gruppe",
"membership.leave-group": "Leave Group", "membership.leave-group": "Forlat gruppe",
"membership.reject": "Reject", "membership.reject": "Avslå",
"new-group.group_name": "Group Name:" "new-group.group_name": "Gruppenavn"
} }

View File

@@ -5,6 +5,6 @@
"mark_as_read": "Marker som lest", "mark_as_read": "Marker som lest",
"selected": "Valgte", "selected": "Valgte",
"all": "Alle", "all": "Alle",
"all_categories": "All categories", "all_categories": "Alle kategorier",
"topics_marked_as_read.success": "Emner merket som lest!" "topics_marked_as_read.success": "Emner merket som lest!"
} }

View File

@@ -6,12 +6,12 @@
"postcount": "Antall innlegg", "postcount": "Antall innlegg",
"email": "E-post", "email": "E-post",
"confirm_email": "Bekfreft e-post", "confirm_email": "Bekfreft e-post",
"ban_account": "Ban Account", "ban_account": "Utesteng kont",
"ban_account_confirm": "Do you really want to ban this user?", "ban_account_confirm": "Vil du virkelig utestenge denne brukeren?",
"unban_account": "Unban Account", "unban_account": "Opphev utestenging",
"delete_account": "Slett konto", "delete_account": "Slett konto",
"delete_account_confirm": "Er du sikker på at du vil slette kontoen din?<br /><strong>Dette kan ikke reverseres, og du vil ikke kunne hente tilbake dine data.</strong><br /><br />Skriv inn ditt brukernavn for å bekrefte at du vil tilintetgjøre denne kontoen.", "delete_account_confirm": "Er du sikker på at du vil slette kontoen din?<br /><strong>Dette kan ikke reverseres, og du vil ikke kunne hente tilbake dine data.</strong><br /><br />Skriv inn ditt brukernavn for å bekrefte at du vil tilintetgjøre denne kontoen.",
"delete_this_account_confirm": "Are you sure you want to delete this account? <br /><strong>This action is irreversible and you will not be able to recover any data</strong><br /><br />", "delete_this_account_confirm": "Er du sikker på at du vil slette denne kontoen? <br /><strong>Denne handlingen kan ikke reverseres og du vil ikke kunne gjenopprette noe data</strong><br /><br />",
"fullname": "Fullt navn", "fullname": "Fullt navn",
"website": "Nettsted", "website": "Nettsted",
"location": "Plassering", "location": "Plassering",
@@ -68,9 +68,9 @@
"settings-require-reload": "Noen innstillingsendringer krever at du laster siden på nytt. Klikk her for å laste på nytt.", "settings-require-reload": "Noen innstillingsendringer krever at du laster siden på nytt. Klikk her for å laste på nytt.",
"has_no_follower": "Denne brukeren har ingen følgere :(", "has_no_follower": "Denne brukeren har ingen følgere :(",
"follows_no_one": "Denne brukeren følger ingen :(", "follows_no_one": "Denne brukeren følger ingen :(",
"has_no_posts": "This user hasn't posted anything yet.", "has_no_posts": "Denne brukeren har ikke skrevet noe enda.",
"has_no_topics": "This user hasn't posted any topics yet.", "has_no_topics": "Denne brukeren har ikke skrevet noen emner enda.",
"has_no_watched_topics": "This user hasn't watched any topics yet.", "has_no_watched_topics": "Denne brukeren har ikke overvåket noen emner enda.",
"email_hidden": "E-post skjult", "email_hidden": "E-post skjult",
"hidden": "skjult", "hidden": "skjult",
"paginate_description": "Bruk sidevelger for emner og innlegg istedet for uendelig scrolling", "paginate_description": "Bruk sidevelger for emner og innlegg istedet for uendelig scrolling",

View File

@@ -1,12 +1,12 @@
{ {
"category": "Category", "category": "Categorie",
"subcategories": "Subcategories", "subcategories": "subcategorie",
"new_topic_button": "Nieuw onderwerp", "new_topic_button": "Nieuw onderwerp",
"guest-login-post": "Log in om een reactie te plaatsen", "guest-login-post": "Log in om een reactie te plaatsen",
"no_topics": "<strong>Er zijn geen onderwerpen in deze categorie.</strong><br />Waarom maak je er niet een aan?", "no_topics": "<strong>Er zijn geen onderwerpen in deze categorie.</strong><br />Waarom maak je er niet een aan?",
"browsing": "browsing", "browsing": "browsing",
"no_replies": "Niemand heeft gereageerd", "no_replies": "Niemand heeft gereageerd",
"no_new_posts": "No new posts.", "no_new_posts": "Geen nieuwe berichten",
"share_this_category": "Deel deze categorie", "share_this_category": "Deel deze categorie",
"watch": "Volgen", "watch": "Volgen",
"ignore": "Negeren", "ignore": "Negeren",

View File

@@ -46,8 +46,8 @@
"too-many-posts-newbie": "Nieuwe gebruikersaccounts zoals deze zijn begrensd en mogen slechts iedere %1 seconde(n) berichten plaatsen, tot het moment dat %2 reputatie verdiend is - wacht daarom even met opnieuw een bericht te plaatsten", "too-many-posts-newbie": "Nieuwe gebruikersaccounts zoals deze zijn begrensd en mogen slechts iedere %1 seconde(n) berichten plaatsen, tot het moment dat %2 reputatie verdiend is - wacht daarom even met opnieuw een bericht te plaatsten",
"tag-too-short": "Geef een tag op die uit meer tekens bestaat. Tags dienen uit minimaal %1 teken(s) te bestaan.", "tag-too-short": "Geef een tag op die uit meer tekens bestaat. Tags dienen uit minimaal %1 teken(s) te bestaan.",
"tag-too-long": "Geef een kortere tag op. Tags mogen niet langer dan %1 teken(s) zijn", "tag-too-long": "Geef een kortere tag op. Tags mogen niet langer dan %1 teken(s) zijn",
"not-enough-tags": "Not enough tags. Topics must have at least %1 tag(s)", "not-enough-tags": "Niet genoeg labels. Onderwerp moeten tenminste %1 label(s) hebben",
"too-many-tags": "Too many tags. Topics can't have more than %1 tag(s)", "too-many-tags": "Teveel labels. Onderwerpen kunnen niet meer dan %1 label(s) hebben ",
"file-too-big": "Maximum toegestane bestandsgrootte is %1 kB - probeer een kleiner bestand te verzenden", "file-too-big": "Maximum toegestane bestandsgrootte is %1 kB - probeer een kleiner bestand te verzenden",
"cant-vote-self-post": "Het is niet mogelijk op eigen berichten te stemmen", "cant-vote-self-post": "Het is niet mogelijk op eigen berichten te stemmen",
"already-favourited": "Dit bericht staat al tussen de favorieten", "already-favourited": "Dit bericht staat al tussen de favorieten",

View File

@@ -22,7 +22,7 @@
"pagination.out_of": "%1 van %2", "pagination.out_of": "%1 van %2",
"pagination.enter_index": "Vul index in", "pagination.enter_index": "Vul index in",
"header.admin": "Beheer", "header.admin": "Beheer",
"header.categories": "Categories", "header.categories": "Categorieën",
"header.recent": "Recent", "header.recent": "Recent",
"header.unread": "Ongelezen", "header.unread": "Ongelezen",
"header.tags": "Tags", "header.tags": "Tags",

View File

@@ -38,13 +38,13 @@
"details.private_help": "Wanneer ingeschakeld, zal eerst een groepseigenaar goedkeuring moeten verlenen voordat nieuwe leden kunnen toetreden", "details.private_help": "Wanneer ingeschakeld, zal eerst een groepseigenaar goedkeuring moeten verlenen voordat nieuwe leden kunnen toetreden",
"details.hidden": "Niet getoond", "details.hidden": "Niet getoond",
"details.hidden_help": "Indien geactiveerd zal deze groep niet getoond worden in de groepslijst en zullen gebruikers handmatig uitgenodigd moeten worden.", "details.hidden_help": "Indien geactiveerd zal deze groep niet getoond worden in de groepslijst en zullen gebruikers handmatig uitgenodigd moeten worden.",
"details.delete_group": "Delete Group", "details.delete_group": "Groep verwijderen",
"event.updated": "Groepsdetails zijn bijgewerkt", "event.updated": "Groepsdetails zijn bijgewerkt",
"event.deleted": "De groep \"%1\" is verwijderd", "event.deleted": "De groep \"%1\" is verwijderd",
"membership.accept-invitation": "Accept Invitation", "membership.accept-invitation": "Uitnodiging accepteren",
"membership.invitation-pending": "Invitation Pending", "membership.invitation-pending": "Openstaande uitnodiging",
"membership.join-group": "Join Group", "membership.join-group": "Deelnemen aan groep",
"membership.leave-group": "Leave Group", "membership.leave-group": "Verlaat groep",
"membership.reject": "Reject", "membership.reject": "Afwijzen",
"new-group.group_name": "Group Name:" "new-group.group_name": "Groepsnaam:"
} }

View File

@@ -52,16 +52,16 @@
"reputation": "Amanota", "reputation": "Amanota",
"read_more": "komeza usome", "read_more": "komeza usome",
"more": "Ibindi", "more": "Ibindi",
"posted_ago_by_guest": "byashyizweho %1 na Umushyitsi", "posted_ago_by_guest": "%1 bishyizweho na Umushyitsi",
"posted_ago_by": "byashyizweho %1 na %2", "posted_ago_by": "%1 bishyizweho na %2",
"posted_ago": "kuva %1", "posted_ago": "%1 biriho",
"posted_in_ago_by_guest": "byashyizwe muri %1 %2 na Umushyitsi", "posted_in_ago_by_guest": "%2 bishyizwe muri %1 na Umushyitsi",
"posted_in_ago_by": "byashyizwe muri %1 %2 na %3", "posted_in_ago_by": "%2 bishyizwe muri %1 na %3",
"posted_in_ago": "byashyizwe muri %1 %2", "posted_in_ago": "%2 bishyizwe muri %1",
"replied_ago": "yasubije %1", "replied_ago": "%1 asubije",
"user_posted_ago": "%1 yashyizeho %2", "user_posted_ago": "%2 %1 ashyizeho",
"guest_posted_ago": "Umushyitsi yashyizeho %1", "guest_posted_ago": "%1 Umushyitsi ashyizeho",
"last_edited_by_ago": "byahinduweho na %1 %2", "last_edited_by_ago": "%2 bihinduweho na %1",
"norecentposts": "Nta Biherutseho", "norecentposts": "Nta Biherutseho",
"norecenttopics": "Nta Biganiro Biherutse", "norecenttopics": "Nta Biganiro Biherutse",
"recentposts": "Ibiherutseho", "recentposts": "Ibiherutseho",

View File

@@ -1,5 +1,5 @@
{ {
"name": "Kinyarwanda", "name": "Kinyarwanda",
"code": "rw", "code": "rw",
"dir": "ltr" "dir": "ltr"
} }

View File

@@ -1,12 +1,12 @@
{ {
"title": "最新", "title": "最新",
"day": "24小时新帖热榜", "day": "",
"week": "7天新帖热榜", "week": "",
"month": "月度热帖榜", "month": "月",
"year": "年度热帖榜", "year": "年",
"alltime": "总热帖榜", "alltime": "总",
"no_recent_topics": "暂无主题。", "no_recent_topics": "暂无主题。",
"no_popular_topics": "没有热门主题。", "no_popular_topics": "暂无热门主题。",
"there-is-a-new-topic": "共计 1 个新主题。", "there-is-a-new-topic": "共计 1 个新主题。",
"there-is-a-new-topic-and-a-new-post": "共计 1 个新主题和 1 个新回复。", "there-is-a-new-topic-and-a-new-post": "共计 1 个新主题和 1 个新回复。",
"there-is-a-new-topic-and-new-posts": "共计 1 个新主题和 %1 个新回复。", "there-is-a-new-topic-and-new-posts": "共计 1 个新主题和 %1 个新回复。",

View File

@@ -23,10 +23,10 @@
"link": "链接", "link": "链接",
"share": "分享", "share": "分享",
"tools": "工具", "tools": "工具",
"flag": "标记", "flag": "举报",
"locked": "已锁定", "locked": "已锁定",
"bookmark_instructions": "点击这里返回您最后浏览的位置。", "bookmark_instructions": "点击这里返回您最后浏览的位置。",
"flag_title": "举报", "flag_title": "举报此帖",
"flag_confirm": "您确认要举报此帖吗?", "flag_confirm": "您确认要举报此帖吗?",
"flag_success": "已举报此回帖。", "flag_success": "已举报此回帖。",
"deleted_message": "此主题已被删除。只有拥有主题管理权限的用户可以查看。", "deleted_message": "此主题已被删除。只有拥有主题管理权限的用户可以查看。",

View File

@@ -1,40 +1,59 @@
@import "./bootstrap/bootstrap"; @import "./bootstrap/bootstrap";
@import "./bootswatch";
@import "./mixins"; @import "./mixins";
@import "./vars"; @import "./vars";
@import "./header";
@import "./mobile";
@import "./general/dashboard"; @import "./general/dashboard";
@import "./general/navigation"; @import "./general/navigation";
@import "./manage/categories"; @import "./manage/categories";
@import "./manage/tags"; @import "./manage/tags";
@import "./manage/flags"; @import "./manage/flags";
@import "./manage/groups";
@import "./manage/users"; @import "./manage/users";
@import "./appearance/customise"; @import "./appearance/customise";
@import "./appearance/themes"; @import "./appearance/themes";
@import "./extend/plugins"; @import "./extend/plugins";
@import "./extend/rewards"; @import "./extend/rewards";
@import "./advanced/database"; @import "./advanced/database";
@import "./settings";
@import "./modules/alerts"; @import "./modules/alerts";
@import "./modules/selectable"; @import "./modules/selectable";
@import "./modules/checkboxes"; @import "./modules/snackbar";
.admin { .admin {
padding-top: 70px; background: #fff;
background: #f0f0f0; font-size: 14px;
.container { h1 {
width: 100% !important; font-size: 35px;
padding: 0px 15px; margin-bottom: 50px;
} }
.jumbotron { label {
padding: @jumbotron-padding; font-weight: 700;
} }
.btn { .btn {
border-radius: 0; border-radius: 0;
} }
.btn-link {
color: @link-color;
}
.floating-button {
background: @brand-primary !important;
position: fixed;
right: 30px;
bottom: 30px;
z-index: 1;
}
.user-img { .user-img {
width:24px; width:24px;
height:24px; height:24px;
@@ -52,129 +71,10 @@
color: #fff; color: #fff;
} }
&.mobile {
#content {
padding-left: 20px;
}
#main-menu {
width: 200px;
height: 100%;
-webkit-transform: translateX(-190px);
transform: translateX(-190px);
&.transitioning {
.transition(.3s ease all);
}
&.open {
-webkit-transform: translateX(0);
transform: translateX(0);
}
}
}
#main-menu {
position: fixed;
width: 200px;
height: 100%;
padding-top: 50px;
top: 0px;
left: 0px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgAQMAAACxAfVuAAAAA3NCSVQICAjb4U/gAAAABlBMVEU5OTk1NTVxIqOYAAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABZ0RVh0Q3JlYXRpb24gVGltZQAxNC8xMS8xMc34jO8AAAFQSURBVEiJ7ZUxbsMwDEV/68Fbc4M4aC+QsYOhXstDELg3c9CLqPAFNHYo4tKkEBoMhxgoPEkD8aRBIkV+Enh4VRFvswkLwu4HY09m6pXQ/D6NA5lpUMLHtRojmSkq4RyqS2xD9Z2U0DX1Zzo19ZCU6KW6Tx2ZJT1+SDddZuQ7MyEEcqTdk1ECO0b7KSqBQ9i3ElEmcLAv7xJ7JvmW54P8Uqbtlrx5vL1+zDm699ONyI09NDX/zVdUwmlHmeGvVEJHHvB/J6UVh3wTZbtPSpKjMBeHEkwZMcEUHBNMaTLdivh1QRvnyIjJ99ONyI3dSIgJRkJMsMKQdKw5XEpI8m4kxARTRqJ3U3DSGUxpSg8xEpJus9kyEpLXXT/diNzYjYSYYCTEBCMMphWHRkJyp5GQ5MjtyW73dvu8kdDGOSrzqMyjMo/+KUdlHpV5VObR/foD6jrYlpchAFAAAAAASUVORK5CYII=);
z-index: 1;
overflow-y: auto;
.nano-content {
top: 51px !important;
}
.sidebar-nav {
overflow: hidden;
.transition(.4s ease-in-out max-height);
max-height: 100%;
cursor: pointer;
max-height: 38px;
&.open {
max-height: 500px;
}
.nav-header {
color: #fff;
border-top: 1px solid #32353E;
border-bottom: 1px solid #1A1C20;
background-color: #272727;
text-shadow: 0px 0px 2px #111;
padding: 10px;
.user-select(none);
}
.nav-list {
background: #232323;
li {
i {
margin-right: 6px;
}
&:hover a {
background-color: #3f3f3f;
span {
opacity: 0.8;
}
}
&.active a {
padding-left: 20px;
background-color: #3f3f3f;
span {
opacity: 0;
}
}
a {
color: white;
padding: 7px 15px;
font-size: 13px;
padding-left: 11px;
outline: 0;
span {
opacity: 0;
margin-right: -8px;
.transition(.3s ease-in opacity);
}
-webkit-transition: background-color .3s ease-in, padding-left .3s ease-in;
-moz-transition: background-color .3s ease-in, padding-left .3s ease-in;
-o-transition: background-color .3s ease-in, padding-left .3s ease-in;
transition: background-color .3s ease-in, padding-left .3s ease-in;
}
}
}
}
}
#content {
padding-left: 215px;
padding-right: 15px;
}
#breadcrumbs { #breadcrumbs {
cursor: default; cursor: default;
} }
.wrapper {
width: 100%;
overflow-y: hidden;
}
.acp-panel-heading { .acp-panel-heading {
padding: 7px 14px; padding: 7px 14px;
border: 0; border: 0;
@@ -203,20 +103,6 @@
.box-header-font .box-header-font
} }
#user_label {
a {
padding-top: 13px;
padding-bottom: 13px;
img {
width: 24px;
height: 24px;
border-radius: 50%;
border: 1px solid #454;
}
}
}
.icon-container { .icon-container {
.row { .row {
margin: 0; margin: 0;
@@ -271,30 +157,6 @@
} }
} }
#acp-search {
input {
background: black;
border: 0;
color: white;
box-shadow: none;
.transition(.4s ease width);
font-family: @font-family-monospace;
width: 30px;
height: 30px;
vertical-align: -30%;
border-radius: 0;
&:focus {
width: 200px;
}
}
.search-match {
font-weight: 700;
color: black;
}
}
#taskbar { #taskbar {
display: none; /* not sure why I have to do this, but it only seems to show up on prod */ display: none; /* not sure why I have to do this, but it only seems to show up on prod */
} }
@@ -311,16 +173,6 @@
display: inline-block; display: inline-block;
} }
@media (min-width: 1200px) {
.acp-sidebar {
position: fixed;
top: 70px;
right: 15px;
width: initial;
max-width: calc( ~"(100% - 200px)/4" );
}
}
.category-settings-form { .category-settings-form {
h3 { h3 {
margin-top: 0; margin-top: 0;
@@ -365,3 +217,19 @@
max-height: 24px; max-height: 24px;
} }
} }
.mdl-switch.is-checked .mdl-switch__ripple-container {
cursor: pointer !important;
}
.mdl-switch.is-checked .mdl-switch__thumb {
background: @brand-primary !important;
}
.mdl-switch.is-checked .mdl-switch__track {
background: lighten(@brand-primary, 20%) !important;
}
* > .checkbox:first-child {
margin-top: 0px;
}

View File

@@ -8,14 +8,6 @@
margin: 0.25em 1em; margin: 0.25em 1em;
list-style-type: none; list-style-type: none;
.pointer; .pointer;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-transition: background-color 250ms linear;
-moz-transition: background-color 250ms linear;
-ms-transition: background-color 250ms linear;
-o-transition: background-color 250ms linear;
transition: background-color 250ms linear;
img { img {
max-width: 150px; max-width: 150px;
@@ -30,16 +22,47 @@
font-size: 0.9em; font-size: 0.9em;
} }
&:hover {
background-color: rgba(128, 128, 128, 0.2);
}
&.no-themes { &.no-themes {
font-style: italic; font-style: italic;
} }
} }
} }
.theme-card {
margin-bottom: 30px;
margin-left: auto;
margin-right: auto;
.mdl-card__title {
height: 223px;
background-size: contain;
}
.mdl-card__supporting-text h2 {
margin-bottom: 15px;
}
}
[data-theme].selected .mdl-button {
color: black;
}
[data-type="bootswatch"] {
.mdl-card__title {
height: 198px;
}
.mdl-card__title-text {
display: none;
}
}
[data-type="local"] {
.mdl-card__supporting-text {
height: 150px;
}
}
textarea[data-field] { textarea[data-field] {
min-height: 450px; min-height: 450px;
width: 100%; width: 100%;

View File

@@ -1,4 +1,4 @@
// // Paper 3.3.5
// Variables // Variables
// -------------------------------------------------- // --------------------------------------------------
@@ -9,16 +9,16 @@
@gray-base: #000; @gray-base: #000;
@gray-darker: lighten(@gray-base, 13.5%); // #222 @gray-darker: lighten(@gray-base, 13.5%); // #222
@gray-dark: lighten(@gray-base, 20%); // #333 @gray-dark: #212121;
@gray: lighten(@gray-base, 33.5%); // #555 @gray: #666;
@gray-light: lighten(@gray-base, 46.7%); // #777 @gray-light: #bbb;
@gray-lighter: lighten(@gray-base, 93.5%); // #eee @gray-lighter: lighten(@gray-base, 93.5%); // #eee
@brand-primary: darken(#428bca, 6.5%); @brand-primary: #2196F3;
@brand-success: #5cb85c; @brand-success: #4CAF50;
@brand-info: #5bc0de; @brand-info: #9C27B0;
@brand-warning: #f0ad4e; @brand-warning: #ff9800;
@brand-danger: #d9534f; @brand-danger: #e51c23;
//== Scaffolding //== Scaffolding
@@ -28,7 +28,7 @@
//** Background color for `<body>`. //** Background color for `<body>`.
@body-bg: #fff; @body-bg: #fff;
//** Global text color on `<body>`. //** Global text color on `<body>`.
@text-color: @gray-dark; @text-color: @gray;
//** Global textual link color. //** Global textual link color.
@link-color: @brand-primary; @link-color: @brand-primary;
@@ -42,33 +42,33 @@
// //
//## Font, line-height, and color for body text, headings, and more. //## Font, line-height, and color for body text, headings, and more.
@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; @font-family-sans-serif: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
@font-family-serif: Georgia, "Times New Roman", Times, serif; @font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`. //** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; @font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
@font-family-base: @font-family-sans-serif; @font-family-base: @font-family-sans-serif;
@font-size-base: 14px; @font-size-base: 13px;
@font-size-large: ceil((@font-size-base * 1.25)); // ~18px @font-size-large: ceil((@font-size-base * 1.25)); // ~18px
@font-size-small: ceil((@font-size-base * 0.85)); // ~12px @font-size-small: ceil((@font-size-base * 0.85)); // ~12px
@font-size-h1: floor((@font-size-base * 2.6)); // ~36px @font-size-h1: 56px;
@font-size-h2: floor((@font-size-base * 2.15)); // ~30px @font-size-h2: 45px;
@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px @font-size-h3: 34px;
@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px @font-size-h4: 24px;
@font-size-h5: @font-size-base; @font-size-h5: 20px;
@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px @font-size-h6: 14px;
//** Unit-less `line-height` for use in components like buttons. //** Unit-less `line-height` for use in components like buttons.
@line-height-base: 1.428571429; // 20/14 @line-height-base: 1.846; // 20/14
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc. //** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px @line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px
//** By default, this inherits from the `<body>`. //** By default, this inherits from the `<body>`.
@headings-font-family: inherit; @headings-font-family: inherit;
@headings-font-weight: 500; @headings-font-weight: 400;
@headings-line-height: 1.1; @headings-line-height: 1.1;
@headings-color: inherit; @headings-color: #444;
//== Iconography //== Iconography
@@ -88,7 +88,7 @@
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). //## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
@padding-base-vertical: 6px; @padding-base-vertical: 6px;
@padding-base-horizontal: 12px; @padding-base-horizontal: 16px;
@padding-large-vertical: 10px; @padding-large-vertical: 10px;
@padding-large-horizontal: 16px; @padding-large-horizontal: 16px;
@@ -99,12 +99,12 @@
@padding-xs-vertical: 1px; @padding-xs-vertical: 1px;
@padding-xs-horizontal: 5px; @padding-xs-horizontal: 5px;
@line-height-large: 1.33; @line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome
@line-height-small: 1.5; @line-height-small: 1.5;
@border-radius-base: 4px; @border-radius-base: 0px;
@border-radius-large: 6px; @border-radius-large: 0px;
@border-radius-small: 3px; @border-radius-small: 0px;
//** Global color for active items (e.g., navs or dropdowns). //** Global color for active items (e.g., navs or dropdowns).
@component-active-color: #fff; @component-active-color: #fff;
@@ -144,49 +144,55 @@
@btn-font-weight: normal; @btn-font-weight: normal;
@btn-default-color: #333; @btn-default-color: #444;
@btn-default-bg: #fff; @btn-default-bg: #fff;
@btn-default-border: #ccc; @btn-default-border: transparent;
@btn-primary-color: #fff; @btn-primary-color: #fff;
@btn-primary-bg: @brand-primary; @btn-primary-bg: @brand-primary;
@btn-primary-border: darken(@btn-primary-bg, 5%); @btn-primary-border: transparent;
@btn-success-color: #fff; @btn-success-color: #fff;
@btn-success-bg: @brand-success; @btn-success-bg: @brand-success;
@btn-success-border: darken(@btn-success-bg, 5%); @btn-success-border: transparent;
@btn-info-color: #fff; @btn-info-color: #fff;
@btn-info-bg: @brand-info; @btn-info-bg: @brand-info;
@btn-info-border: darken(@btn-info-bg, 5%); @btn-info-border: transparent;
@btn-warning-color: #fff; @btn-warning-color: #fff;
@btn-warning-bg: @brand-warning; @btn-warning-bg: @brand-warning;
@btn-warning-border: darken(@btn-warning-bg, 5%); @btn-warning-border: transparent;
@btn-danger-color: #fff; @btn-danger-color: #fff;
@btn-danger-bg: @brand-danger; @btn-danger-bg: @brand-danger;
@btn-danger-border: darken(@btn-danger-bg, 5%); @btn-danger-border: transparent;
@btn-link-disabled-color: @gray-light; @btn-link-disabled-color: @gray-light;
// Allows for customizing button radius independently from global border radius
@btn-border-radius-base: @border-radius-base;
@btn-border-radius-large: @border-radius-large;
@btn-border-radius-small: @border-radius-small;
//== Forms //== Forms
// //
//## //##
//** `<input>` background color //** `<input>` background color
@input-bg: #fff; @input-bg: transparent;
//** `<input disabled>` background color //** `<input disabled>` background color
@input-bg-disabled: @gray-lighter; @input-bg-disabled: transparent;
//** Text color for `<input>`s //** Text color for `<input>`s
@input-color: @gray; @input-color: @gray;
//** `<input>` border color //** `<input>` border color
@input-border: #ccc; @input-border: transparent;
// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4 // TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
//** Default `.form-control` border radius //** Default `.form-control` border radius
// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
@input-border-radius: @border-radius-base; @input-border-radius: @border-radius-base;
//** Large `.form-control` border radius //** Large `.form-control` border radius
@input-border-radius-large: @border-radius-large; @input-border-radius-large: @border-radius-large;
@@ -197,7 +203,7 @@
@input-border-focus: #66afe9; @input-border-focus: #66afe9;
//** Placeholder text color //** Placeholder text color
@input-color-placeholder: #999; @input-color-placeholder: @gray-light;
//** Default `.form-control` height //** Default `.form-control` height
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); @input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
@@ -206,11 +212,14 @@
//** Small `.form-control` height //** Small `.form-control` height
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); @input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
//** `.form-group` margin
@form-group-margin-bottom: 15px;
@legend-color: @gray-dark; @legend-color: @gray-dark;
@legend-border-color: #e5e5e5; @legend-border-color: #e5e5e5;
//** Background color for textual input addons //** Background color for textual input addons
@input-group-addon-bg: @gray-lighter; @input-group-addon-bg: transparent;
//** Border color for textual input addons //** Border color for textual input addons
@input-group-addon-border-color: @input-border; @input-group-addon-border-color: @input-border;
@@ -232,11 +241,11 @@
@dropdown-divider-bg: #e5e5e5; @dropdown-divider-bg: #e5e5e5;
//** Dropdown link text color. //** Dropdown link text color.
@dropdown-link-color: @gray-dark; @dropdown-link-color: @text-color;
//** Hover color for dropdown links. //** Hover color for dropdown links.
@dropdown-link-hover-color: darken(@gray-dark, 5%); @dropdown-link-hover-color: darken(@gray-dark, 5%);
//** Hover background for dropdown links. //** Hover background for dropdown links.
@dropdown-link-hover-bg: #f5f5f5; @dropdown-link-hover-bg: @gray-lighter;
//** Active dropdown menu item text color. //** Active dropdown menu item text color.
@dropdown-link-active-color: @component-active-color; @dropdown-link-active-color: @component-active-color;
@@ -250,7 +259,7 @@
@dropdown-header-color: @gray-light; @dropdown-header-color: @gray-light;
//** Deprecated `@dropdown-caret-color` as of v3.1.0 //** Deprecated `@dropdown-caret-color` as of v3.1.0
@dropdown-caret-color: #000; @dropdown-caret-color: @gray-light;
//-- Z-index master list //-- Z-index master list
@@ -265,7 +274,8 @@
@zindex-popover: 1060; @zindex-popover: 1060;
@zindex-tooltip: 1070; @zindex-tooltip: 1070;
@zindex-navbar-fixed: 1030; @zindex-navbar-fixed: 1030;
@zindex-modal: 1040; @zindex-modal-background: 1040;
@zindex-modal: 1050;
//== Media queries breakpoints //== Media queries breakpoints
@@ -347,45 +357,45 @@
//## //##
// Basics of a navbar // Basics of a navbar
@navbar-height: 50px; @navbar-height: 64px;
@navbar-margin-bottom: @line-height-computed; @navbar-margin-bottom: @line-height-computed;
@navbar-border-radius: @border-radius-base; @navbar-border-radius: @border-radius-base;
@navbar-padding-horizontal: floor((@grid-gutter-width / 2)); @navbar-padding-horizontal: floor((@grid-gutter-width / 2));
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); @navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
@navbar-collapse-max-height: 340px; @navbar-collapse-max-height: 340px;
@navbar-default-color: #777; @navbar-default-color: @gray-light;
@navbar-default-bg: #f8f8f8; @navbar-default-bg: #fff;
@navbar-default-border: darken(@navbar-default-bg, 6.5%); @navbar-default-border: transparent;
// Navbar links // Navbar links
@navbar-default-link-color: #777; @navbar-default-link-color: @gray;
@navbar-default-link-hover-color: #333; @navbar-default-link-hover-color: @gray-dark;
@navbar-default-link-hover-bg: transparent; @navbar-default-link-hover-bg: transparent;
@navbar-default-link-active-color: #555; @navbar-default-link-active-color: @gray-dark;
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%); @navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
@navbar-default-link-disabled-color: #ccc; @navbar-default-link-disabled-color: #ccc;
@navbar-default-link-disabled-bg: transparent; @navbar-default-link-disabled-bg: transparent;
// Navbar brand label // Navbar brand label
@navbar-default-brand-color: @navbar-default-link-color; @navbar-default-brand-color: @navbar-default-link-color;
@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%); @navbar-default-brand-hover-color: @navbar-default-link-hover-color;
@navbar-default-brand-hover-bg: transparent; @navbar-default-brand-hover-bg: transparent;
// Navbar toggle // Navbar toggle
@navbar-default-toggle-hover-bg: #ddd; @navbar-default-toggle-hover-bg: transparent;
@navbar-default-toggle-icon-bar-bg: #888; @navbar-default-toggle-icon-bar-bg: rgba(0,0,0,0.5);
@navbar-default-toggle-border-color: #ddd; @navbar-default-toggle-border-color: transparent;
// Inverted navbar //=== Inverted navbar
// Reset inverted navbar basics // Reset inverted navbar basics
@navbar-inverse-color: lighten(@gray-light, 15%); @navbar-inverse-color: @gray-light;
@navbar-inverse-bg: #222; @navbar-inverse-bg: @brand-primary;
@navbar-inverse-border: darken(@navbar-inverse-bg, 10%); @navbar-inverse-border: transparent;
// Inverted navbar links // Inverted navbar links
@navbar-inverse-link-color: lighten(@gray-light, 15%); @navbar-inverse-link-color: lighten(@brand-primary, 30%);
@navbar-inverse-link-hover-color: #fff; @navbar-inverse-link-hover-color: #fff;
@navbar-inverse-link-hover-bg: transparent; @navbar-inverse-link-hover-bg: transparent;
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; @navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
@@ -398,10 +408,10 @@
@navbar-inverse-brand-hover-color: #fff; @navbar-inverse-brand-hover-color: #fff;
@navbar-inverse-brand-hover-bg: transparent; @navbar-inverse-brand-hover-bg: transparent;
// Inverted navbar toggle // Inverted navbar toggle\
@navbar-inverse-toggle-hover-bg: #333; @navbar-inverse-toggle-hover-bg: transparent;
@navbar-inverse-toggle-icon-bar-bg: #fff; @navbar-inverse-toggle-icon-bar-bg: rgba(0,0,0,0.5);
@navbar-inverse-toggle-border-color: #333; @navbar-inverse-toggle-border-color: transparent;
//== Navs //== Navs
@@ -416,15 +426,15 @@
@nav-disabled-link-hover-color: @gray-light; @nav-disabled-link-hover-color: @gray-light;
//== Tabs //== Tabs
@nav-tabs-border-color: #ddd; @nav-tabs-border-color: transparent;
@nav-tabs-link-hover-border-color: @gray-lighter; @nav-tabs-link-hover-border-color: @gray-lighter;
@nav-tabs-active-link-hover-bg: @body-bg; @nav-tabs-active-link-hover-bg: transparent;
@nav-tabs-active-link-hover-color: @gray; @nav-tabs-active-link-hover-color: @gray;
@nav-tabs-active-link-hover-border-color: #ddd; @nav-tabs-active-link-hover-border-color: transparent;
@nav-tabs-justified-link-border-color: #ddd; @nav-tabs-justified-link-border-color: @nav-tabs-border-color;
@nav-tabs-justified-active-link-border-color: @body-bg; @nav-tabs-justified-active-link-border-color: @body-bg;
//== Pills //== Pills
@@ -476,29 +486,30 @@
@jumbotron-padding: 30px; @jumbotron-padding: 30px;
@jumbotron-color: inherit; @jumbotron-color: inherit;
@jumbotron-bg: @gray-lighter; @jumbotron-bg: #f9f9f9;
@jumbotron-heading-color: inherit; @jumbotron-heading-color: @headings-color;
@jumbotron-font-size: ceil((@font-size-base * 1.5)); @jumbotron-font-size: ceil((@font-size-base * 1.5));
@jumbotron-heading-font-size: ceil((@font-size-base * 4.5));
//== Form states and alerts //== Form states and alerts
// //
//## Define colors for form feedback states and, by default, alerts. //## Define colors for form feedback states and, by default, alerts.
@state-success-text: #3c763d; @state-success-text: @brand-success;
@state-success-bg: #dff0d8; @state-success-bg: #dff0d8;
@state-success-border: darken(spin(@state-success-bg, -10), 5%); @state-success-border: darken(spin(@state-success-bg, -10), 5%);
@state-info-text: #31708f; @state-info-text: @brand-info;
@state-info-bg: #d9edf7; @state-info-bg: #e1bee7;
@state-info-border: darken(spin(@state-info-bg, -10), 7%); @state-info-border: darken(spin(@state-info-bg, -10), 7%);
@state-warning-text: #8a6d3b; @state-warning-text: @brand-warning;
@state-warning-bg: #fcf8e3; @state-warning-bg: #ffe0b2;
@state-warning-border: darken(spin(@state-warning-bg, -10), 5%); @state-warning-border: darken(spin(@state-warning-bg, -10), 5%);
@state-danger-text: #a94442; @state-danger-text: @brand-danger;
@state-danger-bg: #f2dede; @state-danger-bg: #f9bdbb;
@state-danger-border: darken(spin(@state-danger-bg, -10), 5%); @state-danger-border: darken(spin(@state-danger-bg, -10), 5%);
@@ -511,7 +522,7 @@
//** Tooltip text color //** Tooltip text color
@tooltip-color: #fff; @tooltip-color: #fff;
//** Tooltip background color //** Tooltip background color
@tooltip-bg: #000; @tooltip-bg: #727272;
@tooltip-opacity: .9; @tooltip-opacity: .9;
//** Tooltip arrow width //** Tooltip arrow width
@@ -529,9 +540,9 @@
//** Popover maximum width //** Popover maximum width
@popover-max-width: 276px; @popover-max-width: 276px;
//** Popover border color //** Popover border color
@popover-border-color: rgba(0,0,0,.2); @popover-border-color: transparent;
//** Popover fallback border color //** Popover fallback border color
@popover-fallback-border-color: #ccc; @popover-fallback-border-color: transparent;
//** Popover title background color //** Popover title background color
@popover-title-bg: darken(@popover-bg, 3%); @popover-title-bg: darken(@popover-bg, 3%);
@@ -544,7 +555,7 @@
//** Popover outer arrow width //** Popover outer arrow width
@popover-arrow-outer-width: (@popover-arrow-width + 1); @popover-arrow-outer-width: (@popover-arrow-width + 1);
//** Popover outer arrow color //** Popover outer arrow color
@popover-arrow-outer-color: fadein(@popover-border-color, 5%); @popover-arrow-outer-color: fadein(@popover-border-color, 7.5%);
//** Popover outer arrow fallback color //** Popover outer arrow fallback color
@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%); @popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);
@@ -587,7 +598,7 @@
//** Background color of modal content area //** Background color of modal content area
@modal-content-bg: #fff; @modal-content-bg: #fff;
//** Modal content border color //** Modal content border color
@modal-content-border-color: rgba(0,0,0,.2); @modal-content-border-color: transparent;
//** Modal content border color **for IE8** //** Modal content border color **for IE8**
@modal-content-fallback-border-color: #999; @modal-content-fallback-border-color: #999;
@@ -596,7 +607,7 @@
//** Modal backdrop opacity //** Modal backdrop opacity
@modal-backdrop-opacity: .5; @modal-backdrop-opacity: .5;
//** Modal header border color //** Modal header border color
@modal-header-border-color: #e5e5e5; @modal-header-border-color: transparent;
//** Modal footer border color //** Modal footer border color
@modal-footer-border-color: @modal-header-border-color; @modal-footer-border-color: @modal-header-border-color;
@@ -709,21 +720,21 @@
@panel-primary-border: @brand-primary; @panel-primary-border: @brand-primary;
@panel-primary-heading-bg: @brand-primary; @panel-primary-heading-bg: @brand-primary;
@panel-success-text: @state-success-text; @panel-success-text: #fff;
@panel-success-border: @state-success-border; @panel-success-border: @state-success-border;
@panel-success-heading-bg: @state-success-bg; @panel-success-heading-bg: @brand-success;
@panel-info-text: @state-info-text; @panel-info-text: #fff;
@panel-info-border: @state-info-border; @panel-info-border: @state-info-border;
@panel-info-heading-bg: @state-info-bg; @panel-info-heading-bg: @brand-info;
@panel-warning-text: @state-warning-text; @panel-warning-text: #fff;
@panel-warning-border: @state-warning-border; @panel-warning-border: @state-warning-border;
@panel-warning-heading-bg: @state-warning-bg; @panel-warning-heading-bg: @brand-warning;
@panel-danger-text: @state-danger-text; @panel-danger-text: #fff;
@panel-danger-border: @state-danger-border; @panel-danger-border: @state-danger-border;
@panel-danger-heading-bg: @state-danger-bg; @panel-danger-heading-bg: @brand-danger;
//== Thumbnails //== Thumbnails
@@ -749,8 +760,8 @@
// //
//## //##
@well-bg: #f5f5f5; @well-bg: #f9f9f9;
@well-border: darken(@well-bg, 7%); @well-border: transparent;
//== Badges //== Badges
@@ -767,7 +778,7 @@
//** Badge background color in active nav link //** Badge background color in active nav link
@badge-active-bg: #fff; @badge-active-bg: #fff;
@badge-font-weight: bold; @badge-font-weight: normal;
@badge-line-height: 1; @badge-line-height: 1;
@badge-border-radius: 10px; @badge-border-radius: 10px;
@@ -809,9 +820,9 @@
// //
//## //##
@close-font-weight: bold; @close-font-weight: normal;
@close-color: #000; @close-color: #000;
@close-text-shadow: 0 1px 0 #fff; @close-text-shadow: none;
//== Code //== Code

View File

@@ -0,0 +1,607 @@
// Paper 3.3.5
// Bootswatch
// -----------------------------------------------------
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700");
// Navbar =====================================================================
.navbar {
border: none;
.box-shadow(0 1px 2px rgba(0,0,0,.3));
&-brand {
font-size: 24px;
}
&-inverse {
.form-control {
color: #fff;
.placeholder(@navbar-inverse-link-color);
&[type=text],
&[type=password] {
.box-shadow(inset 0 -1px 0 @navbar-inverse-link-color);
&:focus {
.box-shadow(inset 0 -2px 0 #fff);
}
}
}
}
}
// Buttons ====================================================================
#btn(@class,@bg) {
.btn-@{class} {
background-size: 200%;
background-position: 50%;
&:focus {
background-color: @bg;
}
&:hover,
&:active:hover {
background-color: darken(@bg, 6%);
}
&:active {
background-color: darken(@bg, 12%);
#gradient > .radial(darken(@bg, 12%) 10%, @bg 11%);
background-size: 1000%;
.box-shadow(2px 2px 4px rgba(0,0,0,.4));
}
}
}
#btn(default,@btn-default-bg);
#btn(primary,@btn-primary-bg);
#btn(success,@btn-success-bg);
#btn(info,@btn-info-bg);
#btn(warning,@btn-warning-bg);
#btn(danger,@btn-danger-bg);
#btn(link,#fff);
.btn {
text-transform: uppercase;
border: none;
.box-shadow(1px 1px 4px rgba(0,0,0,.4));
.transition(all 0.4s);
&-link {
border-radius: @btn-border-radius-base;
.box-shadow(none);
color: @btn-default-color;
&:hover,
&:focus {
.box-shadow(none);
color: @btn-default-color;
text-decoration: none;
}
}
&-default {
&.disabled {
background-color: rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.4);
opacity: 1;
}
}
}
.btn-group {
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: 0;
}
&-vertical {
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: 0;
}
}
}
// Typography =================================================================
body {
-webkit-font-smoothing: antialiased;
letter-spacing: .1px;
}
p {
margin: 0 0 1em;
}
input,
button {
-webkit-font-smoothing: antialiased;
letter-spacing: .1px;
}
a {
.transition(all 0.2s);
}
// Tables =====================================================================
.table-hover {
> tbody > tr,
> tbody > tr > th,
> tbody > tr > td {
.transition(all 0.2s);
}
}
// Forms ======================================================================
label {
font-weight: normal;
}
textarea,
textarea.form-control,
input.form-control,
input[type=text],
input[type=password],
input[type=email],
input[type=number],
[type=text].form-control,
[type=password].form-control,
[type=email].form-control,
[type=tel].form-control,
[contenteditable].form-control {
padding: 0;
border: none;
border-radius: 0;
-webkit-appearance: none;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px;
&:focus {
.box-shadow(inset 0 -2px 0 @brand-primary);
}
&[disabled],
&[readonly] {
.box-shadow(none);
border-bottom: 1px dotted #ddd;
}
&.input {
&-sm {
font-size: @font-size-small;
}
&-lg {
font-size: @font-size-large;
}
}
}
select,
select.form-control {
border: 0;
border-radius: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding-left: 0;
padding-right: 0\9; // remove padding for < ie9 since default arrow can't be removed
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmaP/QSjAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
background-size: 13px;
background-repeat: no-repeat;
background-position: right center;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px;
line-height: 1.5;
&::-ms-expand {
display: none;
}
&.input {
&-sm {
font-size: @font-size-small;
}
&-lg {
font-size: @font-size-large;
}
}
&:focus {
.box-shadow(inset 0 -2px 0 @brand-primary);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEUhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF8S9ewAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
}
&[multiple] {
background: none;
}
}
.radio,
.radio-inline,
.checkbox,
.checkbox-inline {
label {
padding-left: 25px;
}
input[type="radio"],
input[type="checkbox"] {
margin-left: -25px;
}
}
input[type="radio"],
.radio input[type="radio"],
.radio-inline input[type="radio"] {
position: relative;
margin-top: 6px;
margin-right: 4px;
vertical-align: top;
border: none;
background-color: transparent;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
&:focus {
outline: none;
}
&:before,
&:after {
content: "";
display: block;
width: 18px;
height: 18px;
border-radius: 50%;
.transition(240ms);
}
&:before {
position: absolute;
left: 0;
top: -3px;
background-color: @brand-primary;
.scale(0);
}
&:after {
position: relative;
top: -3px;
border: 2px solid @gray;
}
&:checked:before {
.scale(0.5);
}
&:disabled:checked:before {
background-color: @gray-light;
}
&:checked:after {
border-color: @brand-primary;
}
&:disabled:after,
&:disabled:checked:after {
border-color: @gray-light;
}
}
input[type="checkbox"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
position: relative;
border: none;
margin-bottom: -4px;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
&:focus {
outline: none;
}
&:after {
content: "";
display: block;
width: 18px;
height: 18px;
margin-top: -2px;
margin-right: 5px;
border: 2px solid @gray;
border-radius: 2px;
.transition(240ms);
}
&:checked:before {
content: "";
position: absolute;
top: 0;
left: 6px;
display: table;
width: 6px;
height: 12px;
border: 2px solid #fff;
border-top-width: 0;
border-left-width: 0;
.rotate(45deg);
}
&:checked:after {
background-color: @brand-primary;
border-color: @brand-primary;
}
&:disabled:after {
border-color: @gray-light;
}
&:disabled:checked:after {
background-color: @gray-light;
border-color: transparent;
}
}
.has-warning {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-warning);
}
}
.has-error {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-danger);
}
}
.has-success {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-success);
}
}
// Remove the Bootstrap feedback styles for input addons
.input-group-addon {
.has-warning &, .has-error &, .has-success & {
color: @input-color;
border-color: @input-group-addon-border-color;
background-color: @input-group-addon-bg;
}
}
// Navs =======================================================================
.nav-tabs {
> li > a,
> li > a:focus {
margin-right: 0;
background-color: transparent;
border: none;
color: @navbar-default-link-color;
.box-shadow(inset 0 -1px 0 #ddd);
.transition(all 0.2s);
&:hover {
background-color: transparent;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary;
}
}
& > li.active > a,
& > li.active > a:focus {
border: none;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary;
&:hover {
border: none;
color: @brand-primary;
}
}
& > li.disabled > a {
.box-shadow(inset 0 -1px 0 #ddd);
}
&.nav-justified {
& > li > a,
& > li > a:hover,
& > li > a:focus,
& > .active > a,
& > .active > a:hover,
& > .active > a:focus {
border: none;
}
}
.dropdown-menu {
margin-top: 0;
}
}
.dropdown-menu {
margin-top: 0;
border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
}
// Indicators =================================================================
.alert {
border: none;
color: #fff;
&-success {
background-color: @brand-success;
}
&-info {
background-color: @brand-info;
}
&-warning {
background-color: @brand-warning;
}
&-danger {
background-color: @brand-danger;
}
a:not(.close),
.alert-link {
color: #fff;
font-weight: bold;
}
.close {
color: #fff;
}
}
.badge {
padding: 3px 6px 5px;
}
.progress {
position: relative;
z-index: 1;
height: 6px;
border-radius: 0;
.box-shadow(none);
&-bar {
.box-shadow(none);
&:last-child {
border-radius: 0 3px 3px 0;
}
&:last-child {
&:before {
display: block;
content: "";
position: absolute;
width: 100%;
height: 100%;
left: 0;
right: 0;
z-index: -1;
background-color: lighten(@progress-bar-bg, 35%);
}
}
&-success:last-child.progress-bar:before {
background-color: lighten(@brand-success, 35%);
}
&-info:last-child.progress-bar:before {
background-color: lighten(@brand-info, 45%);
}
&-warning:last-child.progress-bar:before {
background-color: lighten(@brand-warning, 35%);
}
&-danger:last-child.progress-bar:before {
background-color: lighten(@brand-danger, 25%);
}
}
}
// Progress bars ==============================================================
// Containers =================================================================
.close {
font-size: 34px;
font-weight: 300;
line-height: 24px;
opacity: 0.6;
.transition(all 0.2s);
&:hover {
opacity: 1;
}
}
.list-group {
&-item {
padding: 15px;
}
&-item-text {
color: @gray-light;
}
}
.well {
border-radius: 0;
.box-shadow(none);
}
.panel {
border: none;
border-radius: 2px;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
&-heading {
border-bottom: none;
}
&-footer {
border-top: none;
}
}
.popover {
border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
}
.carousel {
&-caption {
h1, h2, h3, h4, h5, h6 {
color: inherit;
}
}
}

View File

@@ -0,0 +1,91 @@
.header {
position: relative;
background: #333;
width: 100%;
height: 200px;
margin-bottom: 50px;
font-size: 16px;
#main-page-title {
position: absolute;
left: 48px;
bottom: 17px;
color: #aaa;
font-size: 47px;
font-weight: 300;
}
#user_label {
position: absolute;
right: 30px;
bottom: 125px;
.dropdown {
margin-right: 0px;
.dropdown-toggle i {
padding: 0 1rem;
}
}
#user_dropdown {
font-size: 25px;
color: #eee;
i {
margin-top: 12px;
display: block;
}
}
}
#acp-search {
margin-top: 2px;
margin-right: 20px;
input {
padding: 10px 20px;
width: 250px;
height: 44px;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 3px;
box-shadow: none;
.transition(.4s ease background-color);
&:focus {
background-color: #eee;
color: #333;
}
}
.search-match {
font-weight: 700;
color: black;
}
}
> ul {
list-style-type: none;
padding: 0px;
position: absolute;
bottom: -11px;
left: 50px;
> li {
float: left;
margin-right: 30px;
&.active {
border-bottom: 4px solid @brand-primary;
padding-bottom: 10px;
}
> a {
color: white;
text-transform: uppercase;
text-decoration: none;
outline: none;
}
}
}
}

View File

@@ -16,6 +16,12 @@ div.categories {
padding-bottom: 12px; padding-bottom: 12px;
margin-bottom: 12px; margin-bottom: 12px;
} }
> li li:last-child {
.row {
border-bottom: 0px;
}
}
} }
.stats { .stats {
@@ -32,6 +38,7 @@ div.categories {
li { li {
min-height: @acp-line-height; min-height: @acp-line-height;
margin: @acp-base-line 0; margin: @acp-base-line 0;
margin-top: 28px;
&.placeholder { &.placeholder {
border: 1px dashed #2196F3; border: 1px dashed #2196F3;
@@ -41,7 +48,7 @@ div.categories {
.disabled { .disabled {
.icon, .header, .description { .icon, .category-header, .description {
opacity: 0.5; opacity: 0.5;
} }
@@ -67,7 +74,7 @@ div.categories {
float: left; float: left;
} }
.header { .category-header {
margin-top: 0; margin-top: 0;
margin-bottom: @acp-base-line; margin-bottom: @acp-base-line;
} }

View File

@@ -0,0 +1,5 @@
.group {
.current_members {
padding: 0;
}
}

View File

@@ -18,8 +18,6 @@
.tag-item { .tag-item {
border: solid 1px @gray-light; border: solid 1px @gray-light;
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
background-color: transparent; background-color: transparent;
color: @gray-light; color: @gray-light;
padding: .2em .6em .3em; padding: .2em .6em .3em;
@@ -31,15 +29,14 @@
.tag-topic-count { .tag-topic-count {
border: solid 1px lighten(@brand-primary, 20%); border: solid 1px lighten(@brand-primary, 20%);
background-color: lighten(@brand-primary, 20%); background-color: lighten(@brand-primary, 20%);
padding: .2em .6em .3em; padding: 6px;
font-size: 75%; font-size: 75%;
font-weight: 700; font-weight: 700;
white-space: nowrap; white-space: nowrap;
border-left: none; border-left: none;
padding-right: 5px; padding-right: 5px;
padding-left: 5px; padding-left: 5px;
border-bottom-right-radius: 5px; border-width: 1px 1px 2px medium;
border-top-right-radius: 5px;
a { a {
color: #FFFFFF; color: #FFFFFF;

View File

@@ -0,0 +1,176 @@
#mobile-menu {
display: none;
}
@media (max-width: 1200px) {
}
@media (max-width: 980px) {
body {
height: 100%;
}
.header {
height: 58px;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.26);
position: fixed;
top: 0px;
z-index: 5;
#main-page-title {
bottom: -31px;
font-size: 20px;
color: #FFF;
left: 52px;
font-weight: 400;
}
#user_label {
right: 0px;
bottom: 7px;
}
#main-menu {
display: none;
}
}
#mobile-menu {
width: 31px;
background: none;
border: none;
vertical-align: 10%;
margin-right: 10px;
margin-left: -15px;
outline: none !important;
display: block;
position: absolute;
top: 22px;
left: 22px;
.bar {
width: 100%;
height: 2px;
background: #fff;
margin-bottom: 3px;
border-radius: 10px;
}
}
#menu {
background-color: #1D1F20;
background-image: linear-gradient(145deg, #1D1F20, #404348);
a {
color: #fff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
}
.menu-header-title {
font-weight: 400;
letter-spacing: 0.5px;
margin: 0;
}
.menu-section {
margin: 25px 0;
}
.menu-section-title {
text-transform: uppercase;
color: #85888d;
font-weight: 200;
font-size: 13px;
letter-spacing: 1px;
padding: 0 20px;
margin:0;
}
.menu-section-list {
padding:0;
margin: 10px 0;
list-style:none;
a {
display: block;
padding: 10px 20px;
}
a:hover {
background-color: rgba(255, 255, 255, 0.1);
text-decoration: none;
}
}
#panel {
background: white;
min-height: 100%;
padding-top: 80px;
}
.slideout-menu {
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 0;
width: 256px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
display: none;
}
.slideout-panel {
position: relative;
z-index: 1;
}
.slideout-open,
.slideout-open body,
.slideout-open .slideout-panel {
overflow: hidden;
overflow-y: hidden !important;
}
.slideout-open .slideout-menu {
display: block;
}
html {
height: 100%;
overflow-y: hidden;
}
.slideout-open {
overflow-y: hidden;
height: 100%;
}
body {
overflow-y: scroll;
overflow-x: hidden;
}
}
@media (max-width: 768px) {
.content-header, .settings-header {
font-size: 200%;
margin-bottom: 20px;
margin-left: -2px;
}
.dropdown-menu {
margin-top: -35px;
margin-right: -2px;
}
}

View File

@@ -1,18 +0,0 @@
label {
cursor: pointer;
}
.checkbox label {
padding-left: 2px;
}
.admin {
.fa-toggle-on, .fa-toggle-off {
font-size: 21px;
vertical-align: -3px;
}
.fa-toggle-on {
color: @brand-success;
}
}

View File

@@ -0,0 +1,65 @@
#snackbar-container {
position:fixed;
left:20px;
bottom:0;
z-index:99999;
strong {
margin-right: 30px;
}
}
.snackbar {
overflow:hidden;
clear:both;
min-width:288px;
max-width:568px;
cursor:pointer;
opacity:0;
}
.snackbar.snackbar-opened {
height:auto;
opacity:1;
}
@media (max-width:767px) {
#snackbar-container {
left:0!important;
right:0;
width:100%;
strong {
display: block;
}
}
#snackbar-container .snackbar {
min-width:100%;
}
#snackbar-container [class="snackbar snackbar-opened"]~.snackbar.toast {
margin-top:20px;
}
#snackbar-container [class="snackbar snackbar-opened"] {
border-radius:0;
margin-bottom:0;
}
}
.snackbar {
background-color: #323232;
color: #FFFFFF;
font-size: 14px;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
height: 0;
.transition(.25s ease-in-out opacity);
}
.snackbar.snackbar-opened {
padding: 10px 15px;
margin-bottom: 20px;
height: auto;
}

View File

@@ -0,0 +1,19 @@
.settings {
.row {
margin-bottom: 30px;
}
.section-content {
border-left: 3px solid @brand-primary;
ul {
list-style-type: none;
font-size: 16px;
padding-left: 20px;
}
}
[data-action="upload"][type="text"] {
width: 95%;
}
}

View File

@@ -1,32 +1,29 @@
"use strict"; "use strict";
/*global define, socket, app, ajaxify, utils, bootbox, Mousetrap, Hammer, RELATIVE_PATH*/ /*global componentHandler, define, socket, app, ajaxify, utils, bootbox, Mousetrap, Hammer, RELATIVE_PATH*/
(function() { (function() {
$(document).ready(function() { $(document).ready(function() {
setupMenu();
setupKeybindings(); setupKeybindings();
if(!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { if(!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
require(['admin/modules/search'], function(search) { require(['admin/modules/search'], function(search) {
search.init(); search.init();
}); });
} else {
activateMobile();
} }
$(window).on('action:ajaxify.contentLoaded', function(ev, data) { $(window).on('action:ajaxify.contentLoaded', function(ev, data) {
var url = data.url; var url = data.url;
selectMenuItem(data.url); selectMenuItem(data.url);
setupHeaderMenu();
setupRestartLinks(); setupRestartLinks();
componentHandler.upgradeDom();
}); });
$(window).on('action:admin.settingsLoaded', setupCheckboxes);
$('[component="logout"]').on('click', app.logout); $('[component="logout"]').on('click', app.logout);
app.alert = launchSnackbar;
$(window).resize(setupHeaderMenu); configureSlidemenu();
}); });
socket.emit('admin.config.get', function(err, config) { socket.emit('admin.config.get', function(err, config) {
@@ -45,27 +42,6 @@
$(window).trigger('action:config.loaded'); $(window).trigger('action:config.loaded');
}); });
function setupMenu() {
var listElements = $('.sidebar-nav li');
listElements.on('click', function() {
var $this = $(this);
if ($this.hasClass('nav-header')) {
$this.parents('.sidebar-nav').toggleClass('open').bind('animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd', function (ev) {
$('.nano').nanoScroller();
});
} else {
listElements.removeClass('active');
$this.addClass('active');
}
});
$('.nano').nanoScroller();
$('#main-menu .nav-list > li a').append('<span class="pull-right"><i class="fa fa-inverse fa-arrow-circle-right"></i>&nbsp;</span>');
}
function setupKeybindings() { function setupKeybindings() {
Mousetrap.bind('ctrl+shift+a r', function() { Mousetrap.bind('ctrl+shift+a r', function() {
require(['admin/modules/instance'], function(instance) { require(['admin/modules/instance'], function(instance) {
@@ -84,75 +60,32 @@
}); });
} }
function activateMobile() {
$('.admin').addClass('mobile');
$('#main-menu').addClass('transitioning');
Hammer(document.body).on('swiperight', function(e) {
$('#main-menu').addClass('open');
});
Hammer(document.body).on('swipeleft', function(e) {
$('#main-menu').removeClass('open');
});
Hammer($('#main-menu')[0]).on('swiperight', function(e) {
$('#main-menu').addClass('open');
});
Hammer($('#main-menu')[0]).on('swipeleft', function(e) {
$('#main-menu').removeClass('open');
});
$(window).on('scroll', function() {
$('#main-menu').height($(window).height() + 20);
});
}
function selectMenuItem(url) { function selectMenuItem(url) {
url = url.replace(/\/\d+$/, ''); url = url
.replace(/\/\d+$/, '')
.split('/').slice(0, 3).join('/');
// If index is requested, load the dashboard // If index is requested, load the dashboard
if (url === 'admin') { if (url === 'admin') {
url = 'admin/general/dashboard'; url = 'admin/general/dashboard';
} }
$('#main-menu .nav-list > li').removeClass('active').each(function() { $('#main-menu li').removeClass('active');
$('#main-menu a').removeClass('active').each(function() {
var menu = $(this), var menu = $(this),
category = menu.parents('.sidebar-nav'), href = menu.attr('href'),
href = menu.children('a').attr('href'), isLink = menu.parent().attr('data-link') === '1';
isLink = menu.attr('data-link') === '1';
if (!isLink && href && href.slice(1) === url) { if (!isLink && href && href === [config.relative_path, url].join('/')) {
category.addClass('open'); menu
menu.addClass('active'); .parent().addClass('active')
modifyBreadcrumb(category.find('.nav-header').text(), menu.text()); .parents('.menu-item').addClass('active');
$('#main-page-title').text(menu.text() + (menu.parents('.menu-item').children('a').text() === 'Settings' ? ' Settings' : ''));
} }
}); });
} }
function modifyBreadcrumb() {
var caret = ' <i class="fa fa-angle-right"></i> ';
$('#breadcrumbs').html(caret + Array.prototype.slice.call(arguments).join(caret));
}
function setupHeaderMenu() {
var env = utils.findBootstrapEnvironment();
if (env !== 'lg') {
if ($('.mobile-header').length || $('#content .col-lg-9').first().height() < 2000) {
return;
}
($('#content .col-lg-3').first().clone().addClass('mobile-header'))
.insertBefore($('#content .col-lg-9').first());
} else {
$('.mobile-header').remove();
}
}
function setupRestartLinks() { function setupRestartLinks() {
$('.restart').off('click').on('click', function() { $('.restart').off('click').on('click', function() {
bootbox.confirm('Are you sure you wish to restart NodeBB?', function(confirm) { bootbox.confirm('Are you sure you wish to restart NodeBB?', function(confirm) {
@@ -171,37 +104,54 @@
}); });
} }
function setupCheckboxes() { function launchSnackbar(params) {
if (ajaxify.currentPage.match(/^admin\/manage\/categories/)) { var bar = $.snackbar({
return $('[type=checkbox]').show(); content: "<strong>" + params.title + "</strong>" + params.message,
timeout: 3000,
htmlAllowed: true
});
if (params.clickfn) {
bar.on('click', params.clickfn);
} }
$('[type=checkbox]').change(function() {
var checked = $(this).is(':checked');
$(this).siblings('[class*=fa-]').toggleClass('fa-toggle-off', !checked)
.toggleClass('fa-toggle-on', checked);
});
$('[type=checkbox]').each(function() {
var checkbox = $(this),
checked = checkbox.is(':checked');
if (checkbox.attr('data-toggle-added')) {
return;
}
checkbox.hide();
if (checked) {
checkbox.after('<i class="fa fa-toggle-on"></i>');
}
else {
checkbox.after('<i class="fa fa-toggle-off"></i>');
}
checkbox.attr('data-toggle-added', true);
});
} }
function configureSlidemenu() {
var slideout = new Slideout({
'panel': document.getElementById('panel'),
'menu': document.getElementById('menu'),
'padding': 256,
'tolerance': 70
});
$('#mobile-menu').on('click', function() {
slideout.toggle();
});
$('#menu a').on('click', function() {
slideout.close();
});
$(window).on('resize', function() {
slideout.close();
});
function onOpeningMenu() {
$('#header').css({
'top': $('#panel').position().top * -1 + 'px',
'position': 'absolute'
});
}
slideout.on('beforeopen', onOpeningMenu);
slideout.on('open', onOpeningMenu);
slideout.on('translate', onOpeningMenu);
slideout.on('close', function() {
$('#header').css({
'top': '0px',
'position': 'fixed'
});
});
}
}()); }());

View File

@@ -9,12 +9,12 @@ define('admin/appearance/skins', function() {
scriptEl.attr('src', '//bootswatch.aws.af.cm/3/?callback=bootswatchListener'); scriptEl.attr('src', '//bootswatch.aws.af.cm/3/?callback=bootswatchListener');
$('body').append(scriptEl); $('body').append(scriptEl);
$('#bootstrap_themes').on('click', function(e){ $('#skins').on('click', function(e){
var target = $(e.target), var target = $(e.target),
action = target.attr('data-action'); action = target.attr('data-action');
if (action && action === 'use') { if (action && action === 'use') {
var parentEl = target.parents('li'), var parentEl = target.parents('[data-theme]'),
themeType = parentEl.attr('data-type'), themeType = parentEl.attr('data-type'),
cssSrc = parentEl.attr('data-css'), cssSrc = parentEl.attr('data-css'),
themeId = parentEl.attr('data-theme'); themeId = parentEl.attr('data-theme');
@@ -59,12 +59,39 @@ define('admin/appearance/skins', function() {
showRevert: true showRevert: true
}, function(html) { }, function(html) {
themeContainer.html(html); themeContainer.html(html);
if (config['theme:src']) {
var skin = config['theme:src']
.match(/latest\/(\S+)\/bootstrap.min.css/)[1]
.replace(/(^|\s)([a-z])/g , function(m,p1,p2){return p1+p2.toUpperCase();});
highlightSelectedTheme(skin);
}
}); });
}; };
function highlightSelectedTheme(themeId) { function highlightSelectedTheme(themeId) {
$('.themes li[data-theme]').removeClass('btn-warning'); $('[data-theme]')
$('.themes li[data-theme="' + themeId + '"]').addClass('btn-warning'); .removeClass('selected')
.find('[data-action="use"]').each(function() {
if ($(this).parents('[data-theme]').attr('data-theme')) {
$(this)
.html('Select Theme')
.removeClass('btn-success')
.addClass('btn-primary');
}
});
if (!themeId) {
return;
}
$('[data-theme="' + themeId + '"]')
.addClass('selected')
.find('[data-action="use"]')
.html('Current Theme')
.removeClass('btn-primary')
.addClass('btn-success');
} }
return Skins; return Skins;

View File

@@ -10,7 +10,7 @@ define('admin/appearance/themes', function() {
action = target.attr('data-action'); action = target.attr('data-action');
if (action && action === 'use') { if (action && action === 'use') {
var parentEl = target.parents('li'), var parentEl = target.parents('[data-theme]'),
themeType = parentEl.attr('data-type'), themeType = parentEl.attr('data-type'),
cssSrc = parentEl.attr('data-css'), cssSrc = parentEl.attr('data-css'),
themeId = parentEl.attr('data-theme'); themeId = parentEl.attr('data-theme');
@@ -40,16 +40,16 @@ define('admin/appearance/themes', function() {
}); });
$('#revert_theme').on('click', function() { $('#revert_theme').on('click', function() {
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) { bootbox.confirm('Are you sure you wish to restore the default NodeBB theme?', function(confirm) {
if (confirm) { if (confirm) {
socket.emit('admin.themes.set', { socket.emit('admin.themes.set', {
type: 'local', type: 'local',
id: 'nodebb-theme-vanilla' id: 'nodebb-theme-persona'
}, function(err) { }, function(err) {
if (err) { if (err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
highlightSelectedTheme('nodebb-theme-vanilla'); highlightSelectedTheme('nodebb-theme-persona');
app.alert({ app.alert({
alert_id: 'admin:theme', alert_id: 'admin:theme',
type: 'success', type: 'success',
@@ -84,8 +84,19 @@ define('admin/appearance/themes', function() {
}; };
function highlightSelectedTheme(themeId) { function highlightSelectedTheme(themeId) {
$('.themes li[data-theme]').removeClass('btn-warning'); $('[data-theme]')
$('.themes li[data-theme="' + themeId + '"]').addClass('btn-warning'); .removeClass('selected')
.find('[data-action="use"]')
.html('Select Theme')
.removeClass('btn-success')
.addClass('btn-primary');
$('[data-theme="' + themeId + '"]')
.addClass('selected')
.find('[data-action="use"]')
.html('Current Theme')
.removeClass('btn-primary')
.addClass('btn-success');
} }
return Themes; return Themes;

View File

@@ -13,6 +13,8 @@ define('admin/extend/plugins', function() {
return; return;
} }
$('#plugin-search').val('');
pluginsList.on('click', 'button[data-action="toggleActive"]', function() { pluginsList.on('click', 'button[data-action="toggleActive"]', function() {
pluginID = $(this).parents('li').attr('data-plugin-id'); pluginID = $(this).parents('li').attr('data-plugin-id');
var btn = $(this); var btn = $(this);

View File

@@ -17,6 +17,13 @@ define('admin/extend/widgets', function() {
return false; return false;
}); });
$('#widget-selector').on('change', function() {
$('.available-widgets [data-widget]').addClass('hide');
$('.available-widgets [data-widget="' + $(this).val() + '"]').removeClass('hide');
});
$('#widget-selector').trigger('change');
loadWidgetData(); loadWidgetData();
}; };
@@ -64,7 +71,7 @@ define('admin/extend/widgets', function() {
} }
}); });
$('#widgets .save').on('click', saveWidgets); $('#save').on('click', saveWidgets);
function saveWidgets() { function saveWidgets() {
var total = $('#widgets [data-template][data-location]').length; var total = $('#widgets [data-template][data-location]').length;
@@ -198,7 +205,7 @@ define('admin/extend/widgets', function() {
for (var k=0; k<area.data.length; ++k) { for (var k=0; k<area.data.length; ++k) {
var widgetData = area.data[k], var widgetData = area.data[k],
widgetEl = $('.available-widgets [data-widget="' + widgetData.widget + '"]').clone(true); widgetEl = $('.available-widgets [data-widget="' + widgetData.widget + '"]').clone(true).removeClass('hide');
widgetArea.append(populateWidget(widgetEl, widgetData.data)); widgetArea.append(populateWidget(widgetEl, widgetData.data));
appendToggle(widgetEl); appendToggle(widgetEl);

View File

@@ -50,11 +50,11 @@ define('admin/manage/category', [
function enableColorPicker(idx, inputEl) { function enableColorPicker(idx, inputEl) {
var $inputEl = $(inputEl), var $inputEl = $(inputEl),
previewEl = $inputEl.parents('[data-cid]').find('.preview-box'); previewEl = $inputEl.parents('[data-cid]').find('.category-preview');
colorpicker.enable($inputEl, function(hsb, hex) { colorpicker.enable($inputEl, function(hsb, hex) {
if ($inputEl.attr('data-name') === 'bgColor') { if ($inputEl.attr('data-name') === 'bgColor') {
previewEl.css('background', '#' + hex); previewEl.css('background-color', '#' + hex);
} else if ($inputEl.attr('data-name') === 'color') { } else if ($inputEl.attr('data-name') === 'color') {
previewEl.css('color', '#' + hex); previewEl.css('color', '#' + hex);
} }
@@ -63,35 +63,24 @@ define('admin/manage/category', [
}); });
} }
function setupEditTargets() {
$('[data-edit-target]').on('click', function() {
var $this = $(this),
target = $($this.attr('data-edit-target'));
$this.addClass('hide');
target.removeClass('hide').on('blur', function() {
$this.removeClass('hide').children('span').text(this.value).html();
$(this).addClass('hide');
}).val($this.children('span').html().text());
target.focus();
});
}
// If any inputs have changed, prepare it for saving // If any inputs have changed, prepare it for saving
$('form.category input, form.category select').on('change', function(ev) { $('form.category input, form.category select').on('change', function(ev) {
modified(ev.target); modified(ev.target);
}); });
// Update preview image size on change
$('[data-name="imageClass"]').on('change', function(ev) {
$('.category-preview').css('background-size', $(this).val());
});
// Colour Picker // Colour Picker
$('[data-name="bgColor"], [data-name="color"]').each(enableColorPicker); $('[data-name="bgColor"], [data-name="color"]').each(enableColorPicker);
$('.save').on('click', save); $('#save').on('click', save);
$('.revert').on('click', ajaxify.refresh);
$('.purge').on('click', function(e) { $('.purge').on('click', function(e) {
e.preventDefault(); e.preventDefault();
bootbox.confirm('<p class="lead">Do you really want to purge this category "' + $('form.category').find('input[data-name="name"]').val() + '"?</p><p><strong class="text-danger">Warning!</strong> All topics and posts in this category will be purged!</p>', function(confirm) { bootbox.confirm('<p class="lead">Do you really want to purge this category "' + $('form.category').find('input[data-name="name"]').val() + '"?</p><h5><strong class="text-danger">Warning!</strong> All topics and posts in this category will be purged!</h5> <p class="help-block">Purging a category will remove all topics and posts, and delete the category from the database. If you want to remove a category <em>temporarily</em>, you\'ll want to "disable" the category instead.</p>', function(confirm) {
if (!confirm) { if (!confirm) {
return; return;
} }
@@ -113,8 +102,7 @@ define('admin/manage/category', [
uploader.open(RELATIVE_PATH + '/api/admin/category/uploadpicture', { cid: cid }, 0, function(imageUrlOnServer) { uploader.open(RELATIVE_PATH + '/api/admin/category/uploadpicture', { cid: cid }, 0, function(imageUrlOnServer) {
inputEl.val(imageUrlOnServer); inputEl.val(imageUrlOnServer);
var previewBox = inputEl.parent().parent().siblings('.category-preview'); var previewBox = inputEl.parent().parent().siblings('.category-preview');
previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')') previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
.css('background-size', 'cover');
modified(inputEl[0]); modified(inputEl[0]);
}); });
}); });
@@ -154,7 +142,6 @@ define('admin/manage/category', [
}); });
}); });
setupEditTargets();
Category.setupPrivilegeTable(); Category.setupPrivilegeTable();
}; };

View File

@@ -50,14 +50,10 @@ define(function() {
return false; return false;
}); });
$('.sidebar-nav a').each(function(idx, link) { $('#main-menu a').each(function(idx, link) {
routes.push($(link).attr('href')); routes.push($(link).attr('href'));
}); });
input.on('blur', function() {
$(this).val('').attr('placeholder', '/');
});
input.on('keyup focus', function() { input.on('keyup focus', function() {
var $input = $(this), var $input = $(this),
value = $input.val().toLowerCase(), value = $input.val().toLowerCase(),
@@ -67,8 +63,6 @@ define(function() {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
} }
$input.attr('placeholder', '');
firstResult = null; firstResult = null;
if (value.length >= 3) { if (value.length >= 3) {
@@ -101,15 +95,14 @@ define(function() {
} }
} }
if (menuItems.html() !== '') { if (menuItems.html() === '') {
menuItems.append('<li role="presentation" class="divider"></li>');
} else {
menuItems.append('<li role="presentation"><a role="menuitem" href="#">No results...</a></li>'); menuItems.append('<li role="presentation"><a role="menuitem" href="#">No results...</a></li>');
} }
} }
if (value.length > 0) { if (value.length > 0) {
if (config.searchEnabled) { if (config.searchEnabled) {
menuItems.append('<li role="presentation" class="divider"></li>');
menuItems.append('<li role="presentation"><a role="menuitem" target="_top" href="' + RELATIVE_PATH + '/search/' + value + '">Search the forum for <strong>' + value + '</strong></a></li>'); menuItems.append('<li role="presentation"><a role="menuitem" target="_top" href="' + RELATIVE_PATH + '/search/' + value + '">Search the forum for <strong>' + value + '</strong></a></li>');
} else if (value.length < 3) { } else if (value.length < 3) {
menuItems.append('<li role="presentation"><a role="menuitem" href="#">Type more to see results...</a></li>'); menuItems.append('<li role="presentation"><a role="menuitem" href="#">Type more to see results...</a></li>');

View File

@@ -5,7 +5,21 @@ define('admin/settings', ['uploader', 'sounds'], function(uploader, sounds) {
var Settings = {}; var Settings = {};
Settings.init = function() { Settings.init = function() {
$(window).on('action:config.loaded', Settings.prepare); if (!app.config) {
$(window).on('action:config.loaded', Settings.prepare);
} else {
Settings.prepare();
}
};
Settings.populateTOC = function() {
$('.settings-header').each(function() {
var header = $(this).text(),
anchor = header.toLowerCase().replace(/ /g, '-').trim();
$(this).prepend('<a name="' + anchor + '"></a>');
$('.section-content ul').append('<li><a href="#' + anchor + '">' + header + '</a></li>');
});
}; };
Settings.prepare = function(callback) { Settings.prepare = function(callback) {

View File

@@ -150,7 +150,7 @@ $(document).ready(function() {
$('#content, #footer').removeClass('ajaxifying'); $('#content, #footer').removeClass('ajaxifying');
app.refreshTitle(url); app.refreshTitle(data.title);
}); });
}); });
} }

View File

@@ -92,7 +92,7 @@ app.cacheBuster = null;
switch(url_parts[0]) { switch(url_parts[0]) {
case 'user': case 'user':
room = 'user/' + ajaxify.data ? ajaxify.data.theirid : 0; room = 'user/' + (ajaxify.data ? ajaxify.data.theirid : 0);
break; break;
case 'topic': case 'topic':
room = 'topic_' + url_parts[1]; room = 'topic_' + url_parts[1];
@@ -130,6 +130,50 @@ app.cacheBuster = null;
} }
} }
function overrideBootbox() {
var dialog = bootbox.dialog,
prompt = bootbox.prompt,
confirm = bootbox.confirm;
function translate(modal) {
var footer = modal.find('.modal-footer');
translator.translate(footer.html(), function(html) {
footer.html(html);
});
}
bootbox.dialog = function() {
var modal = $(dialog.apply(this, arguments)[0]);
translate(modal);
return modal;
}
bootbox.prompt = function() {
var modal = $(prompt.apply(this, arguments)[0]);
translate(modal);
return modal;
}
bootbox.confirm = function() {
var modal = $(confirm.apply(this, arguments)[0]);
translate(modal);
return modal;
}
}
function overrideTimeago() {
var timeagoFn = $.fn.timeago;
$.fn.timeago = function() {
var els = timeagoFn.apply(this, arguments);
if (els) {
els.each(function() {
$(this).attr('title', (new Date($(this).attr('title'))).toString());
});
}
};
}
app.logout = function() { app.logout = function() {
require(['csrf'], function(csrf) { require(['csrf'], function(csrf) {
$.ajax(RELATIVE_PATH + '/logout', { $.ajax(RELATIVE_PATH + '/logout', {
@@ -241,8 +285,6 @@ app.cacheBuster = null;
app.processPage = function () { app.processPage = function () {
highlightNavigationLink(); highlightNavigationLink();
utils.overrideTimeago();
$('.timeago').timeago(); $('.timeago').timeago();
utils.makeNumbersHumanReadable($('.human-readable-number')); utils.makeNumbersHumanReadable($('.human-readable-number'));
@@ -347,19 +389,13 @@ app.cacheBuster = null;
} }
}; };
app.refreshTitle = function(url) { app.refreshTitle = function(title) {
if (!url) { require(['translator'], function(translator) {
var a = document.createElement('a'); translator.translate(title, function(translated) {
a.href = document.location; translated = translated ? (translated + ' | ' + config.browserTitle) : config.browserTitle;
url = a.pathname.slice(1); titleObj.titles[0] = translated;
} app.alternatingTitle('');
});
socket.emit('meta.buildTitle', url, function(err, title, numNotifications) {
if (err) {
return;
}
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
app.alternatingTitle('');
}); });
}; };
@@ -451,13 +487,16 @@ app.cacheBuster = null;
}; };
function handleStatusChange() { function handleStatusChange() {
$('#user-control-list .user-status').off('click').on('click', function(e) { $('[component="header/usercontrol"] [data-status]').off('click').on('click', function(e) {
var status = $(this).attr('data-status'); var status = $(this).attr('data-status');
socket.emit('user.setStatus', status, function(err, data) { socket.emit('user.setStatus', status, function(err, data) {
if(err) { if(err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
$('#logged-in-menu #user_label #user-profile-link>i').attr('class', 'fa fa-circle status ' + status); $('[component="user/status"]')
.removeClass('away online dnd offline')
.addClass(status);
app.user.status = status; app.user.status = status;
}); });
e.preventDefault(); e.preventDefault();
@@ -491,6 +530,9 @@ app.cacheBuster = null;
if (err) { if (err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
categories = categories.filter(function(category) {
return !category.link && !parseInt(category.parentCid, 10);
});
if (categories.length) { if (categories.length) {
$(window).trigger('action:composer.topic.new', { $(window).trigger('action:composer.topic.new', {
cid: categories[0].cid cid: categories[0].cid
@@ -503,7 +545,7 @@ app.cacheBuster = null;
app.load = function() { app.load = function() {
$('document').ready(function () { $('document').ready(function () {
var url = ajaxify.start(window.location.pathname.slice(1), true, window.location.search); var url = ajaxify.start(window.location.pathname.slice(1) + window.location.search, true);
ajaxify.end(url, app.template); ajaxify.end(url, app.template);
handleStatusChange(); handleStatusChange();
@@ -514,7 +556,9 @@ app.cacheBuster = null;
handleNewTopic(); handleNewTopic();
$('#logout-link').on('click', app.logout); require(['components'], function(components) {
components.get('user/logout').on('click', app.logout);
});
Visibility.change(function(e, state){ Visibility.change(function(e, state){
if (state === 'visible') { if (state === 'visible') {
@@ -525,6 +569,8 @@ app.cacheBuster = null;
} }
}); });
overrideBootbox();
overrideTimeago();
createHeaderTooltips(); createHeaderTooltips();
app.showEmailConfirmWarning(); app.showEmailConfirmWarning();

View File

@@ -87,18 +87,20 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
} }
function updateHeader(picture, username, userslug) { function updateHeader(picture, username, userslug) {
if (parseInt(ajaxify.data.theirid, 10) !== parseInt(ajaxify.data.yourid, 10)) { require(['components'], function(components) {
return; if (parseInt(ajaxify.data.theirid, 10) !== parseInt(ajaxify.data.yourid, 10)) {
} return;
}
if (picture) { if (picture) {
$('#user-header-picture').attr('src', picture); components.get('header/userpicture').attr('src', picture);
} }
if (username && userslug) { if (username && userslug) {
$('#user-profile-link').attr('href', config.relative_path + '/user/' + userslug); components.get('header/profilelink').attr('href', config.relative_path + '/user/' + userslug);
$('#user-header-name').text(username); components.get('header/username').text(username);
} }
});
} }
function handleImageChange() { function handleImageChange() {
@@ -266,7 +268,9 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
if (password.val()) { if (password.val()) {
showSuccess(password_confirm_notify, successIcon); showSuccess(password_confirm_notify, successIcon);
} else { } else {
removeAlert(password_confirm_notify); password_confirm_notify.parent().removeClass('alert-success alert-danger');
password_confirm_notify.children().show();
password_confirm_notify.find('.msg').html('');
} }
passwordsmatch = true; passwordsmatch = true;
@@ -365,7 +369,8 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
function showError(element, msg) { function showError(element, msg) {
translator.translate(msg, function(msg) { translator.translate(msg, function(msg) {
element.html(msg); element.find('.msg').html(msg).siblings().hide();
element.parent() element.parent()
.removeClass('alert-success') .removeClass('alert-success')
.addClass('alert-danger'); .addClass('alert-danger');
@@ -375,7 +380,7 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
function showSuccess(element, msg) { function showSuccess(element, msg) {
translator.translate(msg, function(msg) { translator.translate(msg, function(msg) {
element.html(msg); element.find('.msg').html(msg);
element.parent() element.parent()
.removeClass('alert-danger') .removeClass('alert-danger')
.addClass('alert-success'); .addClass('alert-success');
@@ -383,10 +388,5 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
}); });
} }
function removeAlert(element) {
element.html('');
element.parent().removeClass('alert-success alert-danger');
}
return AccountEdit; return AccountEdit;
}); });

View File

@@ -66,20 +66,21 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll',
popoutEl.on('click', function() { popoutEl.on('click', function() {
var username = $('.expanded-chat').attr('data-username'), var username = $('.expanded-chat').attr('data-username'),
uid = Chats.getRecipientUid(); uid = Chats.getRecipientUid(),
text = components.get('chat/input').val();
if (app.previousUrl && app.previousUrl.match(/chats/)) { if (app.previousUrl && app.previousUrl.match(/chats/)) {
var text = components.get('chat/input').val();
ajaxify.go('chats', function() { ajaxify.go('chats', function() {
app.openChat(username, uid); app.openChat(username, uid);
}, true); }, true);
$(window).one('action:chat.loaded', function() {
components.get('chat/input').val(text);
});
} else { } else {
window.history.go(-1); window.history.go(-1);
app.openChat(username, uid);
} }
$(window).one('action:chat.loaded', function() {
components.get('chat/input').val(text);
});
}); });
$('.recent-chats').on('scroll', function() { $('.recent-chats').on('scroll', function() {

View File

@@ -121,7 +121,9 @@ define('forum/topic', [
var postIndex = getPostIndex(); var postIndex = getPostIndex();
if (postIndex && window.location.search.indexOf('page=') === -1) { if (postIndex && window.location.search.indexOf('page=') === -1) {
navigator.scrollToPost(postIndex - 1, true); if (components.get('post/anchor', postIndex).length) {
return navigator.scrollToPostIndex(postIndex - 1, true);
}
} else if (bookmark && (!config.usePagination || (config.usePagination && pagination.currentPage === 1)) && ajaxify.data.postcount > 1) { } else if (bookmark && (!config.usePagination || (config.usePagination && pagination.currentPage === 1)) && ajaxify.data.postcount > 1) {
app.alert({ app.alert({
alert_id: 'bookmark', alert_id: 'bookmark',
@@ -140,10 +142,18 @@ define('forum/topic', [
function getPostIndex() { function getPostIndex() {
var parts = window.location.pathname.split('/'); var parts = window.location.pathname.split('/');
if (parts[parts.length - 1] && utils.isNumber(parts[parts.length - 1])) { var lastPart = parts[parts.length - 1];
return parseInt(parts[parts.length - 1], 10); if (lastPart && utils.isNumber(lastPart)) {
lastPart = parseInt(lastPart, 10);
} else {
return 0;
} }
return 0;
while (lastPart > 0 && !components.get('post/anchor', lastPart).length) {
lastPart --;
}
return lastPart;
} }
function addBlockQuoteHandler() { function addBlockQuoteHandler() {

View File

@@ -139,10 +139,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
selection = window.getSelection ? window.getSelection() : document.selection.createRange(); selection = window.getSelection ? window.getSelection() : document.selection.createRange();
if ($(selection.baseNode).parents('[component="post/content"]').length > 0) { if ($(selection.baseNode).parents('[component="post/content"]').length > 0) {
var snippet = selection.toString(); selectionText = selection.toString();
if (snippet.length) {
selectionText = '> ' + snippet.replace(/\n/g, '\n> ') + '\n\n';
}
} }
var username = getUserName(selectionText ? $(selection.baseNode) : button); var username = getUserName(selectionText ? $(selection.baseNode) : button);
@@ -177,10 +174,6 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
if(err) { if(err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
var quoted = '';
if(post) {
quoted = '> ' + post.replace(/\n/g, '\n> ') + '\n\n';
}
$(window).trigger('action:composer.addQuote', { $(window).trigger('action:composer.addQuote', {
tid: tid, tid: tid,
@@ -189,7 +182,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
pid: pid, pid: pid,
username: username, username: username,
topicName: topicName, topicName: topicName,
text: quoted text: post
}); });
}); });
} }

View File

@@ -7,9 +7,8 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
var newMessage = false; var newMessage = false;
module.prepareDOM = function() { module.prepareDOM = function() {
var chatsToggleEl = $('#chat_dropdown'), var chatsToggleEl = components.get('chat/dropdown'),
chatsListEl = $('#chat-list'), chatsListEl = components.get('chat/list');
dropdownEl;
// Sync open chats between all user socket sessions // Sync open chats between all user socket sessions
module.sync(); module.sync();
@@ -19,46 +18,7 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
return; return;
} }
socket.emit('modules.chats.getRecentChats', {after: 0}, function(err, chats) { module.loadChats(chatsListEl);
if (err) {
return app.alertError(err.message);
}
chats = chats.users;
var userObj;
chatsListEl.empty();
if (!chats.length) {
translator.translate('[[modules:chat.no_active]]', function(str) {
$('<li />')
.addClass('no_active')
.html('<a href="#">' + str + '</a>')
.appendTo(chatsListEl);
});
return;
}
for(var x = 0; x<chats.length; ++x) {
userObj = chats[x];
dropdownEl = $('<li class="' + (userObj.unread ? 'unread' : '') + '"/>')
.attr('data-uid', userObj.uid)
.html('<a data-ajaxify="false">'+
'<img src="' + userObj.picture + '" title="' + userObj.username +'" />' +
'<i class="fa fa-circle status ' + userObj.status + '"></i> ' +
userObj.username + '</a>')
.appendTo(chatsListEl);
(function(userObj) {
dropdownEl.click(function() {
if (!ajaxify.currentPage.match(/^chats\//)) {
app.openChat(userObj.username, userObj.uid);
} else {
ajaxify.go('chats/' + utils.slugify(userObj.username));
}
});
})(userObj);
}
});
}); });
socket.on('event:chats.receive', function(data) { socket.on('event:chats.receive', function(data) {
@@ -139,7 +99,7 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
username: chatObj.options.title, username: chatObj.options.title,
uid: chatObj.options.touid, uid: chatObj.options.touid,
new: chatObj.element.hasClass('new') new: chatObj.element.hasClass('new')
} };
}); });
callback(null, chats); callback(null, chats);
@@ -170,6 +130,51 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
}); });
}; };
module.loadChats = function(chatsListEl) {
var dropdownEl;
socket.emit('modules.chats.getRecentChats', {after: 0}, function(err, chats) {
if (err) {
return app.alertError(err.message);
}
chats = chats.users;
var userObj;
chatsListEl.empty();
if (!chats.length) {
translator.translate('[[modules:chat.no_active]]', function(str) {
$('<li />')
.addClass('no_active')
.html('<a href="#">' + str + '</a>')
.appendTo(chatsListEl);
});
return;
}
for(var x = 0; x<chats.length; ++x) {
userObj = chats[x];
dropdownEl = $('<li class="' + (userObj.unread ? 'unread' : '') + '"/>')
.attr('data-uid', userObj.uid)
.html('<a data-ajaxify="false">'+
'<img src="' + userObj.picture + '" title="' + userObj.username +'" />' +
'<i class="fa fa-circle status ' + userObj.status + '"></i> ' +
userObj.username + '</a>')
.appendTo(chatsListEl);
(function(userObj) {
dropdownEl.click(function() {
if (!ajaxify.currentPage.match(/^chats\//)) {
app.openChat(userObj.username, userObj.uid);
} else {
ajaxify.go('chats/' + utils.slugify(userObj.username));
}
});
})(userObj);
}
});
};
module.bringModalToTop = function(chatModal) { module.bringModalToTop = function(chatModal) {
var topZ = 0; var topZ = 0;

View File

@@ -147,6 +147,10 @@
}).join(''); }).join('');
}; };
helpers.localeToHTML = function(locale) {
return locale.replace('_', '-');
};
exports.register = function() { exports.register = function() {
var templates; var templates;

View File

@@ -175,18 +175,18 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
navigator.scrollActive = true; navigator.scrollActive = true;
if (components.get('post/anchor', postIndex).length) { if (components.get('post/anchor', postIndex).length) {
return scrollToPid(postIndex, highlight, duration, offset); return navigator.scrollToPostIndex(postIndex, highlight, duration, offset);
} }
if (config.usePagination) { if (config.usePagination) {
var page = Math.max(1, Math.ceil(postIndex / config.postsPerPage)); var page = Math.max(1, Math.ceil(postIndex / config.postsPerPage));
if(parseInt(page, 10) !== pagination.currentPage) { if (parseInt(page, 10) !== pagination.currentPage) {
pagination.loadPage(page, function() { pagination.loadPage(page, function() {
scrollToPid(postIndex, highlight, duration, offset); navigator.scrollToPostIndex(postIndex, highlight, duration, offset);
}); });
} else { } else {
scrollToPid(postIndex, highlight, duration, offset); navigator.scrollToPostIndex(postIndex, highlight, duration, offset);
} }
} else { } else {
navigator.scrollActive = false; navigator.scrollActive = false;
@@ -195,14 +195,16 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
} }
}; };
function scrollToPid(postIndex, highlight, duration, offset) { navigator.scrollToPostIndex = function(postIndex, highlight, duration, offset) {
var scrollTo = components.get('post/anchor', postIndex); var scrollTo = components.get('post/anchor', postIndex);
if (!scrollTo.length) { if (!scrollTo.length) {
navigator.scrollActive = false; navigator.scrollActive = false;
return; return;
} }
offset = offset || 0;
duration = duration !== undefined ? duration : 400;
navigator.scrollActive = true;
var done = false; var done = false;
function animateScroll() { function animateScroll() {
$('html, body').animate({ $('html, body').animate({
@@ -232,8 +234,10 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
if (components.get('topic').length) { if (components.get('topic').length) {
animateScroll(); animateScroll();
} else {
navigator.scrollActive = false;
} }
} };
return navigator; return navigator;

View File

@@ -2,14 +2,14 @@
/* globals define, socket, utils, config, app, ajaxify, templates, Tinycon*/ /* globals define, socket, utils, config, app, ajaxify, templates, Tinycon*/
define('notifications', ['sounds', 'translator'], function(sound, translator) { define('notifications', ['sounds', 'translator', 'components'], function(sound, translator, components) {
var Notifications = {}; var Notifications = {};
Notifications.prepareDOM = function() { Notifications.prepareDOM = function() {
var notifContainer = $('.notifications'), var notifContainer = $('.notifications'),
notifTrigger = notifContainer.children('a'), notifTrigger = notifContainer.children('a'),
notifList = $('#notif-list'), notifList = $('#notif-list'),
notifIcon = $('.notification-icon'); notifIcon = components.get('notifications/icon');
notifTrigger.on('click', function(e) { notifTrigger.on('click', function(e) {
e.preventDefault(); e.preventDefault();
@@ -17,25 +17,7 @@ define('notifications', ['sounds', 'translator'], function(sound, translator) {
return; return;
} }
socket.emit('notifications.get', null, function(err, data) { Notifications.loadNotifications(notifList);
if (err) {
return app.alertError(err.message);
}
var notifs = data.unread.concat(data.read).sort(function(a, b) {
return parseInt(a.datetime, 10) > parseInt(b.datetime, 10) ? -1 : 1;
});
translator.toggleTimeagoShorthand();
for(var i=0; i<notifs.length; ++i) {
notifs[i].timeago = $.timeago(new Date(parseInt(notifs[i].datetime, 10)));
}
translator.toggleTimeagoShorthand();
templates.parse('partials/notifications_list', {notifications: notifs}, function(html) {
notifList.translateHtml(html);
});
});
}); });
notifList.on('click', '[data-nid]', function() { notifList.on('click', '[data-nid]', function() {
@@ -114,8 +96,30 @@ define('notifications', ['sounds', 'translator'], function(sound, translator) {
}); });
}; };
Notifications.loadNotifications = function(notifList) {
socket.emit('notifications.get', null, function(err, data) {
if (err) {
return app.alertError(err.message);
}
var notifs = data.unread.concat(data.read).sort(function(a, b) {
return parseInt(a.datetime, 10) > parseInt(b.datetime, 10) ? -1 : 1;
});
translator.toggleTimeagoShorthand();
for(var i=0; i<notifs.length; ++i) {
notifs[i].timeago = $.timeago(new Date(parseInt(notifs[i].datetime, 10)));
}
translator.toggleTimeagoShorthand();
templates.parse('partials/notifications_list', {notifications: notifs}, function(html) {
notifList.translateHtml(html);
});
});
};
Notifications.updateNotifCount = function(count) { Notifications.updateNotifCount = function(count) {
var notifIcon = $('.notification-icon'); var notifIcon = components.get('notifications/icon');
if (count > 0) { if (count > 0) {
notifIcon.removeClass('fa-bell-o').addClass('fa-bell'); notifIcon.removeClass('fa-bell-o').addClass('fa-bell');

View File

@@ -9,7 +9,7 @@
var languages = {}, var languages = {},
regexes = { regexes = {
match: /\[\[\w+:[^\]]+?\]\]/g, match: /\[\[\w+:.*?\]\]/g,
split: /[,][\s]*/, split: /[,][\s]*/,
replace: /\]+$/ replace: /\]+$/
}; };

View File

@@ -203,19 +203,6 @@
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"); return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}, },
overrideTimeago: function() {
var timeagoFn = $.fn.timeago;
$.fn.timeago = function() {
var els = timeagoFn.apply(this, arguments);
if (els) {
els.each(function() {
$(this).attr('title', (new Date($(this).attr('title'))).toString());
});
}
};
},
toISOString: function(timestamp) { toISOString: function(timestamp) {
if (!timestamp || !Date.prototype.toISOString) { if (!timestamp || !Date.prototype.toISOString) {
return ''; return '';

File diff suppressed because one or more lines are too long

9724
public/vendor/mdl/mdl.css vendored Normal file

File diff suppressed because it is too large Load Diff

1
public/vendor/mdl/mdl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,54 +0,0 @@
/** initial setup **/
.nano {
position : relative;
width : 100%;
height : 100%;
overflow : hidden;
}
.nano > .nano-content {
position : absolute;
overflow : scroll;
overflow-x : hidden;
top : 0;
right : 0;
bottom : 0;
left : 0;
}
.nano > .nano-content:focus {
outline: thin dotted;
}
.nano > .nano-content::-webkit-scrollbar {
display: none;
}
.has-scrollbar > .nano-content::-webkit-scrollbar {
display: block;
}
.nano > .nano-pane {
background : rgba(0,0,0,.25);
position : absolute;
width : 10px;
right : 0;
top : 0;
bottom : 0;
visibility : hidden\9; /* Target only IE7 and IE8 with this hack */
opacity : .01;
-webkit-transition : .2s;
-moz-transition : .2s;
-o-transition : .2s;
transition : .2s;
-moz-border-radius : 5px;
-webkit-border-radius : 5px;
border-radius : 5px;
}
.nano > .nano-pane > .nano-slider {
background: rgba(255, 255, 255, 0.3);
position : relative;
margin : 0 1px;
-moz-border-radius : 3px;
-webkit-border-radius : 3px;
border-radius : 3px;
}
.nano:hover > .nano-pane, .nano-pane.active, .nano-pane.flashed {
visibility : visible\9; /* Target only IE7 and IE8 with this hack */
opacity : 0.99;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
/* SnackbarJS - MIT LICENSE (https://github.com/FezVrasta/snackbarjs/blob/master/LICENSE.md) */
!function(t){"function"==typeof define&&define.amd&&t(jQuery)}(function(t){function a(t){return"undefined"!=typeof t&&null!==t?!0:!1}t(document).ready(function(){t("body").append("<div id=snackbar-container/>")}),t(document).on("click","[data-toggle=snackbar]",function(){t(this).snackbar("toggle")}).on("click","#snackbar-container .snackbar",function(){t(this).snackbar("hide")}),t.snackbar=function(n){if(a(n)&&n===Object(n)){var e,o=!1;a(n.id)?t("#"+n.id).length?e=t("#"+n.id):(e=t("<div/>").attr("id",""+n.id).attr("class","snackbar"),o=!0):(e=t("<div/>").attr("id","snackbar"+Date.now()).attr("class","snackbar"),o=!0);var i=e.hasClass("snackbar-opened");a(n.style)?(i?e.attr("class","snackbar snackbar-opened "+n.style):e.attr("class","snackbar "+n.style),e.attr("data-style",n.style)):i?e.attr("class","snackbar snackbar-opened"):e.attr("class","snackbar"),n.htmlAllowed=a(n.htmlAllowed)?n.htmlAllowed:!1,n.timeout=a(n.timeout)?n.timeout:3e3,e.attr("data-timeout",n.timeout),n.content=n.htmlAllowed?n.content:t("<p>"+n.content+"</p>").text(),a(n.htmlAllowed)&&e.attr("data-html-allowed",n.htmlAllowed),a(n.content)&&(e.find(".snackbar-content").length?e.find(".snackbar-content").html(n.content):e.prepend("<span class=snackbar-content>"+n.content+"</span>"),e.attr("data-content",n.content)),o?e.appendTo("#snackbar-container"):e.insertAfter("#snackbar-container .snackbar:last-child"),a(n.action)&&"toggle"==n.action&&(n.action=i?"hide":"show");var s=Date.now();e.data("animationId1",s),setTimeout(function(){e.data("animationId1")===s&&(a(n.action)&&"show"!=n.action?a(n.action)&&"hide"==n.action&&e.removeClass("snackbar-opened"):e.addClass("snackbar-opened"))},50);var c=Date.now();return e.data("animationId2",c),0!==n.timeout&&setTimeout(function(){e.data("animationId2")===c&&e.removeClass("snackbar-opened")},n.timeout),e}return!1},t.fn.snackbar=function(n){if("undefined"!=typeof n){var e={};if(this.hasClass("snackbar"))return e={id:this.attr("id"),content:t(this).attr("data-content"),style:t(this).attr("data-style"),timeout:t(this).attr("data-timeout"),htmlAllowed:t(this).attr("data-html-allowed")},("show"===n||"hide"===n||"toggle"==n)&&(e.action=n),t.snackbar(e);a(n)&&"show"!==n&&"hide"!==n&&"toggle"!=n||(e={content:t(this).attr("data-content"),style:t(this).attr("data-style"),timeout:t(this).attr("data-timeout"),htmlAllowed:t(this).attr("data-html-allowed")}),a(n)&&(e.id=this.attr("data-snackbar-id"),("show"===n||"hide"===n||"toggle"==n)&&(e.action=n));var o=t.snackbar(e);return this.attr("data-snackbar-id",o.attr("id")),o}}});

View File

@@ -103,10 +103,10 @@ var async = require('async'),
}); });
}; };
Categories.getCategoriesByPrivilege = function(uid, privilege, callback) { Categories.getCategoriesByPrivilege = function(set, uid, privilege, callback) {
async.waterfall([ async.waterfall([
function(next) { function(next) {
db.getSortedSetRange('categories:cid', 0, -1, next); db.getSortedSetRange(set, 0, -1, next);
}, },
function(cids, next) { function(cids, next) {
privileges.categories.filterCids(privilege, cids, uid, next); privileges.categories.filterCids(privilege, cids, uid, next);
@@ -273,6 +273,7 @@ var async = require('async'),
if (!category) { if (!category) {
return; return;
} }
var postCount = parseInt(category.post_count, 10) || 0; var postCount = parseInt(category.post_count, 10) || 0;
var topicCount = parseInt(category.topic_count, 10) || 0; var topicCount = parseInt(category.topic_count, 10) || 0;
if (!Array.isArray(category.children) || !category.children.length) { if (!Array.isArray(category.children) || !category.children.length) {
@@ -282,9 +283,11 @@ var async = require('async'),
} }
category.children.forEach(function(child) { category.children.forEach(function(child) {
postCount += parseInt(child.post_count, 10) || 0; calculateTopicPostCount(child);
topicCount += parseInt(child.topic_count, 10) || 0; postCount += parseInt(child.totalPostCount, 10) || 0;
topicCount += parseInt(child.totalTopicCount, 10) || 0;
}); });
category.totalPostCount = postCount; category.totalPostCount = postCount;
category.totalTopicCount = topicCount; category.totalTopicCount = topicCount;
} }
@@ -308,22 +311,57 @@ var async = require('async'),
}; };
Categories.getChildren = function(cids, uid, callback) { Categories.getChildren = function(cids, uid, callback) {
var categories = cids.map(function(cid) {
return {cid: cid};
});
async.each(categories, function(category, next) {
getChildrenRecursive(category, uid, next);
}, function (err) {
callback(err, categories.map(function(c) {
return c && c.children;
}));
});
};
function getChildrenRecursive(category, uid, callback) {
async.waterfall([ async.waterfall([
async.apply(db.getSortedSetRange, 'categories:cid', 0, -1), function (next) {
function(cids, next) { db.getSortedSetRange('cid:' + category.cid + ':children', 0, -1, next);
privileges.categories.filterCids('find', cids, uid, next);
}, },
function (cids, next) { function (children, next) {
Categories.getCategoriesData(cids, next); privileges.categories.filterCids('find', children, uid, next);
}, },
function (categories, next) { function (children, next) {
async.map(cids, function(cid, next) { if (!children.length) {
next(null, categories.filter(function(category) { category.children = [];
return category && parseInt(category.parentCid, 10) === parseInt(cid, 10); return callback();
})); }
Categories.getCategoriesData(children, next);
},
function (childrenData, next) {
category.children = childrenData;
async.each(category.children, function(child, next) {
getChildrenRecursive(child, uid, next);
}, next); }, next);
} }
], callback); ], callback);
}
Categories.flattenCategories = function(allCategories, categoryData) {
categoryData.forEach(function(category) {
if (!category) {
return;
}
if (!category.parent) {
allCategories.push(category);
}
if (Array.isArray(category.children) && category.children.length) {
Categories.flattenCategories(allCategories, category.children);
}
});
}; };
/** /**
@@ -335,13 +373,13 @@ var async = require('async'),
Categories.getTree = function(categories, parentCid) { Categories.getTree = function(categories, parentCid) {
var tree = [], i = 0, len = categories.length, category; var tree = [], i = 0, len = categories.length, category;
for(i; i < len; ++i) { for (i; i < len; ++i) {
category = categories[i]; category = categories[i];
if (!category.hasOwnProperty('parentCid')) { if (!category.hasOwnProperty('parentCid')) {
category.parentCid = 0; category.parentCid = 0;
} }
if(category.parentCid == parentCid){ if (category.parentCid == parentCid){
tree.push(category); tree.push(category);
category.children = Categories.getTree(categories, category.cid); category.children = Categories.getTree(categories, category.cid);
} }

View File

@@ -10,6 +10,8 @@ module.exports = function(Categories) {
Categories.create = function(data, callback) { Categories.create = function(data, callback) {
var category; var category;
var parentCid = data.parentCid ? data.parentCid : 0;
async.waterfall([ async.waterfall([
function(next) { function(next) {
db.incrObjectField('global', 'nextCid', next); db.incrObjectField('global', 'nextCid', next);
@@ -27,7 +29,7 @@ module.exports = function(Categories) {
bgColor: data.bgColor || colours[0], bgColor: data.bgColor || colours[0],
color: data.color || colours[1], color: data.color || colours[1],
slug: slug, slug: slug,
parentCid: ( data.parentCid ? data.parentCid : 0 ), parentCid: parentCid,
topic_count: 0, topic_count: 0,
post_count: 0, post_count: 0,
disabled: 0, disabled: 0,
@@ -48,6 +50,7 @@ module.exports = function(Categories) {
async.series([ async.series([
async.apply(db.setObject, 'category:' + category.cid, category), async.apply(db.setObject, 'category:' + category.cid, category),
async.apply(db.sortedSetAdd, 'categories:cid', category.order, category.cid), async.apply(db.sortedSetAdd, 'categories:cid', category.order, category.cid),
async.apply(db.sortedSetAdd, 'cid:' + parentCid + ':children', category.order, category.cid),
async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'administrators'), async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'administrators'),
async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'registered-users'), async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'registered-users'),
async.apply(privileges.categories.give, ['find', 'read'], category.cid, 'guests') async.apply(privileges.categories.give, ['find', 'read'], category.cid, 'guests')

View File

@@ -30,15 +30,32 @@ module.exports = function(Categories) {
function(next) { function(next) {
db.sortedSetRemove('categories:cid', cid, next); db.sortedSetRemove('categories:cid', cid, next);
}, },
function(next) {
removeFromParent(cid, next);
},
function(next) { function(next) {
db.deleteAll([ db.deleteAll([
'cid:' + cid + ':tids', 'cid:' + cid + ':tids',
'cid:' + cid + ':tids:posts', 'cid:' + cid + ':tids:posts',
'cid:' + cid + ':pids', 'cid:' + cid + ':pids',
'cid:' + cid + ':read_by_uid', 'cid:' + cid + ':read_by_uid',
'cid:' + cid + ':children',
'category:' + cid 'category:' + cid
], next); ], next);
} }
], callback); ], callback);
} }
function removeFromParent(cid, callback) {
async.waterfall([
function(next) {
Categories.getCategoryField(cid, 'parentCid', next);
},
function(parentCid, next) {
parentCid = parseInt(parentCid, 10) || 0;
db.sortedSetRemove('cid:' + parentCid + ':children', cid, next);
}
], callback);
}
}; };

View File

@@ -56,9 +56,10 @@ module.exports = function(Categories) {
} }
}, },
function(posts, next) { function(posts, next) {
categoryData.forEach(function(category) { assignPostsToCategories(categoryData, posts);
assignPostsToCategory(category, posts);
}); bubbleUpChildrenPosts(categoryData);
next(); next();
} }
], callback); ], callback);
@@ -87,13 +88,42 @@ module.exports = function(Categories) {
], callback); ], callback);
} }
function assignPostsToCategory(category, posts) { function bubbleUpChildrenPosts(categoryData) {
category.posts = posts.filter(function(post) { categoryData.forEach(function(category) {
return post.category && (parseInt(post.category.cid, 10) === parseInt(category.cid, 10) || if (category.posts.length) {
parseInt(post.category.parentCid, 10) === parseInt(category.cid, 10)); return;
}).sort(function(a, b) { }
return b.timestamp - a.timestamp; var posts = [];
}).slice(0, parseInt(category.numRecentReplies, 10)); getPostsRecursive(category, posts);
posts.sort(function(a, b) {
return b.timestamp - a.timestamp;
});
if (posts.length) {
category.posts = [posts[0]];
}
});
}
function getPostsRecursive(category, posts) {
category.posts.forEach(function(p) {
posts.push(p);
});
category.children.forEach(function(child) {
getPostsRecursive(child, posts);
});
}
function assignPostsToCategories(categories, posts) {
categories.forEach(function(category) {
category.posts = posts.filter(function(post) {
return post.category && (parseInt(post.category.cid, 10) === parseInt(category.cid, 10) ||
parseInt(post.category.parentCid, 10) === parseInt(category.cid, 10));
}).sort(function(a, b) {
return b.timestamp - a.timestamp;
}).slice(0, parseInt(category.numRecentReplies, 10));
});
} }
function getRecentTopicPids(category, callback) { function getRecentTopicPids(category, callback) {

View File

@@ -50,17 +50,63 @@ module.exports = function(Categories) {
}; };
function updateCategoryField(cid, key, value, callback) { function updateCategoryField(cid, key, value, callback) {
if (key === 'parentCid') {
return updateParent(cid, value, callback);
}
db.setObjectField('category:' + cid, key, value, function(err) { db.setObjectField('category:' + cid, key, value, function(err) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
if (key === 'order') { if (key === 'order') {
db.sortedSetAdd('categories:cid', value, cid, callback); updateOrder(cid, value, callback);
} else { } else {
callback(); callback();
} }
}); });
} }
function updateParent(cid, newParent, callback) {
Categories.getCategoryField(cid, 'parentCid', function(err, oldParent) {
if (err) {
return callback(err);
}
async.series([
function (next) {
oldParent = parseInt(oldParent, 10) || 0;
db.sortedSetRemove('cid:' + oldParent + ':children', cid, next);
},
function (next) {
newParent = parseInt(newParent, 10) || 0;
db.sortedSetAdd('cid:' + newParent + ':children', cid, cid, next);
},
function (next) {
db.setObjectField('category:' + cid, 'parentCid', newParent, next);
}
], function(err, results) {
callback(err);
});
});
}
function updateOrder(cid, order, callback) {
Categories.getCategoryField(cid, 'parentCid', function(err, parentCid) {
if (err) {
return callback(err);
}
async.parallel([
function (next) {
db.sortedSetAdd('categories:cid', order, cid, next);
},
function (next) {
parentCid = parseInt(parentCid, 10) || 0;
db.sortedSetAdd('cid:' + parentCid + ':children', order, cid, next);
}
], callback);
});
}
}; };

View File

@@ -175,6 +175,10 @@ accountsController.getAccount = function(req, res, next) {
return next(err); return next(err);
} }
if (parseInt(meta.config['reputation:disabled'], 10) === 1) {
delete userData.reputation;
}
userData.posts = results.posts.posts.filter(function (p) { userData.posts = results.posts.posts.filter(function (p) {
return p && parseInt(p.deleted, 10) !== 1; return p && parseInt(p.deleted, 10) !== 1;
}); });
@@ -226,6 +230,7 @@ function getFollow(tpl, name, req, res, next) {
userData.users = users; userData.users = users;
userData.nextStart = 50; userData.nextStart = 50;
userData.title = '[[pages:' + tpl + ', ' + userData.username + ']]';
res.render(tpl, userData); res.render(tpl, userData);
}); });
@@ -264,7 +269,7 @@ accountsController.getGroups = function(req, res, next) {
userData.groups = groupsData[0]; userData.groups = groupsData[0];
userData.groups.forEach(groups.escapeGroupData); userData.groups.forEach(groups.escapeGroupData);
userData.title = '[[pages:account/groups, ' + userData.username + ']]';
res.render('account/groups', userData); res.render('account/groups', userData);
}); });
}); });
@@ -317,6 +322,8 @@ function getFromUserSet(tpl, set, method, type, req, res, next) {
var pagination = require('../pagination'); var pagination = require('../pagination');
userData.pagination = pagination.create(page, pageCount); userData.pagination = pagination.create(page, pageCount);
userData.title = '[[pages:' + tpl + ', ' + userData.username + ']]';
res.render(tpl, userData); res.render(tpl, userData);
}); });
}); });
@@ -373,7 +380,7 @@ accountsController.accountEdit = function(req, res, next) {
} }
userData.hasPassword = !!password; userData.hasPassword = !!password;
userData.title = '[[pages:account/edit, ' + userData.username + ']]';
res.render('account/edit', userData); res.render('account/edit', userData);
}); });
}; };
@@ -508,6 +515,10 @@ accountsController.accountSettings = function(req, res, next) {
language.selected = language.code === userData.settings.userLang; language.selected = language.code === userData.settings.userLang;
}); });
userData.disableCustomUserSkins = parseInt(meta.config.disableCustomUserSkins, 10) === 1;
userData.title = '[[pages:account/settings]]';
res.render('account/settings', userData); res.render('account/settings', userData);
}); });
}; };
@@ -557,7 +568,8 @@ accountsController.getNotifications = function(req, res, next) {
return next(err); return next(err);
} }
res.render('notifications', { res.render('notifications', {
notifications: notifications notifications: notifications,
title: '[[pages:notifications]]'
}); });
}); });
}; };
@@ -597,7 +609,8 @@ accountsController.getChats = function(req, res, next) {
chats: results.recentChats.users, chats: results.recentChats.users,
nextStart: results.recentChats.nextStart, nextStart: results.recentChats.nextStart,
contacts: results.contacts, contacts: results.contacts,
allowed: true allowed: true,
title: '[[pages:chats]]'
}); });
} }
@@ -625,7 +638,8 @@ accountsController.getChats = function(req, res, next) {
contacts: results.contacts, contacts: results.contacts,
meta: data.toUser, meta: data.toUser,
messages: data.messages, messages: data.messages,
allowed: data.allowed allowed: data.allowed,
title: '[[pages:chat, ' + data.toUser.username + ']]'
}); });
}); });
}); });

View File

@@ -269,17 +269,39 @@ adminController.postCache.get = function(req, res, next) {
}; };
adminController.plugins.get = function(req, res, next) { adminController.plugins.get = function(req, res, next) {
plugins.getAll(function(err, plugins) { async.parallel({
if (err || !Array.isArray(plugins)) { compatible: function(next) {
plugins = []; plugins.list(function(err, plugins) {
if (err || !Array.isArray(plugins)) {
plugins = [];
}
next(null, plugins);
});
},
all: function(next) {
plugins.list(false, function(err, plugins) {
if (err || !Array.isArray(plugins)) {
plugins = [];
}
next(null, plugins);
});
} }
}, function(err, payload) {
var compatiblePkgNames = payload.compatible.map(function(pkgData) {
return pkgData.name;
});
res.render('admin/extend/plugins' , { res.render('admin/extend/plugins' , {
installed: plugins.filter(function(plugin) { installed: payload.compatible.filter(function(plugin) {
return plugin.installed; return plugin.installed;
}), }),
download: plugins.filter(function(plugin) { download: payload.compatible.filter(function(plugin) {
return !plugin.installed; return !plugin.installed;
}),
incompatible: payload.all.filter(function(plugin) {
return compatiblePkgNames.indexOf(plugin.name) === -1;
}) })
}); });
}); });

View File

@@ -27,6 +27,7 @@ apiController.getConfig = function(req, res, next) {
config.websocketAddress = nconf.get('socket.io:address') || ''; config.websocketAddress = nconf.get('socket.io:address') || '';
config.version = nconf.get('version'); config.version = nconf.get('version');
config.siteTitle = validator.escape(meta.config.title || meta.config.browserTitle || 'NodeBB'); config.siteTitle = validator.escape(meta.config.title || meta.config.browserTitle || 'NodeBB');
config.browserTitle = validator.escape(meta.config.browserTitle || meta.config.title || 'NodeBB');
config.showSiteTitle = parseInt(meta.config.showSiteTitle, 10) === 1; config.showSiteTitle = parseInt(meta.config.showSiteTitle, 10) === 1;
config.postDelay = meta.config.postDelay; config.postDelay = meta.config.postDelay;
config.minimumTitleLength = meta.config.minimumTitleLength; config.minimumTitleLength = meta.config.minimumTitleLength;

View File

@@ -27,13 +27,13 @@ categoriesController.list = function(req, res, next) {
content: validator.escape(meta.config.description || '') content: validator.escape(meta.config.description || '')
}, { }, {
property: 'og:title', property: 'og:title',
content: 'Index | ' + validator.escape(meta.config.title || 'NodeBB') content: '[[pages:categories]]'
}, { }, {
property: 'og:type', property: 'og:type',
content: 'website' content: 'website'
}]; }];
if(meta.config['brand:logo']) { if (meta.config['brand:logo']) {
res.locals.metaTags.push({ res.locals.metaTags.push({
property: 'og:image', property: 'og:image',
content: meta.config['brand:logo'] content: meta.config['brand:logo']
@@ -46,22 +46,13 @@ categoriesController.list = function(req, res, next) {
var categoryData; var categoryData;
async.waterfall([ async.waterfall([
function(next) { function(next) {
categories.getCategoriesByPrivilege(req.uid, 'find', next); categories.getCategoriesByPrivilege('cid:0:children', req.uid, 'find', next);
}, },
function(_categoryData, next) { function(_categoryData, next) {
categoryData = _categoryData; categoryData = _categoryData;
var allCategories = []; var allCategories = [];
categories.flattenCategories(allCategories, categoryData);
categoryData = categoryData.filter(function(category) {
if (!category.parent) {
allCategories.push(category);
}
if (Array.isArray(category.children) && category.children.length) {
allCategories.push.apply(allCategories, category.children);
}
return category && !category.parent;
});
categories.getRecentTopicReplies(allCategories, req.uid, next); categories.getRecentTopicReplies(allCategories, req.uid, next);
} }
@@ -74,6 +65,8 @@ categoriesController.list = function(req, res, next) {
return next(err); return next(err);
} }
data.title = '[[pages:categories]]';
plugins.fireHook('filter:categories.build', {req: req, res: res, templateData: data}, function(err, data) { plugins.fireHook('filter:categories.build', {req: req, res: res, templateData: data}, function(err, data) {
if (err) { if (err) {
return next(err); return next(err);
@@ -200,7 +193,9 @@ categoriesController.get = function(req, res, next) {
}); });
}, },
function(categoryData, next) { function(categoryData, next) {
categories.getRecentTopicReplies(categoryData.children, req.uid, function(err) { var allCategories = [];
categories.flattenCategories(allCategories, [categoryData]);
categories.getRecentTopicReplies(allCategories, req.uid, function(err) {
next(err, categoryData); next(err, categoryData);
}); });
}, },
@@ -257,7 +252,7 @@ categoriesController.get = function(req, res, next) {
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data.rssFeedUrl = nconf.get('relative_path') + '/category/' + data.cid + '.rss'; data.rssFeedUrl = nconf.get('relative_path') + '/category/' + data.cid + '.rss';
data.pagination = pagination.create(data.currentPage, data.pageCount); data.pagination = pagination.create(data.currentPage, data.pageCount);
data.title = data.name;
data.pagination.rel.forEach(function(rel) { data.pagination.rel.forEach(function(rel) {
res.locals.linkTags.push(rel); res.locals.linkTags.push(rel);
}); });

View File

@@ -16,6 +16,7 @@ groupsController.list = function(req, res, next) {
if (err) { if (err) {
return next(err); return next(err);
} }
data.title = '[[pages:groups]]';
res.render('groups/list', data); res.render('groups/list', data);
}); });
}; };
@@ -97,6 +98,7 @@ groupsController.details = function(req, res, next) {
return helpers.notFound(req, res); return helpers.notFound(req, res);
} }
results.title = '[[pages:group, ' + results.group.displayName + ']]';
res.render('groups/details', results); res.render('groups/details', results);
}); });
}); });

View File

@@ -19,18 +19,34 @@ helpers.notFound = function(req, res, error) {
error: error error: error
}); });
} else if (res.locals.isAPI) { } else if (res.locals.isAPI) {
res.status(404).json({path: req.path.replace(/^\/api/, ''), error: error}); res.status(404).json({
path: req.path.replace(/^\/api/, ''),
error: error,
title: '[[global:404.title]]'
});
} else { } else {
res.status(404).render('404', {path: req.path, error: error}); res.status(404).render('404', {
path: req.path,
error: error,
title: '[[global:404.title]]'
});
} }
}; };
helpers.notAllowed = function(req, res, error) { helpers.notAllowed = function(req, res, error) {
if (req.uid) { if (req.uid) {
if (res.locals.isAPI) { if (res.locals.isAPI) {
res.status(403).json({path: req.path.replace(/^\/api/, ''), loggedIn: !!req.uid, error: error}); res.status(403).json({
path: req.path.replace(/^\/api/, ''),
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
} else { } else {
res.status(403).render('403', {path: req.path, loggedIn: !!req.uid, error: error}); res.status(403).render('403', {
path: req.path,
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
} }
} else { } else {
if (res.locals.isAPI) { if (res.locals.isAPI) {

View File

@@ -42,9 +42,9 @@ Controllers.home = function(req, res, next) {
if (route === 'categories') { if (route === 'categories') {
Controllers.categories.list(req, res, next); Controllers.categories.list(req, res, next);
} else if (route === 'recent') { } else if (route === 'recent') {
Controllers.categories.recent(req, res, next); Controllers.recent.get(req, res, next);
} else if (route === 'popular') { } else if (route === 'popular') {
Controllers.categories.popular(req, res, next); Controllers.popular.get(req, res, next);
} else { } else {
next(); next();
} }
@@ -61,7 +61,8 @@ Controllers.reset = function(req, res, next) {
valid: valid, valid: valid,
displayExpiryNotice: req.session.passwordExpired, displayExpiryNotice: req.session.passwordExpired,
code: req.params.code ? req.params.code : null, code: req.params.code ? req.params.code : null,
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[reset_password:reset_password]]', url: '/reset'}, {text: '[[reset_password:update_password]]'}]) breadcrumbs: helpers.buildBreadcrumbs([{text: '[[reset_password:reset_password]]', url: '/reset'}, {text: '[[reset_password:update_password]]'}]),
title: '[[pages:reset]]'
}); });
delete req.session.passwordExpired; delete req.session.passwordExpired;
@@ -69,7 +70,8 @@ Controllers.reset = function(req, res, next) {
} else { } else {
res.render('reset', { res.render('reset', {
code: req.params.code ? req.params.code : null, code: req.params.code ? req.params.code : null,
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[reset_password:reset_password]]'}]) breadcrumbs: helpers.buildBreadcrumbs([{text: '[[reset_password:reset_password]]'}]),
title: '[[pages:reset]]'
}); });
} }
@@ -90,6 +92,7 @@ Controllers.login = function(req, res, next) {
data.allowLoginWith = '[[login:' + (meta.config.allowLoginWith || 'username-email') + ']]'; data.allowLoginWith = '[[login:' + (meta.config.allowLoginWith || 'username-email') + ']]';
data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:login]]'}]); data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:login]]'}]);
data.error = req.flash('error')[0]; data.error = req.flash('error')[0];
data.title = '[[pages:login]]';
res.render('login', data); res.render('login', data);
}; };
@@ -128,6 +131,7 @@ Controllers.register = function(req, res, next) {
data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[register:register]]'}]); data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[register:register]]'}]);
data.regFormEntry = []; data.regFormEntry = [];
data.error = req.flash('error')[0]; data.error = req.flash('error')[0];
data.title = '[[pages:register]]';
plugins.fireHook('filter:register.build', {req: req, res: res, templateData: data}, next); plugins.fireHook('filter:register.build', {req: req, res: res, templateData: data}, next);
} }

View File

@@ -36,7 +36,8 @@ popularController.get = function(req, res, next) {
topics: topics, topics: topics,
'feeds:disableRSS': parseInt(meta.config['feeds:disableRSS'], 10) === 1, 'feeds:disableRSS': parseInt(meta.config['feeds:disableRSS'], 10) === 1,
rssFeedUrl: nconf.get('relative_path') + '/popular/' + (req.params.term || 'daily') + '.rss', rssFeedUrl: nconf.get('relative_path') + '/popular/' + (req.params.term || 'daily') + '.rss',
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[global:header.popular]]'}]) breadcrumbs: helpers.buildBreadcrumbs([{text: '[[global:header.popular]]'}]),
title: '[[pages:popular-' + term + ']]'
}; };
if (!req.uid) { if (!req.uid) {

View File

@@ -21,6 +21,7 @@ recentController.get = function(req, res, next) {
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data.rssFeedUrl = nconf.get('relative_path') + '/recent.rss'; data.rssFeedUrl = nconf.get('relative_path') + '/recent.rss';
data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[recent:title]]'}]); data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[recent:title]]'}]);
data.title = '[[pages:recent]]';
plugins.fireHook('filter:recent.build', {req: req, res: res, templateData: data}, function(err, data) { plugins.fireHook('filter:recent.build', {req: req, res: res, templateData: data}, function(err, data) {
if (err) { if (err) {

View File

@@ -17,7 +17,7 @@ searchController.search = function(req, res, next) {
var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]); var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]);
categories.getCategoriesByPrivilege(req.uid, 'read', function(err, categories) { categories.getCategoriesByPrivilege('categories:cid', req.uid, 'read', function(err, categories) {
if (err) { if (err) {
return next(err); return next(err);
} }

View File

@@ -62,7 +62,8 @@ tagsController.getTag = function(req, res, next) {
topics: results.topics, topics: results.topics,
tag: tag, tag: tag,
nextStart: stop + 1, nextStart: stop + 1,
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[tags:tags]]', url: '/tags'}, {text: tag}]) breadcrumbs: helpers.buildBreadcrumbs([{text: '[[tags:tags]]', url: '/tags'}, {text: tag}]),
title: '[[pages:tag, ' + tag + ']]'
}; };
res.render('tag', data); res.render('tag', data);
}); });
@@ -76,7 +77,8 @@ tagsController.getTags = function(req, res, next) {
var data = { var data = {
tags: tags, tags: tags,
nextStart: 100, nextStart: 100,
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[tags:tags]]'}]) breadcrumbs: helpers.buildBreadcrumbs([{text: '[[tags:tags]]'}]),
title: '[[pages:tags]]'
}; };
res.render('tags', data); res.render('tags', data);
}); });

View File

@@ -55,6 +55,8 @@ unreadController.get = function(req, res, next) {
} }
data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[unread:title]]'}]); data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[unread:title]]'}]);
data.title = '[[pages:unread]]';
res.render('unread', data); res.render('unread', data);
}); });
}; };

View File

@@ -14,6 +14,10 @@ var async = require('async'),
db = require('../database'), db = require('../database'),
helpers = require('./helpers'); helpers = require('./helpers');
usersController.redirectToOnlineUsers = function(req, res, next) {
helpers.redirect(res, '/users/online');
};
usersController.getOnlineUsers = function(req, res, next) { usersController.getOnlineUsers = function(req, res, next) {
var websockets = require('../socket.io'); var websockets = require('../socket.io');
@@ -44,7 +48,9 @@ usersController.getOnlineUsers = function(req, res, next) {
search_display: 'hidden', search_display: 'hidden',
loadmore_display: results.count > 50 ? 'block' : 'hide', loadmore_display: results.count > 50 ? 'block' : 'hide',
users: results.users, users: results.users,
anonymousUserCount: websockets.getOnlineAnonCount() anonymousUserCount: websockets.getOnlineAnonCount(),
defaultGravatar: user.createGravatarURLFromEmail(''),
title: '[[pages:users/online]]'
}; };
render(req, res, userData, next); render(req, res, userData, next);
@@ -64,6 +70,11 @@ usersController.getUsersSortedByJoinDate = function(req, res, next) {
}; };
usersController.getUsers = function(set, start, stop, req, res, next) { usersController.getUsers = function(set, start, stop, req, res, next) {
var setToTitles = {
'users:postcount': '[[pages:users/sort-posts]]',
'users:reputation': '[[pages:users/sort-reputation]]',
'users:joindate': '[[pages:users/latest]]'
};
usersController.getUsersAndCount(set, req.uid, start, stop, function(err, data) { usersController.getUsersAndCount(set, req.uid, start, stop, function(err, data) {
if (err) { if (err) {
return next(err); return next(err);
@@ -73,7 +84,8 @@ usersController.getUsers = function(set, start, stop, req, res, next) {
search_display: 'hidden', search_display: 'hidden',
loadmore_display: data.count > (stop - start + 1) ? 'block' : 'hide', loadmore_display: data.count > (stop - start + 1) ? 'block' : 'hide',
users: data.users, users: data.users,
pagination: pagination.create(1, pageCount) pagination: pagination.create(1, pageCount),
title: setToTitles[set] || '[[pages:users/latest]]'
}; };
userData['route_' + set] = true; userData['route_' + set] = true;
render(req, res, userData, next); render(req, res, userData, next);
@@ -114,7 +126,8 @@ usersController.getUsersForSearch = function(req, res, next) {
var userData = { var userData = {
search_display: 'block', search_display: 'block',
loadmore_display: 'hidden', loadmore_display: 'hidden',
users: data.users users: data.users,
title: '[[pages:users/search]]'
}; };
render(req, res, userData, next); render(req, res, userData, next);
@@ -157,6 +170,7 @@ usersController.getMap = function(req, res, next) {
} }
data.room = validator.escape(categoryData.name); data.room = validator.escape(categoryData.name);
data.link = '/category/' + categoryData.slug; data.link = '/category/' + categoryData.slug;
data.core = false;
next(null, data); next(null, data);
}); });
} else if (roomName.startsWith('topic_')) { } else if (roomName.startsWith('topic_')) {
@@ -167,15 +181,20 @@ usersController.getMap = function(req, res, next) {
} }
data.room = validator.escape(topicData.title); data.room = validator.escape(topicData.title);
data.link = '/topic/' + topicData.slug; data.link = '/topic/' + topicData.slug;
data.core = false;
next(null, data); next(null, data);
}); });
} else { } else {
data.core = true;
next(null, data); next(null, data);
} }
}); });
}, function(err, data) { }, function(err, data) {
if (err) {
return next(err);
}
data.sort(function(a, b) { data.sort(function(a, b) {
return b.total - a.total; return b.users.length - a.users.length;
}); });
data.forEach(function(room) { data.forEach(function(room) {
@@ -184,7 +203,7 @@ usersController.getMap = function(req, res, next) {
} }
}); });
res.render('usersMap', {rooms: data}); res.render('usersMap', {rooms: data, title: '[[pages:users/map]]'});
}); });
}; };

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