mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-17 22:10:23 +01:00
Compare commits
582 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9b9f090e4 | ||
|
|
b82a6fa888 | ||
|
|
8ab539b518 | ||
|
|
9078c2a536 | ||
|
|
fd20e4a400 | ||
|
|
1a64e40b21 | ||
|
|
cbfba4b45b | ||
|
|
f21a98f37f | ||
|
|
0edd6985ec | ||
|
|
98a646fa62 | ||
|
|
1d69436b44 | ||
|
|
d6c7551120 | ||
|
|
fb53e89023 | ||
|
|
d28beaa4dc | ||
|
|
ac06567617 | ||
|
|
d0a2c077ff | ||
|
|
ebf07626de | ||
|
|
9ef8bb4cdc | ||
|
|
bc8a53aadd | ||
|
|
03c4a1bc73 | ||
|
|
d93163896f | ||
|
|
08bdbc0bcc | ||
|
|
35d6a99775 | ||
|
|
e45e86fcc1 | ||
|
|
9589d340b9 | ||
|
|
91afbf106e | ||
|
|
aff11359ae | ||
|
|
aff8cef5f3 | ||
|
|
879855744d | ||
|
|
b5ab0c9097 | ||
|
|
2c398f81d2 | ||
|
|
520fcadd3f | ||
|
|
e8eb9f91b9 | ||
|
|
8bfb338eee | ||
|
|
bbb655abdd | ||
|
|
095e5527e3 | ||
|
|
4eb8c34855 | ||
|
|
e3185b9560 | ||
|
|
449adfae59 | ||
|
|
714e61b137 | ||
|
|
d0e4689907 | ||
|
|
1996e64c9b | ||
|
|
e2fb617cc0 | ||
|
|
fd88aff195 | ||
|
|
f7a1cca861 | ||
|
|
e3fb996a80 | ||
|
|
fe53037e53 | ||
|
|
438f90d859 | ||
|
|
742c8fb43c | ||
|
|
d43f3cebc6 | ||
|
|
9d452241ad | ||
|
|
c19a51e1b6 | ||
|
|
1b41a8f467 | ||
|
|
f933fc0167 | ||
|
|
8cfb239aac | ||
|
|
a974c6fa99 | ||
|
|
998f780fd2 | ||
|
|
b022d46d47 | ||
|
|
f7793e54b1 | ||
|
|
1e61033667 | ||
|
|
53caa5e422 | ||
|
|
40d20846d8 | ||
|
|
204913c63d | ||
|
|
6c30437c47 | ||
|
|
dd7fe47dfd | ||
|
|
50323c3d23 | ||
|
|
69e0aa338d | ||
|
|
6dcd06b63c | ||
|
|
42d77080f3 | ||
|
|
fbb4998999 | ||
|
|
14744a854f | ||
|
|
2c6afb4244 | ||
|
|
24907e456d | ||
|
|
2039885d96 | ||
|
|
daacdb50f3 | ||
|
|
21155b1b80 | ||
|
|
5d69167a64 | ||
|
|
5db27a835f | ||
|
|
c8e423e9cf | ||
|
|
be3465c5ca | ||
|
|
637e037e27 | ||
|
|
3e6bcd83cc | ||
|
|
dc4aeca427 | ||
|
|
9eb09f14cb | ||
|
|
a55fc364a0 | ||
|
|
2f90949560 | ||
|
|
a940219321 | ||
|
|
aaf6b11dc9 | ||
|
|
0f0913bfe5 | ||
|
|
5569337c40 | ||
|
|
ba2f47ead6 | ||
|
|
b52782deb8 | ||
|
|
2c6bf93eb5 | ||
|
|
4a11307b24 | ||
|
|
d8183c056c | ||
|
|
6ad28dadd4 | ||
|
|
2c489c600c | ||
|
|
abc782f5e6 | ||
|
|
a18e366493 | ||
|
|
12e95df068 | ||
|
|
a078f73e84 | ||
|
|
8f879cd3eb | ||
|
|
8385ceef79 | ||
|
|
83cc8f3ba8 | ||
|
|
cab6ab8e17 | ||
|
|
e9fbed71ae | ||
|
|
b4121f262d | ||
|
|
256a2fa9c6 | ||
|
|
0f362b7fac | ||
|
|
b504e2cd11 | ||
|
|
ea84fd70af | ||
|
|
09efb83ef3 | ||
|
|
b2aeb14094 | ||
|
|
0ed8fd6cbd | ||
|
|
2f1a3b9789 | ||
|
|
d068139d81 | ||
|
|
764e937c43 | ||
|
|
f72cf35348 | ||
|
|
fe1a75d1fd | ||
|
|
3dc9e2f4fa | ||
|
|
3bd8cf69a1 | ||
|
|
2c8725558e | ||
|
|
f68f02d346 | ||
|
|
8fd78199e2 | ||
|
|
1bde86a33f | ||
|
|
b6d4ae2732 | ||
|
|
680dbf138a | ||
|
|
3752a1c691 | ||
|
|
3a00c177d3 | ||
|
|
845e5e7986 | ||
|
|
57d2db36e6 | ||
|
|
8bfea656c4 | ||
|
|
ea2c03e28b | ||
|
|
f29b375ed4 | ||
|
|
07f1e0bcb5 | ||
|
|
0b94297c64 | ||
|
|
8655c2d2a6 | ||
|
|
da9c673ec4 | ||
|
|
1e6863ee19 | ||
|
|
00eb6b4efc | ||
|
|
002826d84f | ||
|
|
289e081e2e | ||
|
|
a717e9626e | ||
|
|
83f20c1cdb | ||
|
|
bc8adff70a | ||
|
|
c4623e2447 | ||
|
|
99fba3b83a | ||
|
|
2580caf864 | ||
|
|
f2d631e42d | ||
|
|
d86aefb518 | ||
|
|
3782ae1647 | ||
|
|
36e1a121ed | ||
|
|
2e52dd59ee | ||
|
|
d7a444d9ab | ||
|
|
f9e2b50826 | ||
|
|
32a32fcf5c | ||
|
|
9435acfa71 | ||
|
|
35ad3be969 | ||
|
|
9cb20c3886 | ||
|
|
a2c9867902 | ||
|
|
58a3f33200 | ||
|
|
25bac03bab | ||
|
|
770cea9329 | ||
|
|
30c11a8b42 | ||
|
|
27a01f6c61 | ||
|
|
bf27ade251 | ||
|
|
9d88b9eed3 | ||
|
|
04ea573caa | ||
|
|
d9eefd667c | ||
|
|
3ad98f3783 | ||
|
|
b89cf6f480 | ||
|
|
4397da144f | ||
|
|
cf8f0ca225 | ||
|
|
885242018f | ||
|
|
1abfe5de63 | ||
|
|
04dd1f9dac | ||
|
|
114294e24a | ||
|
|
dfa4cd4ae3 | ||
|
|
65d5a6cb81 | ||
|
|
64e87b761f | ||
|
|
1021615848 | ||
|
|
69c1ec97c9 | ||
|
|
45e7d64aeb | ||
|
|
b86a01ded1 | ||
|
|
e67af67180 | ||
|
|
9d03147f4e | ||
|
|
c313c4501b | ||
|
|
538356846d | ||
|
|
55d008d71f | ||
|
|
401a30e02c | ||
|
|
9816272b7b | ||
|
|
d72d2decd5 | ||
|
|
43c05d1d85 | ||
|
|
14f35a8c6b | ||
|
|
ffe1549cad | ||
|
|
3ca58a438d | ||
|
|
5da4cead67 | ||
|
|
0000a7f0b9 | ||
|
|
27ac24b1e3 | ||
|
|
95495926fc | ||
|
|
0f254c0b6c | ||
|
|
b27478876e | ||
|
|
a3734f2e15 | ||
|
|
1b843fba9c | ||
|
|
35f17db141 | ||
|
|
bcb364c4d4 | ||
|
|
6e16cb4b30 | ||
|
|
40e71299a1 | ||
|
|
0148cf06d0 | ||
|
|
ffa31ca0e7 | ||
|
|
ba3b8a21ae | ||
|
|
05209b01b9 | ||
|
|
4e0d0c2c20 | ||
|
|
225284073f | ||
|
|
ccef51095a | ||
|
|
cd77a1a457 | ||
|
|
6aeca98cd4 | ||
|
|
07a3b3f00b | ||
|
|
77e0cdcc3e | ||
|
|
e316dd3330 | ||
|
|
b511653e74 | ||
|
|
b5e37a6ce8 | ||
|
|
a34ed92fac | ||
|
|
4ff8509a0e | ||
|
|
e76936abfc | ||
|
|
9471fd8e46 | ||
|
|
2d4ceb8f9f | ||
|
|
4c40ee8e6e | ||
|
|
ddcf46fc73 | ||
|
|
7db234f958 | ||
|
|
f6f7959d28 | ||
|
|
7fa2f474fe | ||
|
|
d5e8044575 | ||
|
|
c0721e105f | ||
|
|
a475e38078 | ||
|
|
932b960aa9 | ||
|
|
24b12e23ea | ||
|
|
2a5d6e04fc | ||
|
|
4459d9d4e0 | ||
|
|
2be3158aff | ||
|
|
f1ad469861 | ||
|
|
0c05ee82b1 | ||
|
|
4f97275d24 | ||
|
|
4b9bfca767 | ||
|
|
202a4c4105 | ||
|
|
090bc2ad10 | ||
|
|
000c7efb1a | ||
|
|
90ad08a00d | ||
|
|
90e1e2436c | ||
|
|
21f5dad1d2 | ||
|
|
bc8bb352a8 | ||
|
|
274310e35a | ||
|
|
0bcc1642c7 | ||
|
|
d1d6605dcf | ||
|
|
da94d6214b | ||
|
|
67e49db797 | ||
|
|
de9100c489 | ||
|
|
4348e1efa4 | ||
|
|
6de3dba239 | ||
|
|
021cf9b8f6 | ||
|
|
ca087e6fa7 | ||
|
|
6c9e28232f | ||
|
|
ceac8e2dc9 | ||
|
|
98cf6eec71 | ||
|
|
5a00767370 | ||
|
|
4c90d22e43 | ||
|
|
e0e153eafb | ||
|
|
5c3c2623f2 | ||
|
|
34fc326a37 | ||
|
|
36745608bf | ||
|
|
090d35f306 | ||
|
|
347f5c132e | ||
|
|
d6f8162f17 | ||
|
|
b0b0f3640c | ||
|
|
4fd08332cc | ||
|
|
aaaffb823f | ||
|
|
76636b64db | ||
|
|
be6ed43223 | ||
|
|
9f2196abfb | ||
|
|
90a75ee045 | ||
|
|
2a21b4855e | ||
|
|
8f769d53a3 | ||
|
|
9ee250b597 | ||
|
|
074d7e7c8d | ||
|
|
870d48dc81 | ||
|
|
9ca10c25d4 | ||
|
|
8e2cc1c883 | ||
|
|
af09f4aca8 | ||
|
|
ab63ca6d92 | ||
|
|
400845ce6c | ||
|
|
351b07bb34 | ||
|
|
f861d44d55 | ||
|
|
2b7e4cbdf4 | ||
|
|
df10bde2db | ||
|
|
0da141e7bc | ||
|
|
6313a5eeb1 | ||
|
|
26de85c1de | ||
|
|
a54f464a13 | ||
|
|
bfbc596348 | ||
|
|
7508bd216e | ||
|
|
8cfc5dda37 | ||
|
|
b81737bc0f | ||
|
|
1c23be8911 | ||
|
|
5f86e31d1e | ||
|
|
746119bd45 | ||
|
|
385aa6df92 | ||
|
|
097810a057 | ||
|
|
3a7fcc2d3d | ||
|
|
95bb838699 | ||
|
|
81055523a0 | ||
|
|
e9fbab0f26 | ||
|
|
53ca7a1143 | ||
|
|
6c70d37f1c | ||
|
|
447073560f | ||
|
|
2c131f172a | ||
|
|
1564e3d530 | ||
|
|
3d9a732c4a | ||
|
|
4819bea378 | ||
|
|
030ce95dea | ||
|
|
2a1671ba9b | ||
|
|
a65c79cb02 | ||
|
|
dcbe4ffd4a | ||
|
|
215b919362 | ||
|
|
58df656c65 | ||
|
|
a8c91e2452 | ||
|
|
806a454b05 | ||
|
|
705754e823 | ||
|
|
fe527ff2a9 | ||
|
|
041e77f688 | ||
|
|
b927f6ce29 | ||
|
|
519d376071 | ||
|
|
d9ee9bf5e3 | ||
|
|
67d5ea83e7 | ||
|
|
7875138c08 | ||
|
|
43b012b32e | ||
|
|
c096656eff | ||
|
|
2dd295118c | ||
|
|
567997ef3c | ||
|
|
c698af17ae | ||
|
|
39b70a9e09 | ||
|
|
9b557cafd8 | ||
|
|
fe4aee177d | ||
|
|
7c4347736c | ||
|
|
16e07d475f | ||
|
|
2125bb2223 | ||
|
|
72a3ab1d6c | ||
|
|
639247a8b0 | ||
|
|
f0caac242c | ||
|
|
e066fbf36a | ||
|
|
b215dbde19 | ||
|
|
1325e4c501 | ||
|
|
2e2938616d | ||
|
|
53a7eab3e8 | ||
|
|
6bd4a34e69 | ||
|
|
d27f2eb214 | ||
|
|
b547d3577b | ||
|
|
4b5988c269 | ||
|
|
cfd3a7d126 | ||
|
|
0471a192ab | ||
|
|
5c6a7d4b94 | ||
|
|
ca01fb9f7d | ||
|
|
b176629b44 | ||
|
|
113cb85c46 | ||
|
|
5b6f5ebf9d | ||
|
|
21bbe68c97 | ||
|
|
28c75e09a9 | ||
|
|
69f453c73c | ||
|
|
dab0435d9b | ||
|
|
b5770be71f | ||
|
|
bf3822e8a5 | ||
|
|
cb6c42ea44 | ||
|
|
3dc3769088 | ||
|
|
3d18c4015a | ||
|
|
610d45bb32 | ||
|
|
66bc4184d8 | ||
|
|
b024d10185 | ||
|
|
e847c015a5 | ||
|
|
10474f8e2a | ||
|
|
8a99eef4fb | ||
|
|
da66efe7a5 | ||
|
|
1bd94b4e41 | ||
|
|
e862a1c4cc | ||
|
|
8b55920acf | ||
|
|
32df811765 | ||
|
|
91d6f83de4 | ||
|
|
7c8f857aaf | ||
|
|
1f970c3bdb | ||
|
|
700cab686b | ||
|
|
af06e0335a | ||
|
|
4a8dc82bd2 | ||
|
|
8a4e2b1ea0 | ||
|
|
1f52717f1e | ||
|
|
304285e874 | ||
|
|
d4eddc6e2c | ||
|
|
6d79521922 | ||
|
|
95db5f93cb | ||
|
|
b900bc9cce | ||
|
|
fc066c21bf | ||
|
|
32d5118266 | ||
|
|
3775c8e50a | ||
|
|
99fbc0dfd5 | ||
|
|
e32d230974 | ||
|
|
c9308efbec | ||
|
|
636551d2e9 | ||
|
|
347d6c2768 | ||
|
|
4f654fb489 | ||
|
|
80e7fd93c6 | ||
|
|
95efb2ae5e | ||
|
|
8d3a647d16 | ||
|
|
53afe6cb68 | ||
|
|
391b8098a3 | ||
|
|
190948336a | ||
|
|
fcda27e251 | ||
|
|
a48a07603c | ||
|
|
d930e2a1be | ||
|
|
7e2166903f | ||
|
|
d5c0ca4a9d | ||
|
|
7695e76494 | ||
|
|
78af47362c | ||
|
|
18a890ed51 | ||
|
|
5f731dd1f6 | ||
|
|
51990142d5 | ||
|
|
b840169a8c | ||
|
|
94fdeb2378 | ||
|
|
68e7ee7f07 | ||
|
|
77d5ecc82a | ||
|
|
437379413e | ||
|
|
ddb7896df1 | ||
|
|
66cdb9a067 | ||
|
|
f5741fd48b | ||
|
|
f405dec4e9 | ||
|
|
cc242ca667 | ||
|
|
2733198f9e | ||
|
|
52700fbe16 | ||
|
|
0f53749e70 | ||
|
|
1aa1ddb4ec | ||
|
|
71125fd1e2 | ||
|
|
5621fb8622 | ||
|
|
b9f1176ec1 | ||
|
|
b3b4d3c37d | ||
|
|
cdbca7d262 | ||
|
|
140f90f7f3 | ||
|
|
a905c6a084 | ||
|
|
bfe081f672 | ||
|
|
46a14715e3 | ||
|
|
c1da56ce45 | ||
|
|
ee63fae803 | ||
|
|
720711756f | ||
|
|
90a12c3253 | ||
|
|
6a00ab3782 | ||
|
|
9ccfa3f18c | ||
|
|
1660d75205 | ||
|
|
f6d57a241d | ||
|
|
bcfb4ca0e4 | ||
|
|
0159a43a20 | ||
|
|
86b019ec89 | ||
|
|
98a12cd1e1 | ||
|
|
e6452cbd4d | ||
|
|
cd44ead595 | ||
|
|
652fda1a6f | ||
|
|
30a7f1a816 | ||
|
|
6ca3d0c4af | ||
|
|
b2074c6dda | ||
|
|
d7c0e1c62e | ||
|
|
56ef05a0bf | ||
|
|
dd36cce329 | ||
|
|
2b2799dae9 | ||
|
|
293c176053 | ||
|
|
3cef5fce2b | ||
|
|
7d0f160c4c | ||
|
|
c5f9f896b2 | ||
|
|
db98b3db55 | ||
|
|
dba47e4bef | ||
|
|
2a46ead29f | ||
|
|
707179edf3 | ||
|
|
53164e96ab | ||
|
|
9702e28a07 | ||
|
|
fa56eca962 | ||
|
|
684839f04a | ||
|
|
0188ea9a3b | ||
|
|
85aa587749 | ||
|
|
48e36e3c31 | ||
|
|
0b6d018f8d | ||
|
|
f2bf65252d | ||
|
|
4335f8c5c6 | ||
|
|
ae82f57c67 | ||
|
|
168052bf45 | ||
|
|
a87ebb64d8 | ||
|
|
38da65ee58 | ||
|
|
e3e1a556cd | ||
|
|
56b618c915 | ||
|
|
7198110b57 | ||
|
|
b7aea63c53 | ||
|
|
78b65c0b12 | ||
|
|
0742590c0c | ||
|
|
c16f04bbcf | ||
|
|
51b38c4c55 | ||
|
|
79eddc9b06 | ||
|
|
21f63ac17f | ||
|
|
fdf5227c35 | ||
|
|
98f03a723e | ||
|
|
69427fa10e | ||
|
|
670986f7ef | ||
|
|
8b62041d28 | ||
|
|
89c5d01efa | ||
|
|
0a06f1ac7d | ||
|
|
df2e9b4b47 | ||
|
|
aed4e2792d | ||
|
|
c860df7975 | ||
|
|
2148f6ff95 | ||
|
|
2d05a06e37 | ||
|
|
e3da005780 | ||
|
|
f0e8633dcc | ||
|
|
590208f0c7 | ||
|
|
7d7ead3f47 | ||
|
|
974629ce85 | ||
|
|
72ef8c839f | ||
|
|
5ee5c8179a | ||
|
|
46d6d7637e | ||
|
|
62e2aa67d7 | ||
|
|
182659d0e1 | ||
|
|
4855131652 | ||
|
|
4d2469b4ce | ||
|
|
4e2326fc84 | ||
|
|
3a8dca6fb9 | ||
|
|
31635b92f3 | ||
|
|
a0c3de0273 | ||
|
|
32b191fa62 | ||
|
|
f616125d02 | ||
|
|
e1f6e064a9 | ||
|
|
633be7ff3c | ||
|
|
6b3863bfbf | ||
|
|
b66ca703b8 | ||
|
|
48a7f9058f | ||
|
|
8f80733563 | ||
|
|
aa1451cfbc | ||
|
|
13ef28118d | ||
|
|
34459e7cf1 | ||
|
|
798e17a954 | ||
|
|
5ad80218a2 | ||
|
|
e90e54cec1 | ||
|
|
bca1fde69c | ||
|
|
d70c688b65 | ||
|
|
541993c80a | ||
|
|
529c8acf6c | ||
|
|
e98d05b1a5 | ||
|
|
0afc7c9761 | ||
|
|
e5c1edd5f5 | ||
|
|
a5e78aab08 | ||
|
|
cec69c2be0 | ||
|
|
bc8815cb94 | ||
|
|
efac6272bb | ||
|
|
bdb30976b5 | ||
|
|
1d4ae8fe4d | ||
|
|
abdb4c34ef | ||
|
|
08d130893c | ||
|
|
b2fb9aa99f | ||
|
|
561ee9e4f1 | ||
|
|
3f70d45f3d | ||
|
|
c07783fa2c | ||
|
|
d4d0e8cd9b | ||
|
|
4be5ac2c23 | ||
|
|
070c95d8de | ||
|
|
8d12ecb758 | ||
|
|
81560c4698 | ||
|
|
390937a20b | ||
|
|
2a8a38b742 | ||
|
|
5a5c3c8c60 | ||
|
|
905e451455 | ||
|
|
69b8b47b15 | ||
|
|
b16e1a0113 | ||
|
|
0b39968a9c | ||
|
|
d8b3abb611 | ||
|
|
7fb0a616a1 | ||
|
|
d987e51a8b | ||
|
|
0f7f6cd0a3 | ||
|
|
0e8b33aa79 | ||
|
|
353b3047cd | ||
|
|
377de06eeb | ||
|
|
4013e27a8b | ||
|
|
181c6eb2e6 | ||
|
|
18009ebb39 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -8,6 +8,7 @@ public/css/*.css
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
.project
|
||||
.idea
|
||||
*.swp
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
@@ -15,3 +16,7 @@ provision.sh
|
||||
*.komodoproject
|
||||
|
||||
feeds/recent.rss
|
||||
|
||||
# winston?
|
||||
error.log
|
||||
events.log
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter")
|
||||
* [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## How can I follow along/contribute?
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
NodeBB requires the following software to be installed:
|
||||
|
||||
* A version of Node.js at least 0.8 or greater
|
||||
* Redis, version 2.6 or greater.
|
||||
* Redis, version 2.6 or greater or MongoDB, version 2.4 or greater
|
||||
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
||||
|
||||
## Installation
|
||||
@@ -32,6 +32,8 @@ First, we install our base software stack:
|
||||
|
||||
# apt-get install git nodejs redis-server npm build-essential imagemagick
|
||||
|
||||
If you want to use MongoDB instead of Redis install it from http://www.mongodb.org/downloads and remove 'redis-server' from the above command. [MongoDB-Setup](https://github.com/designcreateplay/NodeBB/wiki/MongoDB-Setup)
|
||||
|
||||
**If your package manager only installed a version of Node.js that is less than 0.8 (e.g. Ubuntu 12.10, 13.04):**
|
||||
|
||||
# add-apt-repository ppa:chris-lea/node.js
|
||||
|
||||
108
app.js
108
app.js
@@ -25,9 +25,11 @@
|
||||
|
||||
var fs = require('fs'),
|
||||
async = require('async'),
|
||||
semver = require('semver'),
|
||||
winston = require('winston'),
|
||||
pkg = require('./package.json'),
|
||||
path = require('path'),
|
||||
pkg = require('./package.json'),
|
||||
utils = require('./public/src/utils.js'),
|
||||
meta;
|
||||
|
||||
// Runtime environment
|
||||
@@ -48,6 +50,12 @@
|
||||
winston.error(err.stack);
|
||||
};
|
||||
|
||||
require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
|
||||
if(err || !stdout) {
|
||||
winston.warn('Couldn\'t find convert. Did you install imagemagick?');
|
||||
}
|
||||
});
|
||||
|
||||
// Log GNU copyright info along with server info
|
||||
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
||||
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
|
||||
@@ -55,15 +63,15 @@
|
||||
winston.info('');
|
||||
|
||||
|
||||
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
|
||||
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('install') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
|
||||
// Load server-side configs
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
});
|
||||
meta = require('./src/meta.js');
|
||||
meta = require('./src/meta');
|
||||
|
||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + path.sep);
|
||||
nconf.set('upload_url', path.join(path.sep, nconf.get('relative_path'), 'uploads', path.sep));
|
||||
nconf.set('base_dir', __dirname);
|
||||
|
||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
@@ -73,61 +81,55 @@
|
||||
winston.info('Base Configuration OK.');
|
||||
}
|
||||
|
||||
meta.configs.init(function () {
|
||||
// Initial setup for Redis & Reds
|
||||
var reds = require('reds'),
|
||||
RDB = require('./src/redis.js');
|
||||
if (semver.gt(pkg.dependencies['nodebb-theme-cerulean'], require('./node_modules/nodebb-theme-cerulean/package.json').version)) {
|
||||
winston.error('nodebb-theme-cerulean is out of date - please run npm install.')
|
||||
}
|
||||
|
||||
reds.createClient = function () {
|
||||
return reds.client || (reds.client = RDB);
|
||||
};
|
||||
require('./src/database').init(function(err) {
|
||||
meta.configs.init(function () {
|
||||
|
||||
var templates = require('./public/src/templates.js'),
|
||||
translator = require('./public/src/translator.js'),
|
||||
webserver = require('./src/webserver.js'),
|
||||
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
|
||||
websockets = require('./src/websockets.js'),
|
||||
posts = require('./src/posts.js'),
|
||||
plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself
|
||||
Notifications = require('./src/notifications'),
|
||||
Upgrade = require('./src/upgrade');
|
||||
var templates = require('./public/src/templates'),
|
||||
translator = require('./public/src/translator'),
|
||||
webserver = require('./src/webserver'),
|
||||
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket'], 'browser client minification': true}),
|
||||
websockets = require('./src/websockets'),
|
||||
plugins = require('./src/plugins'),
|
||||
notifications = require('./src/notifications'),
|
||||
upgrade = require('./src/upgrade');
|
||||
|
||||
Upgrade.check(function(schema_ok) {
|
||||
if (schema_ok || nconf.get('check-schema') === false) {
|
||||
websockets.init(SocketIO);
|
||||
upgrade.check(function(schema_ok) {
|
||||
if (schema_ok || nconf.get('check-schema') === false) {
|
||||
websockets.init(SocketIO);
|
||||
|
||||
global.templates = {};
|
||||
global.translator = translator;
|
||||
plugins.init();
|
||||
global.templates = {};
|
||||
global.translator = translator;
|
||||
|
||||
translator.loadServer();
|
||||
translator.loadServer();
|
||||
|
||||
var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false;
|
||||
|
||||
// todo: replace below with read directory code, derp.
|
||||
templates.init([
|
||||
'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index',
|
||||
'emails/reset', 'emails/reset_plaintext', 'emails/email_confirm', 'emails/email_confirm_plaintext',
|
||||
'emails/header', 'emails/footer',
|
||||
|
||||
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
||||
], customTemplates);
|
||||
var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false;
|
||||
|
||||
|
||||
plugins.ready(function() {
|
||||
templates.ready(webserver.init);
|
||||
});
|
||||
utils.walk(path.join(__dirname, 'public/templates'), function (err, tplsToLoad) {
|
||||
templates.init(tplsToLoad, customTemplates);
|
||||
});
|
||||
|
||||
Notifications.init();
|
||||
} else {
|
||||
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
|
||||
winston.warn(' node app --upgrade');
|
||||
winston.warn('To ignore this error (not recommended):');
|
||||
winston.warn(' node app --no-check-schema')
|
||||
process.exit();
|
||||
}
|
||||
plugins.ready(function() {
|
||||
templates.ready(webserver.init);
|
||||
});
|
||||
|
||||
notifications.init();
|
||||
} else {
|
||||
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
|
||||
winston.warn(' node app --upgrade');
|
||||
winston.warn('To ignore this error (not recommended):');
|
||||
winston.warn(' node app --no-check-schema')
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else if (nconf.get('setup') || !fs.existsSync(__dirname + '/config.json')) {
|
||||
} else if (nconf.get('setup') || nconf.get('install') || !fs.existsSync(__dirname + '/config.json')) {
|
||||
// New install, ask setup questions
|
||||
if (nconf.get('setup')) {
|
||||
winston.info('NodeBB Setup Triggered via Command Line');
|
||||
@@ -159,10 +161,12 @@
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
});
|
||||
meta = require('./src/meta.js');
|
||||
require('./src/database').init(function(err) {
|
||||
meta = require('./src/meta.js');
|
||||
|
||||
meta.configs.init(function () {
|
||||
require('./src/upgrade').upgrade();
|
||||
meta.configs.init(function () {
|
||||
require('./src/upgrade').upgrade();
|
||||
});
|
||||
});
|
||||
} else/* if (nconf.get('help') */{
|
||||
winston.info('Usage: node app [options] [arguments]');
|
||||
|
||||
@@ -2,85 +2,97 @@
|
||||
{
|
||||
"name": "Announcements",
|
||||
"description": "Announcements regarding our community",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-bullhorn",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-bullhorn",
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"name": "General Discussion",
|
||||
"description": "A place to talk about whateeeever you want",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-comment",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-comment",
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Development",
|
||||
"description": "NodeBB development news and announcements",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-github",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-github",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"name": "Blogs",
|
||||
"description": "Blog posts from individual members",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-pencil",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-pencil",
|
||||
"order": 4
|
||||
},
|
||||
{
|
||||
"name": "Feature Requests",
|
||||
"description": "Got a feature request you'd like to see? Give us a shout here.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-lightbulb",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-lightbulb-o",
|
||||
"order": 5
|
||||
},
|
||||
{
|
||||
"name": "Bug Reports",
|
||||
"description": "Having trouble with NodeBB? Let us know...",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-cogs",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-cogs",
|
||||
"order": 6
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Plugins",
|
||||
"description": "Enhance your NodeBB with plugins!",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-plus-sign",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-plus-square",
|
||||
"order": 7
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Link Exchange",
|
||||
"description": "Link exchange",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-exchange",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-exchange",
|
||||
"order": 8
|
||||
},
|
||||
{
|
||||
"name": "News",
|
||||
"description": "News from around the world",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-globe",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-globe",
|
||||
"order": 9
|
||||
},
|
||||
{
|
||||
"name": "Movies",
|
||||
"description": "Discuss the latest movies here",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-film",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-film",
|
||||
"order": 10
|
||||
},
|
||||
{
|
||||
"name": "Games",
|
||||
"description": "Discuss the latest games here",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-screenshot",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-crosshairs",
|
||||
"order": 11
|
||||
},
|
||||
{
|
||||
"name": "Random",
|
||||
"description": "Anything and (almost) everything welcome!",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-beer",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-beer",
|
||||
"order": 12
|
||||
}
|
||||
]
|
||||
81
mocks/databasemock.js
Normal file
81
mocks/databasemock.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Database Mock - wrapper for database.js, makes system use separate test db, instead of production
|
||||
* ATTENTION: testing db is flushed before every use!
|
||||
*/
|
||||
|
||||
(function(module) {
|
||||
'use strict';
|
||||
|
||||
var utils = require('./../public/src/utils.js'),
|
||||
path = require('path'),
|
||||
nconf = require('nconf'),
|
||||
winston = require('winston'),
|
||||
errorText;
|
||||
|
||||
|
||||
nconf.file({ file: path.join(__dirname, '../config.json') });
|
||||
|
||||
var dbType = nconf.get('database'),
|
||||
testDbConfig = nconf.get('test_database'),
|
||||
productionDbConfig = nconf.get(dbType);
|
||||
|
||||
if(!testDbConfig){
|
||||
errorText = 'test_database is not defined';
|
||||
winston.info(
|
||||
"\n===========================================================\n"+
|
||||
"Please, add parameters for test database in config.json\n"+
|
||||
"For example (redis):\n"+
|
||||
'"test_database": {' + '\n' +
|
||||
' "host": "127.0.0.1",' + '\n' +
|
||||
' "port": "6379",' + '\n' +
|
||||
' "password": "",' + '\n' +
|
||||
' "database": "1"' + '\n' +
|
||||
'}\n'+
|
||||
" or (mongo):\n" +
|
||||
'"test_database": {' + '\n' +
|
||||
' "host": "127.0.0.1",' + '\n' +
|
||||
' "port": "27017",' + '\n' +
|
||||
' "password": "",' + '\n' +
|
||||
' "database": "1"' + '\n' +
|
||||
'}\n'+
|
||||
"==========================================================="
|
||||
);
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
if( testDbConfig.database === productionDbConfig.database &&
|
||||
testDbConfig.host === productionDbConfig.host &&
|
||||
testDbConfig.port === productionDbConfig.port
|
||||
){
|
||||
errorText = 'test_database has the same config as production db';
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
nconf.set(dbType, testDbConfig);
|
||||
|
||||
db = require('../src/database');
|
||||
before(function(done) {
|
||||
|
||||
db.init(function(err) {
|
||||
//Clean up
|
||||
db.flushdb(function(err) {
|
||||
if(err){
|
||||
winston.error(err);
|
||||
throw new Error(err);
|
||||
} else {
|
||||
winston.info('test_database flushed');
|
||||
done();
|
||||
}
|
||||
|
||||
//TODO: data seeding, if needed at all
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = db;
|
||||
|
||||
}(module));
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Redis Mock - wrapper for redis.js, makes system use separate test db, instead of production
|
||||
* ATTENTION: testing db is flushed before every use!
|
||||
*/
|
||||
|
||||
(function(module) {
|
||||
'use strict';
|
||||
|
||||
var RedisDB,
|
||||
redis = require('redis'),
|
||||
utils = require('./../public/src/utils.js'),
|
||||
path = require('path'),
|
||||
nconf = require('nconf'),
|
||||
winston = require('winston'),
|
||||
errorText;
|
||||
|
||||
|
||||
nconf.file({ file: path.join(__dirname, '../config.json') });
|
||||
|
||||
var testDbConfig = nconf.get('redis_test'),
|
||||
productionDbConfig = nconf.get('redis');
|
||||
if(!testDbConfig){
|
||||
errorText = 'redis_test database is not defined';
|
||||
winston.info(
|
||||
"\n===========================================================\n"+
|
||||
"Please, add parameters for test database in config.json\n"+
|
||||
"For example:\n"+
|
||||
'"redis_test": {' + '\n' +
|
||||
' "host": "127.0.0.1",' + '\n' +
|
||||
' "port": "6379",' + '\n' +
|
||||
' "password": "",' + '\n' +
|
||||
' "database": "1"' + '\n' +
|
||||
'}\n'+
|
||||
"==========================================================="
|
||||
);
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
if( testDbConfig.database === productionDbConfig.database &&
|
||||
testDbConfig.host === productionDbConfig.host &&
|
||||
testDbConfig.port === productionDbConfig.port
|
||||
){
|
||||
errorText = 'redis_test database has the same config as production db';
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
nconf.set('redis',testDbConfig);
|
||||
|
||||
RedisDB = require('../src/redis.js');
|
||||
|
||||
|
||||
//Clean up
|
||||
RedisDB.send_command('flushdb', [], function(error){
|
||||
if(error){
|
||||
winston.error(error);
|
||||
throw new Error(error);
|
||||
} else {
|
||||
winston.info('redis_test db flushed');
|
||||
}
|
||||
});
|
||||
|
||||
//TODO: data seeding, if needed at all
|
||||
|
||||
|
||||
module.exports = RedisDB;
|
||||
|
||||
}(module));
|
||||
60
nodebb
60
nodebb
@@ -1,6 +1,54 @@
|
||||
#!/bin/sh
|
||||
clear
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1
|
||||
#!/bin/bash
|
||||
|
||||
# $0 script path
|
||||
# $1 action
|
||||
# $2 subaction
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
node app
|
||||
;;
|
||||
|
||||
dev)
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development node app
|
||||
;;
|
||||
|
||||
watch)
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- app $1
|
||||
;;
|
||||
|
||||
language)
|
||||
case "$2" in
|
||||
check)
|
||||
node app --language="check"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Language Settings"
|
||||
echo $"Usage: $0 language {check}"
|
||||
echo ''
|
||||
column -s ' ' -t <<< '
|
||||
check Compare language files against the /en directory
|
||||
'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Welcome to NodeBB"
|
||||
echo $"Usage: $0 {start|dev|watch|language}"
|
||||
echo ''
|
||||
column -s ' ' -t <<< '
|
||||
start Start NodeBB in production mode
|
||||
dev Start NodeBB in development mode
|
||||
watch Start NodeBB in development mode and watch for changes
|
||||
language Language settings
|
||||
'
|
||||
exit 1
|
||||
esac
|
||||
|
||||
23
package.json
23
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.2",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -14,12 +14,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"socket.io": "~0.9.16",
|
||||
"redis": "0.8.3",
|
||||
"express": "3.2.0",
|
||||
"express-namespace": "~0.1.1",
|
||||
"emailjs": "0.3.4",
|
||||
"cookie": "0.0.6",
|
||||
"connect-redis": "1.4.5",
|
||||
"passport": "0.1.17",
|
||||
"passport-local": "0.1.6",
|
||||
"passport-twitter": "0.1.5",
|
||||
@@ -28,7 +26,7 @@
|
||||
"less-middleware": "0.1.12",
|
||||
"marked": "0.2.8",
|
||||
"bcrypt": "0.7.5",
|
||||
"async": "0.2.8",
|
||||
"async": "~0.2.8",
|
||||
"node-imagemagick": "0.1.8",
|
||||
"gravatar": "1.0.6",
|
||||
"nconf": "~0.6.7",
|
||||
@@ -40,13 +38,20 @@
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0",
|
||||
"validator": "~1.5.1",
|
||||
"nodebb-plugin-mentions": "~0.1.14",
|
||||
"nodebb-plugin-markdown": "~0.1.8",
|
||||
"nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla",
|
||||
"nodebb-theme-cerulean": "0.0.7",
|
||||
"cron": "~1.0.1"
|
||||
"nodebb-plugin-mentions": "~0.1",
|
||||
"nodebb-plugin-markdown": "~0.3",
|
||||
"nodebb-theme-vanilla": "~0.0.12",
|
||||
"nodebb-theme-cerulean": "0.0.10",
|
||||
"cron": "~1.0.1",
|
||||
"semver": "~2.2.1",
|
||||
"string": "~1.7.0",
|
||||
"xregexp": "~2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"redis": "0.8.3",
|
||||
"mongodb": "~1.3.19",
|
||||
"connect-redis": "1.4.5",
|
||||
"connect-mongo": "0.4.0",
|
||||
"hiredis": "~0.1.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
14
public/language/de/category.json
Normal file
14
public/language/de/category.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"new_topic_button": "Neues Thema",
|
||||
"no_topics": "<strong>Es gibt noch keine Threads in dieser Kategorie.</strong><br />Warum beginnst du nicht den ersten?",
|
||||
"sidebar.recent_replies": "Neuste Antworten",
|
||||
"sidebar.active_participants": "Aktive Teilnehmer",
|
||||
"sidebar.moderators": "Moderatoren",
|
||||
"posts": "Posts",
|
||||
"views": "Aufrufe",
|
||||
"posted": "Geposted",
|
||||
"browsing": "Sieht zu",
|
||||
"no_replies": "Niemand hat geantwortet",
|
||||
"replied": "geantwortet",
|
||||
"last_edited_by": "zuletzt editiert durch"
|
||||
}
|
||||
10
public/language/de/footer.json
Normal file
10
public/language/de/footer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"chat.chatting_with": "Chatten mit <span id='chat-with-name'></span>",
|
||||
"chat.placeholder": "schreibe hier etwas, und drücke Enter zum absenden",
|
||||
"chat.send": "Senden",
|
||||
"stats.online": "Online",
|
||||
"stats.users": "Benutzer",
|
||||
"stats.topics": "Themen",
|
||||
"stats.posts": "Beiträge",
|
||||
"success": "erfolg"
|
||||
}
|
||||
31
public/language/de/global.json
Normal file
31
public/language/de/global.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"home": "Übersicht",
|
||||
"search": "Suche",
|
||||
"buttons.close": "Schließen",
|
||||
"403.title": "Zugriff Verweigert",
|
||||
"403.message": "Du bist nicht dazu berechtigt, diese Seite aufzurufen. <a href='/login'>Logge dich ein</a> und versuche es erneut.",
|
||||
"404.title": " Nicht Gefunden",
|
||||
"404.message": "Die abgefragte Seite wurde nicht gefunden. <a href='/''>Zurück zur Übersicht</a>.",
|
||||
"500.title": "Internal error.",
|
||||
"500.message": "Ooops! Looks like something went wrong!",
|
||||
|
||||
"register": "Registrierung",
|
||||
"login": "Login",
|
||||
|
||||
"logout": "Logout",
|
||||
"logout.title": "Du bist ausgeloggt.",
|
||||
"logout.message": "Du hast dich soeben erfolgreich aus dem Forum ausgeloggt.",
|
||||
|
||||
"save_changes": "Speichere Änderungen",
|
||||
"close": "Schließen",
|
||||
|
||||
"header.admin": "Admin",
|
||||
"header.recent": "Aktuell",
|
||||
"header.unread": "Ungelesen",
|
||||
"header.users": "Benutzer",
|
||||
"header.search": "Suche",
|
||||
"header.profile": "Profil",
|
||||
|
||||
"notifications.loading": "Benachrichtigungen laden",
|
||||
"chats.loading": "Nachrichten werden geladen"
|
||||
}
|
||||
10
public/language/de/login.json
Normal file
10
public/language/de/login.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"login": "Einloggen",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort",
|
||||
"remember_me": "Eingeloggt bleiben?",
|
||||
"forgot_password": "Passwort vergessen?",
|
||||
"alternative_logins": "Login Alternativen",
|
||||
"failed_login_attempt": " Anmeldeversuch fehlgeschlagen, versuche es erneut.",
|
||||
"login_successful": "Du hast dich erfolgreich eingeloggt!"
|
||||
}
|
||||
9
public/language/de/notifications.json
Normal file
9
public/language/de/notifications.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Benachrichtigungen",
|
||||
"back_to_home": "Zurück zur Startseite",
|
||||
"mark_all_as_read": "Alles als gelesen markieren",
|
||||
"outgoing_link": "Externer Link",
|
||||
"outgoing_link_message": "Du verlässt nun",
|
||||
"continue_to": "Gehe weiter zu",
|
||||
"return_to": "Kehre zurück zu"
|
||||
}
|
||||
5
public/language/de/recent.json
Normal file
5
public/language/de/recent.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"day": "Tag",
|
||||
"week": "Woche",
|
||||
"month": "Monat"
|
||||
}
|
||||
16
public/language/de/register.json
Normal file
16
public/language/de/register.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"register": "Registrieren",
|
||||
"help.email": "Deine E-Mail Adresse ist standardmäßig nicht öffentlich sichtbar.",
|
||||
"help.username_restrictions": "Einen einmaligen Benutzernamen. 3-16 Zeichen. Andere Benutzer können dich mit @<span id='yourUsername'>Benutzername</span> anschreiben.",
|
||||
"help.minimum_password_length": "Dein Passwort muss mindestens sechs Zeichen lang sein.",
|
||||
"email_address": "E-Mail",
|
||||
"email_address_placeholder": "E-Mail Adresse hier eingeben",
|
||||
"username": "Benutzername",
|
||||
"username_placeholder": "Benutzernamen eingeben",
|
||||
"password": "Passwort",
|
||||
"password_placeholder": "Passwort eingeben",
|
||||
"confirm_password": "Passwort bestätigen",
|
||||
"confirm_password_placeholder": "Passwort zur Bestätigung erneut eingeben",
|
||||
"register_now_button": "Jetzt registrieren",
|
||||
"alternative_registration": "Alternative Registrierung"
|
||||
}
|
||||
13
public/language/de/reset_password.json
Normal file
13
public/language/de/reset_password.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"reset_password": "Passwort zurücksetzen",
|
||||
"update_password": "Ändere Passwort",
|
||||
"password_change": "Passwort wurde geändert",
|
||||
"password_reset_successful": "<p>Das Passwort wurde erfolgreich zurückgesetzt. <a href=\"/login\">Log dich neu ein</a>.",
|
||||
"wrong_reset_code.title": "Der Reset-Code ist falsch.",
|
||||
"wrong_reset_code.message": "Der empfangene Reset-Code war falsch. Bitte versuche es erneut oder <a href=\"/reset\">fordere einen neuen Code an</a>.",
|
||||
"new_password": "Neues Passwort",
|
||||
"repeat_password": "Wiederhole das Passwort",
|
||||
"enter_email": "Bitte gib Deine <strong>E-Mail Adresse</strong> ein und wir senden Dir eine Anleitung, wie Du Dein Passwort zurücksetzen kannst.",
|
||||
"password_reset_sent": "Passwortzrücksetzung beantragt.",
|
||||
"invalid_email": "Ungültige E-Mail / Adresse existiert nicht!"
|
||||
}
|
||||
43
public/language/de/topic.json
Normal file
43
public/language/de/topic.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"topic": "Thema",
|
||||
"topics": "Themen",
|
||||
|
||||
"no_topics_found": "Keine passende Themen gefunden.",
|
||||
|
||||
"profile": "Profil",
|
||||
"posted_by": "geschrieben von",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Werde bei neues Antworten auf dieses Thema benachrichtigt.",
|
||||
"quote": "zitieren",
|
||||
"reply": "antworten",
|
||||
"edit": "bearbeiten",
|
||||
"delete": "löschen",
|
||||
"banned": "gesperrt",
|
||||
"link": "Link",
|
||||
|
||||
"thread_tools.title": "Thread Tools",
|
||||
"thread_tools.pin": "Thread pinnen",
|
||||
"thread_tools.unpin": "Thread nicht mehr pinnen",
|
||||
"thread_tools.lock": "Thread sperren",
|
||||
"thread_tools.move": "Thread verschieben",
|
||||
"thread_tools.delete": "Thread löschen",
|
||||
|
||||
"load_categories": "Kategorien laden",
|
||||
"disabled_categories_note": "Deaktivierte Kategorien sind ausgegraut.",
|
||||
"confirm_move": "verschieben",
|
||||
|
||||
"favourite": "Favorit",
|
||||
"favourites": "Favoriten",
|
||||
"favourites.not_logged_in.title": "Nicht eingeloggt!",
|
||||
"favourites.not_logged_in.message": "Bitte logge dich ein, um diesen Beitrag favorisieren zu können.",
|
||||
"favourites.has_no_favourites":"Du hast noch keine Favoriten.",
|
||||
|
||||
"posted_by": "Geposted von",
|
||||
"loading": "Lade",
|
||||
"more_posts": "Mehr Posts",
|
||||
"move_topic": "Thema verschieben",
|
||||
"topic_will_be_moved_to": "Dieses Thema wird verschoben nach",
|
||||
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts"
|
||||
}
|
||||
5
public/language/de/unread.json
Normal file
5
public/language/de/unread.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"no_unread_topics": "Es gibt keine ungelesenen Themen.",
|
||||
"mark_all_read": "alle als gelesen markieren",
|
||||
"load_more": "mehr laden"
|
||||
}
|
||||
38
public/language/de/user.json
Normal file
38
public/language/de/user.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"banned": "Gebannt",
|
||||
"offline": "offline",
|
||||
"email": "E-Mail",
|
||||
"fullname": "Kompletter Name",
|
||||
"website": "Homepage",
|
||||
"location": "Wohnort",
|
||||
"age": "Alter",
|
||||
"joined": "Beigetreten",
|
||||
"profile_views": "Profilaufrufe",
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts",
|
||||
"followers": "Follower",
|
||||
"following": "Folgt",
|
||||
"signature": "Signatur",
|
||||
"gravatar": "Gravatar",
|
||||
"birthday": "Geburtstag",
|
||||
|
||||
"change_picture": "Ändere Profilbild",
|
||||
"edit": "Ändern",
|
||||
"uploaded_picture": "Hochgeladene Bilder",
|
||||
"upload_new_picture": "Neues Bild hochladen",
|
||||
"change_password": "Ändere Passwort",
|
||||
"confirm_password": "Passwort wiederholen",
|
||||
"password": "Passwort",
|
||||
|
||||
"upload_picture": "Bild hochladen",
|
||||
"upload_a_picture": "Ein Bild hochladen",
|
||||
"image_spec": "Du solltest nur Dateien die PNG, JPG, oder GIF kleiner als 256kb hochladen.",
|
||||
|
||||
"settings": "Einstellungen",
|
||||
"show_email": "Zeige meine E-Mail Adresse an.",
|
||||
|
||||
"has_no_follower": "Dieser User hat noch keine Follower.",
|
||||
"follows_no_one": "Dieser User folgt noch niemanden."
|
||||
|
||||
|
||||
}
|
||||
9
public/language/de/users.json
Normal file
9
public/language/de/users.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"latest_users": "neuste Benutzer",
|
||||
"top_posters": "meiste Beiträge",
|
||||
"most_reputation": "höhstes Ansehen",
|
||||
"online": "Online",
|
||||
"search": "Suchen",
|
||||
"enter_username": "Benutzer durchsuchen",
|
||||
"load_more": "mehr laden"
|
||||
}
|
||||
@@ -3,5 +3,12 @@
|
||||
"no_topics": "<strong>There are no topics in this category.</strong><br />Why don't you try posting one?",
|
||||
"sidebar.recent_replies": "Recent Replies",
|
||||
"sidebar.active_participants": "Active Participants",
|
||||
"sidebar.moderators": "Moderators"
|
||||
}
|
||||
"sidebar.moderators": "Moderators",
|
||||
"posts": "posts",
|
||||
"views": "views",
|
||||
"posted": "posted",
|
||||
"browsing": "browsing",
|
||||
"no_replies": "No one has replied",
|
||||
"replied": "replied",
|
||||
"last_edited_by": "last edited by"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"chat.chatting_with": "Chat with <span id='chat-with-name'></span>",
|
||||
"chat.chatting_with": "Chat with <span id=\"chat-with-name\"></span>",
|
||||
"chat.placeholder": "type chat message here, press enter to send",
|
||||
"chat.send": "Send",
|
||||
"stats.online": "Online",
|
||||
"stats.users": "Users",
|
||||
"stats.topics": "Topics",
|
||||
"stats.posts": "Posts"
|
||||
}
|
||||
"stats.posts": "Posts",
|
||||
"success": "success"
|
||||
}
|
||||
|
||||
@@ -5,14 +5,27 @@
|
||||
"403.title": "Access Denied",
|
||||
"403.message": "You seem to have stumbled upon a page that you do not have access to. Perhaps you should <a href='/login'>try logging in</a>?",
|
||||
"404.title": "Not Found",
|
||||
"404.message": "You seem to have stumbled upon a page that does not exist. Return to the <a href='/''>home page</a>.",
|
||||
"404.message": "You seem to have stumbled upon a page that does not exist. Return to the <a href='/'>home page</a>.",
|
||||
"500.title": "Internal error.",
|
||||
"500.message": "Oops! Looks like something went wrong!",
|
||||
|
||||
"register": "Register",
|
||||
"login": "Login",
|
||||
|
||||
"logout": "Logout",
|
||||
"logout.title": "You are now logged out.",
|
||||
"logout.message": "You have successfully logged out of NodeBB",
|
||||
|
||||
"save_changes": "Save Changes",
|
||||
"close": "Close",
|
||||
|
||||
"header.admin": "Admin",
|
||||
"header.recent": "Recent",
|
||||
"header.unread": "Unread",
|
||||
"header.users": "Users",
|
||||
"header.search": "Search",
|
||||
"notifications.loading": "Loading Notifications"
|
||||
}
|
||||
"header.profile": "Profile",
|
||||
|
||||
"notifications.loading": "Loading Notifications",
|
||||
"chats.loading": "Loading Chats"
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
"alternative_logins": "Alternative Logins",
|
||||
"failed_login_attempt": "Failed login attempt, please try again.",
|
||||
"login_successful": "You have successfully logged in!"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
{
|
||||
"title": "Notifications"
|
||||
}
|
||||
"title": "Notifications",
|
||||
"back_to_home": "back to NodeBB",
|
||||
"mark_all_as_read": "Mark All as Read",
|
||||
"outgoing_link": "Outgoing Link",
|
||||
"outgoing_link_message": "You are now leaving",
|
||||
"continue_to": "Continue to",
|
||||
"return_to": "Return to "
|
||||
}
|
||||
|
||||
13
public/language/en/reset_password.json
Normal file
13
public/language/en/reset_password.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"reset_password": "Reset Password",
|
||||
"update_password": "Update Password",
|
||||
"password_changed.title": "Password Changed",
|
||||
"password_changed.message": "<p>Password successfully reset, please <a href=\"/login\">log in again</a>.",
|
||||
"wrong_reset_code.title": "Incorrect Reset Code",
|
||||
"wrong_reset_code.message": "The reset code received was incorrect. Please try again, or <a href=\"/reset\">request a new reset code</a>.",
|
||||
"new_password": "New Password",
|
||||
"repeat_password": "Confirm Password",
|
||||
"enter_email": "Please enter your <strong>email address</strong> and we will send you an email with instructions on how to reset your account.",
|
||||
"password_reset_sent": "Password Reset Sent",
|
||||
"invalid_email": "Invalid Email / Email does not exist!"
|
||||
}
|
||||
@@ -1,23 +1,43 @@
|
||||
{
|
||||
"topic": "Topic",
|
||||
"topics": "Topics",
|
||||
|
||||
"no_topics_found": "No topics found!",
|
||||
|
||||
"profile": "Profile",
|
||||
"posted_by": "Posted by",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Be notified of new replies in this topic",
|
||||
"favourite": "Favourite",
|
||||
"quote": "Quote",
|
||||
"reply": "Reply",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"fork": "Fork",
|
||||
"banned": "banned",
|
||||
"link": "Link",
|
||||
|
||||
"thread_tools.title": "Thread Tools",
|
||||
"thread_tools.pin": "Pin Thread",
|
||||
"thread_tools.lock": "Lock Thread",
|
||||
"thread_tools.move": "Move Thread",
|
||||
"thread_tools.delete": "Delete Thread",
|
||||
|
||||
"load_categories": "Loading Categories",
|
||||
"disabled_categories_note": "Disabled Categories are greyed out",
|
||||
"confirm_move": "Move",
|
||||
|
||||
"favourite": "Favourite",
|
||||
"favourites": "Favorites",
|
||||
"favourites.not_logged_in.title": "Not Logged In",
|
||||
"favourites.not_logged_in.message": "Please log in in order to favourite this post"
|
||||
}
|
||||
"favourites.not_logged_in.message": "Please log in in order to favourite this post",
|
||||
"favourites.has_no_favourites": "You don't have any favourites, favourite some posts to see them here!",
|
||||
|
||||
"posted_by": "posted by",
|
||||
"loading": "Loading",
|
||||
"more_posts": "More Posts",
|
||||
"move_topic": "Move Topic",
|
||||
"topic_will_be_moved_to": "This topic will be moved to the category",
|
||||
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts"
|
||||
}
|
||||
|
||||
40
public/language/en/user.json
Normal file
40
public/language/en/user.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"banned": "Banned",
|
||||
"offline": "Offline",
|
||||
"email": "Email",
|
||||
"fullname": "Full Name",
|
||||
"website": "Website",
|
||||
"location": "Location",
|
||||
"age": "Age",
|
||||
"joined": "Joined",
|
||||
"lastonline": "Last Online",
|
||||
"profile_views": "Profile views",
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts",
|
||||
"followers": "Followers",
|
||||
"following": "Following",
|
||||
"signature": "Signature",
|
||||
"gravatar": "Gravatar",
|
||||
"birthday": "Birthday",
|
||||
|
||||
"change_picture": "Change Picture",
|
||||
"edit": "Edit",
|
||||
"uploaded_picture": "Uploaded Picture",
|
||||
"upload_new_picture": "Upload New Picture",
|
||||
"change_password": "Change Password",
|
||||
"confirm_password": "Confirm Password",
|
||||
"password": "Password",
|
||||
|
||||
"upload_picture": "Upload picture",
|
||||
"upload_a_picture": "Upload a picture",
|
||||
"image_spec": "You may only upload PNG, JPG, or GIF files under 256kb.",
|
||||
|
||||
"settings": "settings",
|
||||
"show_email": "Show My Email",
|
||||
|
||||
"has_no_follower": "This user doesn't have any followers :(",
|
||||
"follows_no_one": "This user isn't following anyone :(",
|
||||
|
||||
"email_hidden": "Email Hidden",
|
||||
"hidden": "hidden"
|
||||
}
|
||||
14
public/language/es/category.json
Normal file
14
public/language/es/category.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"new_topic_button": "Nuevo Tema",
|
||||
"no_topics": "<strong>No hay temas en esta categoría.</strong><br />Por que no te animas y publicas uno?",
|
||||
"sidebar.recent_replies": "Respuestas recientes",
|
||||
"sidebar.active_participants": "Miembros más activos",
|
||||
"sidebar.moderators": "Moderadores",
|
||||
"posts": "respuestas",
|
||||
"views": "visitas",
|
||||
"posted": "posted",
|
||||
"browsing": "viendo ahora",
|
||||
"no_replies": "Nadie ha respondido aún",
|
||||
"replied": "respondio",
|
||||
"last_edited_by": "ultima edición por"
|
||||
}
|
||||
10
public/language/es/footer.json
Normal file
10
public/language/es/footer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"chat.chatting_with": "Chatear con <span id='chat-with-name'></span>",
|
||||
"chat.placeholder": "ingresa tu mensaje aqui, y presiona enter para enviar",
|
||||
"chat.send": "Enviar",
|
||||
"stats.online": "Online",
|
||||
"stats.users": "Usuarios",
|
||||
"stats.topics": "Temas",
|
||||
"stats.posts": "Posts",
|
||||
"success": "exito!"
|
||||
}
|
||||
31
public/language/es/global.json
Normal file
31
public/language/es/global.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"home": "Inicio",
|
||||
"search": "Buscar",
|
||||
"buttons.close": "Cerrar",
|
||||
"403.title": "Acceso denegado",
|
||||
"403.message": "Al parecer no tienes premisos necesarios para estar en este lugar. Tal vez puedes <a href='/login'>intentar conectarte</a>?",
|
||||
"404.title": "Ups... 404, no se encontra che!",
|
||||
"404.message": "Al parecer lo que estas buscando no existe. Te recomendamos que vuelvas al <a href='/''>inicio</a>.",
|
||||
"500.title": "Error Interno.",
|
||||
"500.message": "Ooops! Algo salio mal!, No te alarmes. Nuestros simios hiperinteligentes lo solucionarán",
|
||||
|
||||
"register": "Registrarse",
|
||||
"login": "Conectarse",
|
||||
|
||||
"logout": "Salir",
|
||||
"logout.title": "Te has desconectado.",
|
||||
"logout.message": "Haz sido desconectado correctamente",
|
||||
|
||||
"save_changes": "Guardar Cambios",
|
||||
"close": "Cerrar",
|
||||
|
||||
"header.admin": "Admin",
|
||||
"header.recent": "Recientes",
|
||||
"header.unread": "No Leeidos",
|
||||
"header.users": "Miembros",
|
||||
"header.search": "Buscar",
|
||||
"header.profile": "Perfil",
|
||||
|
||||
"notifications.loading": "Cargando Notificaciones",
|
||||
"chats.loading": "Cargando Chats"
|
||||
}
|
||||
10
public/language/es/login.json
Normal file
10
public/language/es/login.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"login": "Conectarse",
|
||||
"username": "Usuario",
|
||||
"password": "Contraseña",
|
||||
"remember_me": "Recordarme?",
|
||||
"forgot_password": "Olvidaste tu contraseña?",
|
||||
"alternative_logins": "Conexiones Alternativas",
|
||||
"failed_login_attempt": "Error al loguearte, intenta de nuevo.",
|
||||
"login_successful": "Te has conectado con exito!"
|
||||
}
|
||||
9
public/language/es/notifications.json
Normal file
9
public/language/es/notifications.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Notificaciones",
|
||||
"back_to_home": "volver al Inicio",
|
||||
"mark_all_as_read": "Marcar todo como leeido",
|
||||
"outgoing_link": "Link Externo",
|
||||
"outgoing_link_message": "Estas saliendo del sitio",
|
||||
"continue_to": "Continuar",
|
||||
"return_to": "Volver a "
|
||||
}
|
||||
5
public/language/es/recent.json
Normal file
5
public/language/es/recent.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"day": "Día",
|
||||
"week": "Semana",
|
||||
"month": "Mes"
|
||||
}
|
||||
16
public/language/es/register.json
Normal file
16
public/language/es/register.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"register": "Registrase",
|
||||
"help.email": "Por defecto, tu email será oculto al publico.",
|
||||
"help.username_restrictions": "El nombre de usuario debe tener entre %1 y %2 caracteres. Los miembros pueden responderte escribiendo @<span id='yourUsername'>usuario</span>.",
|
||||
"help.minimum_password_length": "Tu contraseña debe tener al menos %1 caracteres.",
|
||||
"email_address": "Email",
|
||||
"email_address_placeholder": "Escribe tu email",
|
||||
"username": "Usuario",
|
||||
"username_placeholder": "Escribe tu usuario",
|
||||
"password": "Contraseña",
|
||||
"password_placeholder": "Escribe tu Contraseña",
|
||||
"confirm_password": "Confirmar Contraseña",
|
||||
"confirm_password_placeholder": "Confirmar Contraseña",
|
||||
"register_now_button": "Registrarme ahora",
|
||||
"alternative_registration": "Otros metodos interesantes para registrarse"
|
||||
}
|
||||
13
public/language/es/reset_password.json
Normal file
13
public/language/es/reset_password.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"reset_password": "Resetear Contraseña",
|
||||
"update_password": "Actualizar contraseña",
|
||||
"password_changed.title": "Contraseña editada",
|
||||
"password_changed.message": "<p>La contraseña fue modificada con exito, por favor <a href=\"/login\">conectate de nuevo</a>.",
|
||||
"wrong_reset_code.title": "Código de Reseteo Incorrecto",
|
||||
"wrong_reset_code.message": "El código de reseteo ingresado no es correcto. Por favor intentalo de nuevo o <a href=\"/reset\">pide un nuevo código</a>.",
|
||||
"new_password": "Nueva Contraseña",
|
||||
"repeat_password": "Confirmar Contraseña",
|
||||
"enter_email": "Por favor ingresa tu <strong>email</strong> y te enviaremos un email de como resetear tu cuenta.",
|
||||
"password_reset_sent": "Resteo de contraseña enviado",
|
||||
"invalid_email": "Email Invalido o no existe!"
|
||||
}
|
||||
42
public/language/es/topic.json
Normal file
42
public/language/es/topic.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"topic": "Tema",
|
||||
"topics": "Temas",
|
||||
|
||||
"no_topics_found": "No se encontraron temas!",
|
||||
|
||||
"profile": "Perfil",
|
||||
"posted_by": "Publicado por",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Seras notificado cuando haya nuevas respuestas en este tema",
|
||||
"quote": "Citar",
|
||||
"reply": "Responder",
|
||||
"edit": "Editar",
|
||||
"delete": "Borrar",
|
||||
"banned": "banneado",
|
||||
"link": "Link",
|
||||
|
||||
"thread_tools.title": "Herramientas del Tema",
|
||||
"thread_tools.pin": "Poner Sticky",
|
||||
"thread_tools.lock": "Cerrar Tema",
|
||||
"thread_tools.move": "Mover Tema",
|
||||
"thread_tools.delete": "Borrar Tema",
|
||||
|
||||
"load_categories": "Cargando Categorias",
|
||||
"disabled_categories_note": "Las categorías deshabilidas estan en gris",
|
||||
"confirm_move": "Mover",
|
||||
|
||||
"favourite": "Favorito",
|
||||
"favourites": "Favoritos",
|
||||
"favourites.not_logged_in.title": "No estas conectado :(",
|
||||
"favourites.not_logged_in.message": "Por favor, conectate para agregar a favorito este post.",
|
||||
"favourites.has_no_favourites": "No tienes favoritos, puedes agregar alguno y volver a verlos aqui!",
|
||||
|
||||
"posted_by": "Publicado por",
|
||||
"loading": "Cargando",
|
||||
"more_posts": "Más posts",
|
||||
"move_topic": "Mover Tema",
|
||||
"topic_will_be_moved_to": "Este tema sera movido a la categoría",
|
||||
|
||||
"reputation": "Reputación",
|
||||
"posts": "Posts"
|
||||
}
|
||||
5
public/language/es/unread.json
Normal file
5
public/language/es/unread.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"no_unread_topics": "No hay temas nuevos para leer.",
|
||||
"mark_all_read": "Marcar todo como leeido",
|
||||
"load_more": "Cargar más"
|
||||
}
|
||||
36
public/language/es/user.json
Normal file
36
public/language/es/user.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"banned": "Banneado",
|
||||
"offline": "Desconectado",
|
||||
"email": "Email",
|
||||
"fullname": "Nombre Completo",
|
||||
"website": "Website",
|
||||
"location": "Ubicación",
|
||||
"age": "Edad",
|
||||
"joined": "Registro",
|
||||
"profile_views": "Visitas en su perfil",
|
||||
"reputation": "Reputación",
|
||||
"posts": "Posts",
|
||||
"followers": "Seguidores",
|
||||
"following": "Siguiendo",
|
||||
"signature": "Firma",
|
||||
"gravatar": "Gravatar",
|
||||
"birthday": "Cumpleaños",
|
||||
|
||||
"change_picture": "Cambiar Foto",
|
||||
"edit": "Editar",
|
||||
"uploaded_picture": "Fotos Cargadas",
|
||||
"upload_new_picture": "Cargar Nueva Foto",
|
||||
"change_password": "Cambiar Contraseña",
|
||||
"confirm_password": "Confirmar Contraseña",
|
||||
"password": "Contraseña",
|
||||
|
||||
"upload_picture": "Cargar foto",
|
||||
"upload_a_picture": "Cargar una foto",
|
||||
"image_spec": "Solo puedes usar PNG, JPG, o GIF hasta 256kb.",
|
||||
|
||||
"settings": "Opciones",
|
||||
"show_email": "Mostrar mi Email",
|
||||
|
||||
"has_no_follower": "Este miembro no tiene seguidores :(",
|
||||
"follows_no_one": "Este miembro no sigue a nadie, que pena :("
|
||||
}
|
||||
9
public/language/es/users.json
Normal file
9
public/language/es/users.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"latest_users": "Ultimos Miembros",
|
||||
"top_posters": "Top Posteadores",
|
||||
"most_reputation": "Mayor Reputación",
|
||||
"online": "Conectados",
|
||||
"search": "Buscar",
|
||||
"enter_username": "Ingresa el nombre de usuario para buscar",
|
||||
"load_more": "Cargar más"
|
||||
}
|
||||
14
public/language/fr/category.json
Normal file
14
public/language/fr/category.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"new_topic_button": "Nouveau Sujet",
|
||||
"no_topics": "<strong>Il n'y a aucun topic dans cette catégorie.</strong><br />Pourquoi ne pas en créer un?",
|
||||
"sidebar.recent_replies": "Réponses Récentes",
|
||||
"sidebar.active_participants": "Participants Actifs",
|
||||
"sidebar.moderators": "Modérateurs",
|
||||
"posts": "messages",
|
||||
"views": "vues",
|
||||
"posted": "posté",
|
||||
"browsing": "naviguer",
|
||||
"no_replies": "Personne n'a répondu",
|
||||
"replied": "répondu",
|
||||
"last_edited_by": "dernière édition par"
|
||||
}
|
||||
10
public/language/fr/footer.json
Normal file
10
public/language/fr/footer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"chat.chatting_with": "Chat avec <span id=\"chat-with-name\"></span>",
|
||||
"chat.placeholder": "taper le message ici, presser entrer pour envoyer",
|
||||
"chat.send": "Envoyer",
|
||||
"stats.online": "Online",
|
||||
"stats.users": "Utilisateurs",
|
||||
"stats.topics": "Sujets",
|
||||
"stats.posts": "Message",
|
||||
"success": "succès"
|
||||
}
|
||||
31
public/language/fr/global.json
Normal file
31
public/language/fr/global.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"home": "Accueil",
|
||||
"search": "Recherche",
|
||||
"buttons.close": "Fermer",
|
||||
"403.title": "Accès Refusé",
|
||||
"403.message": "Il semble que vous vous soyez retrouvé sur une page dont vous n'avez pas accès. Peut-être devriez vous <a href='/login'>essayez de vous connecter</a>?",
|
||||
"404.title": "Introuvable",
|
||||
"404.message": "Il semble que vous vous soyez retrouvé sur une page qui n'existe pas. Retourner à <a href='/'>l'accueil</a>.",
|
||||
"500.title": "Erreur Interne.",
|
||||
"500.message": "Oops! Il semblerait que quelque chose se soit mal passé!",
|
||||
|
||||
"register": "S'inscrire",
|
||||
"login": "Connecter",
|
||||
|
||||
"logout": "Déconnection",
|
||||
"logout.title": "Vous êtes maintenant déconnecté.",
|
||||
"logout.message": "Vous vous êtes déconnecté de NodeBB avec succès",
|
||||
|
||||
"save_changes": "Enregistrer les changements",
|
||||
"close": "Fermer",
|
||||
|
||||
"header.admin": "Admin",
|
||||
"header.recent": "Récent",
|
||||
"header.unread": "Non Lu",
|
||||
"header.users": "Utilisateurs",
|
||||
"header.search": "Recherche",
|
||||
"header.profile": "Profile",
|
||||
|
||||
"notifications.loading": "Chargement des Notifications",
|
||||
"chats.loading": "Chargement des Chats"
|
||||
}
|
||||
10
public/language/fr/login.json
Normal file
10
public/language/fr/login.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"login": "Connexion",
|
||||
"username": "Identifiant",
|
||||
"password": "Mot de passe",
|
||||
"remember_me": "Se souvenir de moi?",
|
||||
"forgot_password": "Mot de passe oublié?",
|
||||
"alternative_logins": "Connexion Alternative",
|
||||
"failed_login_attempt": "Echèc d'authentification, veuillez réessayer.",
|
||||
"login_successful": "Vous êtes maintenant connecté!"
|
||||
}
|
||||
9
public/language/fr/notifications.json
Normal file
9
public/language/fr/notifications.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Notifications",
|
||||
"back_to_home": "retour à NodeBB",
|
||||
"mark_all_as_read": "Tout marquer comme lu",
|
||||
"outgoing_link": "Lien Sortant",
|
||||
"outgoing_link_message": "Vous quitter NodeBB",
|
||||
"continue_to": "Continuer vers",
|
||||
"return_to": "Retour vers"
|
||||
}
|
||||
5
public/language/fr/recent.json
Normal file
5
public/language/fr/recent.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"day": "Jour",
|
||||
"week": "Semaine",
|
||||
"month": "Mois"
|
||||
}
|
||||
16
public/language/fr/register.json
Normal file
16
public/language/fr/register.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"register": "S'inscrire",
|
||||
"help.email": "Par défault, votre email est masqué du public.",
|
||||
"help.username_restrictions": "Un identifiant unique entre %1 et %2 charactères. Les autres utilisateurs peuvent vous citer avec @<span id='yourUsername'>username</span>.",
|
||||
"help.minimum_password_length": "Votre mot de passe doit avoir au moins %1 charactères.",
|
||||
"email_address": "Adresse Email",
|
||||
"email_address_placeholder": "Entrer l'addresse Email",
|
||||
"username": "Nom d'utilisateur",
|
||||
"username_placeholder": "Entré le Nom d'utilisateur",
|
||||
"password": "Mot de passe",
|
||||
"password_placeholder": "Entrer le Mot de passe",
|
||||
"confirm_password": "Confirmer le Mot de passe",
|
||||
"confirm_password_placeholder": "Confirmer le Mot de passe",
|
||||
"register_now_button": "S'enregistrer maintenant",
|
||||
"alternative_registration": "Enregistrement Alternatif"
|
||||
}
|
||||
13
public/language/fr/reset_password.json
Normal file
13
public/language/fr/reset_password.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"reset_password": "Réinitialiser le Mot de passe",
|
||||
"update_password": "Mettre à jour le Mot de passe",
|
||||
"password_changed.title": "Mot de passe modifié",
|
||||
"password_changed.message": "<p>Mot de passe réinitialisé avec succès, veuillez vous <a href=\"/login\">reconnecter</a>.",
|
||||
"wrong_reset_code.title": "Code de Réinisialisation Incorrect",
|
||||
"wrong_reset_code.message": "Le Code de Réinisialisation est Incorrect. Veillez réessayer, ou <a href=\"/reset\">demander un nouveau Code de Réinisialisation</a>.",
|
||||
"new_password": "Nouveau Mot de passe",
|
||||
"repeat_password": "Confirmer le Mot de passe",
|
||||
"enter_email": "Veuillez entrer votre <strong>adresse email</strong> et vous recevrez un email avec les instruction pour réinitialiser votre compte.",
|
||||
"password_reset_sent": "Réinitialisation de Mot de Passe Envoyée",
|
||||
"invalid_email": "Email Invalide / L'Email n'existe pas!"
|
||||
}
|
||||
42
public/language/fr/topic.json
Normal file
42
public/language/fr/topic.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"topic": "Sujet",
|
||||
"topics": "Sujets",
|
||||
|
||||
"no_topics_found": "Aucun sujet trouvé!",
|
||||
|
||||
"profile": "Profile",
|
||||
"posted_by": "Envoyé by",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Être notifié des réponses dans ce sujet",
|
||||
"quote": "Citer",
|
||||
"reply": "Répondre",
|
||||
"edit": "Editer",
|
||||
"delete": "Supprimer",
|
||||
"banned": "bannir",
|
||||
"link": "Lien",
|
||||
|
||||
"thread_tools.title": "Outils du Fil",
|
||||
"thread_tools.pin": "Epingler le fil",
|
||||
"thread_tools.lock": "Verrouiller le fil",
|
||||
"thread_tools.move": "Déplacer le fil",
|
||||
"thread_tools.delete": "Supprimer le fil",
|
||||
|
||||
"load_categories": "Chargement des Categories",
|
||||
"disabled_categories_note": "Les Catégories Désactivées sont grisées",
|
||||
"confirm_move": "Déplacer",
|
||||
|
||||
"favourite": "Favoris",
|
||||
"favourites": "Favoris",
|
||||
"favourites.not_logged_in.title": "Non Connecté",
|
||||
"favourites.not_logged_in.message": "Veuillez vous connecter avant de mettre ce message en Favoris",
|
||||
"favourites.has_no_favourites": "Vous n'avez aucun Favoris, mettre en favoris des messages pour les voir apparaître ici!",
|
||||
|
||||
"posted_by": "posté par",
|
||||
"loading": "Chargement",
|
||||
"more_posts": "d'autres Messages",
|
||||
"move_topic": "Déplacer le Sujet",
|
||||
"topic_will_be_moved_to": "Ce sujet sera déplacé vers la catégorie",
|
||||
|
||||
"reputation": "réputation",
|
||||
"posts": "messages"
|
||||
}
|
||||
5
public/language/fr/unread.json
Normal file
5
public/language/fr/unread.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"no_unread_topics": "Aucun sujet non lu.",
|
||||
"mark_all_read": "Marquer tout comme lu",
|
||||
"load_more": "Charger la suite"
|
||||
}
|
||||
36
public/language/fr/user.json
Normal file
36
public/language/fr/user.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"banned": "Banni",
|
||||
"offline": "Hors-ligne",
|
||||
"email": "email",
|
||||
"fullname": "Nom",
|
||||
"website": "Site Web",
|
||||
"location": "Emplacement",
|
||||
"age": "age",
|
||||
"joined": "adhésion",
|
||||
"profil_views": "vues du profil",
|
||||
"reputation": "réputation",
|
||||
"posts": "messages",
|
||||
"followers": "suiveurs",
|
||||
"following": "suivis",
|
||||
"signature": "signature",
|
||||
"gravatar": "gravatar",
|
||||
"birthday": "anniversaire",
|
||||
|
||||
"change_picture": "changer d'image",
|
||||
"edit": "editer",
|
||||
"uploaded_picture": "images uploadées",
|
||||
"upload_new_picture": "uploader une nouvelle image",
|
||||
"change_password": "chnger le mot de passe",
|
||||
"confirm_password": "confirmer le mot de passe",
|
||||
"password": "mot de passe",
|
||||
|
||||
"upload_picture": "Uploader un image",
|
||||
"upload_a_picture": "Uploader un image",
|
||||
"image_spec": "Vous pouvez uploader seulement des fichiers de types PNG, JPG, ou GIF en dessous de 256kb.",
|
||||
|
||||
"settings": "paramètres",
|
||||
"show_my_email": "montrer mon email",
|
||||
|
||||
"has_no_follower": "Cet utilisateur n'a aucun suiver :(",
|
||||
"follows_no_one": "Cet utilisateur ne suit personne :("
|
||||
}
|
||||
9
public/language/fr/users.json
Normal file
9
public/language/fr/users.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"latest_users": "Derniers Utilisateurs",
|
||||
"top_posters": "Meilleurs Publieur",
|
||||
"most_reputation": "Meilleur Réputation",
|
||||
"online": "En Ligne",
|
||||
"search": "Rechercher",
|
||||
"enter_username": "Entrer un nom d'utilisateur pour rechercher",
|
||||
"load_more": "Charger la suite"
|
||||
}
|
||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -25,20 +25,24 @@ var ajaxify = {};
|
||||
window.onpopstate = function (event) {
|
||||
// "quiet": If set to true, will not call pushState
|
||||
if (event !== null && event.state && event.state.url !== undefined) {
|
||||
ajaxify.go(event.state.url, null, null, true);
|
||||
ajaxify.go(event.state.url, null, true);
|
||||
}
|
||||
};
|
||||
|
||||
var pagination;
|
||||
var pagination, paginator_bar;
|
||||
|
||||
ajaxify.go = function (url, callback, template, quiet) {
|
||||
ajaxify.currentPage = null;
|
||||
|
||||
ajaxify.go = function (url, callback, quiet) {
|
||||
// start: the following should be set like so: ajaxify.onchange(function(){}); where the code actually belongs
|
||||
$(window).off('scroll');
|
||||
app.enterRoom('global');
|
||||
|
||||
pagination = pagination || document.getElementById('pagination');
|
||||
paginator_bar = pagination ? document.body.querySelector('.progress-container') : undefined;
|
||||
if (pagination) {
|
||||
pagination.parentNode.style.display = 'none';
|
||||
paginator_bar.style.display = 'none';
|
||||
}
|
||||
|
||||
window.onscroll = null;
|
||||
@@ -67,30 +71,30 @@ var ajaxify = {};
|
||||
}
|
||||
|
||||
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
|
||||
//if (quiet !== true) {
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({
|
||||
url: url
|
||||
}, url, RELATIVE_PATH + '/' + url);
|
||||
ajaxify.currentPage = tpl_url;
|
||||
|
||||
$.ajax(RELATIVE_PATH + '/plugins/fireHook', {
|
||||
type: 'PUT',
|
||||
data: {
|
||||
_csrf: $('#csrf_token').val(),
|
||||
hook: 'page.load',
|
||||
args: {
|
||||
template: tpl_url,
|
||||
url: url,
|
||||
uid: app.uid
|
||||
}
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history[!quiet ? 'pushState' : 'replaceState']({
|
||||
url: url
|
||||
}, url, RELATIVE_PATH + '/' + url);
|
||||
|
||||
$.ajax(RELATIVE_PATH + '/plugins/fireHook', {
|
||||
type: 'PUT',
|
||||
data: {
|
||||
_csrf: $('#csrf_token').val(),
|
||||
hook: 'page.load',
|
||||
args: {
|
||||
template: tpl_url,
|
||||
url: url,
|
||||
uid: app.uid
|
||||
}
|
||||
});
|
||||
}
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
translator.load(tpl_url);
|
||||
|
||||
jQuery('#footer, #content').fadeOut(100);
|
||||
jQuery('#footer, #content').removeClass('hide').addClass('ajaxifying');
|
||||
|
||||
templates.flush();
|
||||
templates.load_template(function () {
|
||||
@@ -107,21 +111,21 @@ var ajaxify = {};
|
||||
|
||||
app.processPage();
|
||||
|
||||
jQuery('#content, #footer').stop(true, true).fadeIn(200, function () {
|
||||
if (window.location.hash) {
|
||||
hash = window.location.hash;
|
||||
}
|
||||
jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying');
|
||||
|
||||
if (hash) {
|
||||
require(['forum/topic'], function(topic) {
|
||||
topic.scrollToPost(hash.substr(1))
|
||||
});
|
||||
}
|
||||
});
|
||||
if (window.location.hash) {
|
||||
hash = window.location.hash;
|
||||
}
|
||||
|
||||
utils.refreshTitle(url);
|
||||
if (hash) {
|
||||
require(['forum/topic'], function(topic) {
|
||||
topic.scrollToPost(hash.substr(1));
|
||||
});
|
||||
}
|
||||
|
||||
}, url, template);
|
||||
app.refreshTitle(url);
|
||||
|
||||
}, url);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -129,6 +133,10 @@ var ajaxify = {};
|
||||
return false;
|
||||
};
|
||||
|
||||
ajaxify.refresh = function() {
|
||||
ajaxify.go(ajaxify.currentPage);
|
||||
};
|
||||
|
||||
$('document').ready(function () {
|
||||
if (!window.history || !window.history.pushState) {
|
||||
return; // no ajaxification for old browsers
|
||||
@@ -154,7 +162,7 @@ var ajaxify = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && e.which === 1) {
|
||||
if ((!e.ctrlKey && !e.shiftKey) && e.which === 1) {
|
||||
if (this.host === window.location.host) {
|
||||
// Internal link
|
||||
var url = this.href.replace(rootUrl + '/', '');
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
var socket,
|
||||
config,
|
||||
app = {
|
||||
'username': null,
|
||||
'uid': null
|
||||
"username": null,
|
||||
"uid": null,
|
||||
"isFocused": true,
|
||||
"currentRoom": null
|
||||
};
|
||||
|
||||
(function () {
|
||||
var showWelcomeMessage = false;
|
||||
|
||||
|
||||
app.loadConfig = function() {
|
||||
|
||||
$.ajax({
|
||||
url: RELATIVE_PATH + '/api/config',
|
||||
success: function (data) {
|
||||
@@ -47,11 +47,40 @@ var socket,
|
||||
|
||||
socket.on('connect', function (data) {
|
||||
if (reconnecting) {
|
||||
reconnectEl.html('<i class="icon-ok"></i> Connected!');
|
||||
reconnectEl.tooltip('destroy');
|
||||
reconnectEl.html('<i class="fa fa-check"></i>');
|
||||
reconnecting = false;
|
||||
|
||||
// Rejoin room that was left when we disconnected
|
||||
var url_parts = document.location.pathname.slice(RELATIVE_PATH.length).split('/').slice(1),
|
||||
room;
|
||||
switch(url_parts[0]) {
|
||||
case 'user':
|
||||
room = 'user/' + templates.get('theirid');
|
||||
case 'topic':
|
||||
room = 'topic_' + url_parts[1];
|
||||
break;
|
||||
case 'category':
|
||||
room = 'category_' + url_parts[1];
|
||||
break;
|
||||
case 'recent': // intentional fall-through
|
||||
case 'unread':
|
||||
room = 'recent_posts';
|
||||
break;
|
||||
case 'admin':
|
||||
room = 'admin';
|
||||
break;
|
||||
|
||||
default:
|
||||
room = 'global';
|
||||
break;
|
||||
}
|
||||
app.enterRoom(room, true);
|
||||
|
||||
socket.emit('reconnected');
|
||||
|
||||
setTimeout(function() {
|
||||
reconnectEl.removeClass('active');
|
||||
reconnectEl.removeClass('active').addClass("hide");
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
@@ -74,8 +103,12 @@ var socket,
|
||||
if (!reconnectEl) reconnectEl = $('#reconnect');
|
||||
reconnecting = true;
|
||||
|
||||
reconnectEl.addClass('active');
|
||||
reconnectEl.html('<i class="icon-spinner icon-spin"></i> Reconnecting...');
|
||||
if (!reconnectEl.hasClass('active')) reconnectEl.html('<i class="fa fa-spinner fa-spin"></i>');
|
||||
reconnectEl.addClass('active').removeClass("hide");
|
||||
|
||||
reconnectEl.tooltip({
|
||||
placement: 'bottom'
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:user.get_online_users', function (users) {
|
||||
@@ -88,10 +121,10 @@ var socket,
|
||||
|
||||
if (uid && jQuery.inArray(uid, users) !== -1) {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="icon-circle"></i>');
|
||||
el.prepend('<i class="fa fa-circle"></i>');
|
||||
} else {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="icon-circle-blank"></i>');
|
||||
el.prepend('<i class="fa fa-circle-o"></i>');
|
||||
}
|
||||
|
||||
el.processed = true;
|
||||
@@ -130,31 +163,20 @@ var socket,
|
||||
},
|
||||
async: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.logout = function() {
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: $('#csrf_token').val()
|
||||
}, function() {
|
||||
window.location.reload(false);
|
||||
window.location.href = RELATIVE_PATH + '/';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// takes a string like 1000 and returns 1,000
|
||||
app.addCommas = function (text) {
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||
}
|
||||
|
||||
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
|
||||
app.strip_tags = function (input, allowed) {
|
||||
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
||||
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
||||
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
||||
|
||||
return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
|
||||
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// use unique alert_id to have multiple alerts visible at a time, use the same alert_id to fade out the current instance
|
||||
// type : error, success, info, warning/notify
|
||||
@@ -217,7 +239,7 @@ var socket,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.alertSuccess = function (message, timeout) {
|
||||
if (!timeout)
|
||||
@@ -229,7 +251,7 @@ var socket,
|
||||
type: 'success',
|
||||
timeout: timeout
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.alertError = function (message, timeout) {
|
||||
if (!timeout)
|
||||
@@ -241,12 +263,11 @@ var socket,
|
||||
type: 'danger',
|
||||
timeout: timeout
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.currentRoom = null;
|
||||
app.enterRoom = function (room) {
|
||||
app.enterRoom = function (room, force) {
|
||||
if (socket) {
|
||||
if (app.currentRoom === room) {
|
||||
if (app.currentRoom === room && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,7 +288,7 @@ var socket,
|
||||
});
|
||||
|
||||
socket.emit('api:user.get_online_users', uids);
|
||||
}
|
||||
};
|
||||
|
||||
function highlightNavigationLink() {
|
||||
var path = window.location.pathname,
|
||||
@@ -286,7 +307,7 @@ var socket,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.createUserTooltips = function() {
|
||||
$('img[title].teaser-pic,img[title].user-img').each(function() {
|
||||
@@ -295,7 +316,13 @@ var socket,
|
||||
title: $(this).attr('title')
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.makeNumbersHumanReadable = function(elements) {
|
||||
elements.each(function() {
|
||||
$(this).html(utils.makeNumberHumanReadable($(this).attr('title')));
|
||||
});
|
||||
};
|
||||
|
||||
app.processPage = function () {
|
||||
app.populateOnlineUsers();
|
||||
@@ -305,12 +332,14 @@ var socket,
|
||||
$('span.timeago').timeago();
|
||||
$('.post-content img').addClass('img-responsive');
|
||||
|
||||
app.makeNumbersHumanReadable($('.human-readable-number'));
|
||||
|
||||
app.createUserTooltips();
|
||||
|
||||
setTimeout(function () {
|
||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
app.showLoginMessage = function () {
|
||||
function showAlert() {
|
||||
@@ -330,13 +359,13 @@ var socket,
|
||||
showAlert();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.addCommasToNumbers = function () {
|
||||
$('.formatted-number').each(function (index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.openChat = function (username, touid) {
|
||||
if (username === app.username) {
|
||||
@@ -371,8 +400,8 @@ var socket,
|
||||
chat.load(chatModal.attr('UUID'));
|
||||
chat.center(chatModal);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
app.scrollToTop = function () {
|
||||
$('body,html').animate({
|
||||
scrollTop: 0
|
||||
@@ -383,19 +412,66 @@ var socket,
|
||||
$('body,html').animate({
|
||||
scrollTop: $('html').height() - 100
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var titleObj = {
|
||||
active: false,
|
||||
interval: undefined,
|
||||
titles: []
|
||||
};
|
||||
app.alternatingTitle = function (title) {
|
||||
if (typeof title !== 'string') return;
|
||||
|
||||
if (title.length > 0) {
|
||||
titleObj.titles[1] = title;
|
||||
if (titleObj.interval) {
|
||||
clearInterval(titleObj.interval);
|
||||
}
|
||||
titleObj.interval = setInterval(function() {
|
||||
window.document.title = titleObj.titles[titleObj.titles.indexOf(window.document.title) ^ 1];
|
||||
}, 2000);
|
||||
} else {
|
||||
if (titleObj.interval) {
|
||||
clearInterval(titleObj.interval);
|
||||
}
|
||||
if (titleObj.titles[0]) window.document.title = titleObj.titles[0];
|
||||
}
|
||||
};
|
||||
|
||||
app.refreshTitle = function(url) {
|
||||
if (!url) {
|
||||
var a = document.createElement('a');
|
||||
a.href = document.location;
|
||||
url = a.pathname.slice(1);
|
||||
}
|
||||
|
||||
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
|
||||
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
|
||||
app.alternatingTitle('');
|
||||
});
|
||||
};
|
||||
|
||||
jQuery('document').ready(function () {
|
||||
$('#search-form').on('submit', function () {
|
||||
var input = $(this).find('input');
|
||||
ajaxify.go("search/" + input.val(), null, "search");
|
||||
ajaxify.go("search/" + input.val());
|
||||
input.val('');
|
||||
return false;
|
||||
});
|
||||
|
||||
$(window).blur(function(){
|
||||
app.isFocused = false;
|
||||
});
|
||||
|
||||
$(window).focus(function(){
|
||||
app.isFocused = true;
|
||||
|
||||
app.alternatingTitle('');
|
||||
});
|
||||
});
|
||||
|
||||
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||
|
||||
app.loadConfig();
|
||||
|
||||
app.alternatingTitle('');
|
||||
}());
|
||||
@@ -17,18 +17,21 @@ define(['forum/accountheader'], function(header) {
|
||||
|
||||
var followBtn = $('#follow-btn');
|
||||
var unfollowBtn = $('#unfollow-btn');
|
||||
var chatBtn = $('#chat-btn');
|
||||
|
||||
if (yourid !== theirid && yourid !== "0") {
|
||||
if (isFollowing) {
|
||||
followBtn.hide();
|
||||
unfollowBtn.show();
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.removeClass('hide');
|
||||
} else {
|
||||
followBtn.show();
|
||||
unfollowBtn.hide();
|
||||
followBtn.removeClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
}
|
||||
chatBtn.removeClass('hide');
|
||||
} else {
|
||||
followBtn.hide();
|
||||
unfollowBtn.hide();
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
chatBtn.addClass('hide');
|
||||
}
|
||||
|
||||
followBtn.on('click', function() {
|
||||
@@ -36,8 +39,8 @@ define(['forum/accountheader'], function(header) {
|
||||
uid: theirid
|
||||
}, function(success) {
|
||||
if (success) {
|
||||
followBtn.hide();
|
||||
unfollowBtn.show();
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.removeClass('hide');
|
||||
app.alertSuccess('You are now following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error following' + username + '!');
|
||||
@@ -51,8 +54,8 @@ define(['forum/accountheader'], function(header) {
|
||||
uid: theirid
|
||||
}, function(success) {
|
||||
if (success) {
|
||||
followBtn.show();
|
||||
unfollowBtn.hide();
|
||||
followBtn.removeClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
app.alertSuccess('You are no longer following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error unfollowing ' + username + '!');
|
||||
@@ -61,6 +64,10 @@ define(['forum/accountheader'], function(header) {
|
||||
return false;
|
||||
});
|
||||
|
||||
chatBtn.on('click', function() {
|
||||
app.openChat(username, theirid);
|
||||
});
|
||||
|
||||
$('.user-recent-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
@@ -72,6 +79,7 @@ define(['forum/accountheader'], function(header) {
|
||||
socket.on('event:new_post', function(data) {
|
||||
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
|
||||
$('.user-recent-posts').prepend(html);
|
||||
$('.user-recent-posts span.timeago').timeago();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -82,12 +90,12 @@ define(['forum/accountheader'], function(header) {
|
||||
|
||||
if (data.online) {
|
||||
onlineStatus.find('span span').text('online');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||
onlineStatus.find('i').attr('class', 'fa fa-circle');
|
||||
} else {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||
onlineStatus.find('i').attr('class', 'fa fa-circle-o');
|
||||
}
|
||||
};
|
||||
|
||||
return Account;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
var AccountEdit = {};
|
||||
var AccountEdit = {},
|
||||
gravatarPicture = '',
|
||||
uploadedPicture = '';
|
||||
|
||||
AccountEdit.init = function() {
|
||||
header.init();
|
||||
|
||||
var gravatarPicture = templates.get('gravatarpicture');
|
||||
var uploadedPicture = templates.get('uploadedpicture');
|
||||
gravatarPicture = templates.get('gravatarpicture');
|
||||
uploadedPicture = templates.get('uploadedpicture');
|
||||
|
||||
var selectedImageType = '';
|
||||
|
||||
@@ -39,6 +41,17 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
function getSignatureCharsLeft() {
|
||||
return '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')';
|
||||
}
|
||||
|
||||
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
|
||||
|
||||
$('#inputSignature').on('keyup change', function(ev) {
|
||||
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
|
||||
});
|
||||
|
||||
$('#changePictureBtn').on('click', function() {
|
||||
selectedImageType = '';
|
||||
AccountEdit.updateImages();
|
||||
@@ -50,14 +63,14 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
});
|
||||
|
||||
$('#gravatar-box').on('click', function() {
|
||||
$('#gravatar-box .icon-ok').show();
|
||||
$('#uploaded-box .icon-ok').hide();
|
||||
$('#gravatar-box .fa-check').show();
|
||||
$('#uploaded-box .fa-check').hide();
|
||||
selectedImageType = 'gravatar';
|
||||
});
|
||||
|
||||
$('#uploaded-box').on('click', function() {
|
||||
$('#gravatar-box .icon-ok').hide();
|
||||
$('#uploaded-box .icon-ok').show();
|
||||
$('#gravatar-box .fa-check').hide();
|
||||
$('#uploaded-box .fa-check').show();
|
||||
selectedImageType = 'uploaded';
|
||||
});
|
||||
|
||||
@@ -82,7 +95,9 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
$('#uploadPictureBtn').on('click', function() {
|
||||
|
||||
$('#change-picture-modal').modal('hide');
|
||||
uploader.open(config.relative_path + '/user/uploadpicture', function(imageUrlOnServer) {
|
||||
uploader.open(RELATIVE_PATH + '/user/uploadpicture', {}, function(imageUrlOnServer) {
|
||||
imageUrlOnServer = imageUrlOnServer + '?' + new Date().getTime();
|
||||
|
||||
$('#user-current-picture').attr('src', imageUrlOnServer);
|
||||
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
|
||||
|
||||
@@ -97,6 +112,22 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
return false;
|
||||
});
|
||||
|
||||
function showError(element, msg) {
|
||||
element.html(msg);
|
||||
element.parent()
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger');
|
||||
element.show();
|
||||
validationError = true;
|
||||
}
|
||||
|
||||
function showSuccess(element, msg) {
|
||||
element.html(msg);
|
||||
element.parent()
|
||||
.removeClass('alert-danger')
|
||||
.addClass('alert-success');
|
||||
element.show();
|
||||
}
|
||||
|
||||
(function handlePasswordChange() {
|
||||
var currentPassword = $('#inputCurrentPassword');
|
||||
@@ -106,42 +137,29 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
var password_confirm = $('#inputNewPasswordAgain');
|
||||
var passwordvalid = false;
|
||||
var passwordsmatch = false;
|
||||
var successIcon = '<i class="fa fa-check"></i>';
|
||||
|
||||
|
||||
function onPasswordChanged() {
|
||||
passwordvalid = utils.isPasswordValid(password.val());
|
||||
if (password.val().length < config.minimumPasswordLength) {
|
||||
password_notify.html('Password too short');
|
||||
password_notify.attr('class', 'alert alert-danger');
|
||||
password_notify.removeClass('hide');
|
||||
showError(password_notify, 'Password too short!');
|
||||
} else if (!passwordvalid) {
|
||||
password_notify.html('Invalid password');
|
||||
password_notify.attr('class', 'alert alert-danger');
|
||||
password_notify.removeClass('hide');
|
||||
showError(password_notify, 'Invalid password!');
|
||||
} else {
|
||||
password_notify.html('OK!');
|
||||
password_notify.attr('class', 'alert alert-success');
|
||||
password_notify.removeClass('hide');
|
||||
showSuccess(password_notify, successIcon);
|
||||
}
|
||||
|
||||
onPasswordConfirmChanged();
|
||||
}
|
||||
|
||||
function onPasswordConfirmChanged() {
|
||||
if (password_notify.hasClass('alert-danger') || !password_confirm.val()) {
|
||||
password_confirm_notify.addClass('hide');
|
||||
return;
|
||||
}
|
||||
if (password.val() !== password_confirm.val()) {
|
||||
password_confirm_notify.html('Passwords must match!');
|
||||
password_confirm_notify.attr('class', 'alert alert-danger');
|
||||
password_confirm_notify.removeClass('hide');
|
||||
passwordsmatch = false;
|
||||
} else {
|
||||
password_confirm_notify.html('OK!');
|
||||
password_confirm_notify.attr('class', 'alert alert-success');
|
||||
password_confirm_notify.removeClass('hide');
|
||||
passwordsmatch = true;
|
||||
if(password.val()) {
|
||||
if (password.val() !== password_confirm.val()) {
|
||||
showError(password_confirm_notify, 'Passwords must match!')
|
||||
passwordsmatch = false;
|
||||
} else {
|
||||
showSuccess(password_confirm_notify, successIcon);
|
||||
passwordsmatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,8 +177,6 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
currentPassword.val('');
|
||||
password.val('');
|
||||
password_confirm.val('');
|
||||
password_notify.addClass('hide');
|
||||
password_confirm_notify.addClass('hide');
|
||||
passwordsmatch = false;
|
||||
passwordvalid = false;
|
||||
|
||||
@@ -194,31 +210,33 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
|
||||
AccountEdit.updateImages = function() {
|
||||
var currentPicture = $('#user-current-picture').attr('src');
|
||||
var gravatarPicture = templates.get('gravatarpicture');
|
||||
var uploadedPicture = templates.get('uploadedpicture');
|
||||
|
||||
if (gravatarPicture) {
|
||||
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
||||
$('#gravatar-box').show();
|
||||
} else
|
||||
} else {
|
||||
$('#gravatar-box').hide();
|
||||
}
|
||||
|
||||
if (uploadedPicture) {
|
||||
$('#user-uploaded-picture').attr('src', uploadedPicture);
|
||||
$('#uploaded-box').show();
|
||||
} else
|
||||
} else {
|
||||
$('#uploaded-box').hide();
|
||||
}
|
||||
|
||||
|
||||
if (currentPicture == gravatarPicture)
|
||||
$('#gravatar-box .icon-ok').show();
|
||||
else
|
||||
$('#gravatar-box .icon-ok').hide();
|
||||
if (currentPicture == gravatarPicture) {
|
||||
$('#gravatar-box .fa-check').show();
|
||||
} else {
|
||||
$('#gravatar-box .fa-check').hide();
|
||||
}
|
||||
|
||||
if (currentPicture == uploadedPicture)
|
||||
$('#uploaded-box .icon-ok').show();
|
||||
else
|
||||
$('#uploaded-box .icon-ok').hide();
|
||||
if (currentPicture == uploadedPicture) {
|
||||
$('#uploaded-box .fa-check').show();
|
||||
} else {
|
||||
$('#uploaded-box .fa-check').hide();
|
||||
}
|
||||
}
|
||||
|
||||
return AccountEdit;
|
||||
|
||||
@@ -10,8 +10,8 @@ define(['forum/accountheader'], function(header) {
|
||||
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
|
||||
};
|
||||
|
||||
socket.emit('api:user.saveSettings', settings, function(success) {
|
||||
if (success) {
|
||||
socket.emit('api:user.saveSettings', settings, function(err) {
|
||||
if (!err) {
|
||||
app.alertSuccess('Settings saved!');
|
||||
} else {
|
||||
app.alertError('There was an error saving settings!');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
define(function() {
|
||||
define(['uploader'], function(uploader) {
|
||||
var Categories = {};
|
||||
|
||||
Categories.init = function() {
|
||||
@@ -18,27 +18,31 @@ define(function() {
|
||||
}
|
||||
|
||||
function select_icon(el) {
|
||||
var selected = el.attr('class').replace(' icon-2x', '');
|
||||
jQuery('#icons .selected').removeClass('selected');
|
||||
var selected = el.attr('class').replace(' fa-2x', '');
|
||||
$('#icons .selected').removeClass('selected');
|
||||
if (selected)
|
||||
jQuery('#icons .' + selected).parent().addClass('selected');
|
||||
$('#icons .' + selected).parent().addClass('selected');
|
||||
|
||||
|
||||
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
|
||||
if (confirm) {
|
||||
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
|
||||
el.attr('class', iconClass + ' icon-2x');
|
||||
el.val(iconClass);
|
||||
el.attr('value', iconClass);
|
||||
var iconClass = $('.bootbox .selected').children(':first').attr('class');
|
||||
|
||||
el.attr('class', iconClass + ' fa-2x');
|
||||
|
||||
// remove the 'fa ' from the class name, just need the icon name itself
|
||||
var categoryIconClass = iconClass.replace('fa ', '');
|
||||
el.val(categoryIconClass);
|
||||
el.attr('value', categoryIconClass);
|
||||
|
||||
modified(el);
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
|
||||
jQuery('.bootbox .col-md-3').on('click', function() {
|
||||
jQuery('.bootbox .selected').removeClass('selected');
|
||||
jQuery(this).addClass('selected');
|
||||
$('.bootbox .col-md-3').on('click', function() {
|
||||
$('.bootbox .selected').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
@@ -58,13 +62,13 @@ define(function() {
|
||||
}
|
||||
}
|
||||
|
||||
jQuery('#entry-container').sortable({
|
||||
$('#entry-container').sortable({
|
||||
stop: function( event, ui ) {
|
||||
updateCategoryOrders();
|
||||
}
|
||||
});
|
||||
jQuery('.blockclass').each(function() {
|
||||
jQuery(this).val(this.getAttribute('data-value'));
|
||||
$('.blockclass').each(function() {
|
||||
$(this).val(this.getAttribute('data-value'));
|
||||
});
|
||||
|
||||
|
||||
@@ -77,7 +81,9 @@ define(function() {
|
||||
name: $('#inputName').val(),
|
||||
description: $('#inputDescription').val(),
|
||||
icon: $('#new-category-modal i').val(),
|
||||
blockclass: $('#inputBlockclass').val()
|
||||
bgColor: '#0059b2',
|
||||
color: '#fff',
|
||||
order: $('.admin-categories #entry-container').children().length + 1
|
||||
};
|
||||
|
||||
socket.emit('api:admin.categories.create', category, function(err, data) {
|
||||
@@ -100,54 +106,50 @@ define(function() {
|
||||
});
|
||||
}
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
$('document').ready(function() {
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
|
||||
jQuery('.nav-pills li').removeClass('active');
|
||||
jQuery('.nav-pills li a').each(function() {
|
||||
$('.nav-pills li').removeClass('active');
|
||||
$('.nav-pills li a').each(function() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
$(this.parentNode).addClass('active');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#save').on('click', save);
|
||||
jQuery('#addNew').on('click', showCreateCategoryModal);
|
||||
jQuery('#create-category-btn').on('click', createNewCategory);
|
||||
$('#save').on('click', save);
|
||||
$('#addNew').on('click', showCreateCategoryModal);
|
||||
$('#create-category-btn').on('click', createNewCategory);
|
||||
|
||||
jQuery('#entry-container').on('click', '.icon', function(ev) {
|
||||
$('#entry-container').on('click', '.icon', function(ev) {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
jQuery('#new-category-modal').on('click', '.icon', function(ev) {
|
||||
$('#new-category-modal').on('click', '.icon', function(ev) {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
jQuery('.blockclass').on('change', function(ev) {
|
||||
update_blockclass(ev.target);
|
||||
});
|
||||
|
||||
jQuery('.category_name, .category_description, .blockclass .category_bgColor').on('change', function(ev) {
|
||||
$('.admin-categories form input').on('change', function(ev) {
|
||||
modified(ev.target);
|
||||
});
|
||||
|
||||
jQuery('.entry-row button').each(function(index, element) {
|
||||
$('.dropdown li[data-disabled]').each(function(index, element) {
|
||||
var disabled = $(element).attr('data-disabled');
|
||||
if (disabled == "0" || disabled == "")
|
||||
$(element).html('Disable');
|
||||
else
|
||||
$(element).html('Enable');
|
||||
|
||||
if (disabled == "0" || disabled == "") {
|
||||
$(element).html('<a href="#"><i class="fa fa-power-off"></i> Disable</a>');
|
||||
} else {
|
||||
$(element).html('<a href="#"><i class="fa fa-power-off"></i> Enable</a>');
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#entry-container').on('click', '.disable-btn', function(ev) {
|
||||
var btn = jQuery(this);
|
||||
$('.dropdown').on('click', '[data-disabled]', function(ev) {
|
||||
var btn = $(this);
|
||||
var categoryRow = btn.parents('li');
|
||||
var cid = categoryRow.attr('data-cid');
|
||||
|
||||
var disabled = btn.html() == "Disable" ? "1" : "0";
|
||||
var disabled = this.getAttribute('data-disabled') === '0' ? '1' : '0';
|
||||
categoryRow.remove();
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid]['disabled'] = disabled;
|
||||
@@ -159,19 +161,190 @@ define(function() {
|
||||
// Colour Picker
|
||||
$('[data-name="bgColor"], [data-name="color"]').each(function(idx, inputEl) {
|
||||
var jinputEl = $(this),
|
||||
parentEl = jinputEl.parents('[data-cid]');
|
||||
previewEl = jinputEl.parents('[data-cid]').find('.preview-box');
|
||||
|
||||
jinputEl.ColorPicker({
|
||||
color: this.value || '#000',
|
||||
onChange: function(hsb, hex) {
|
||||
jinputEl.val('#' + hex);
|
||||
if (inputEl.getAttribute('data-name') === 'bgColor') parentEl.css('background', '#' + hex);
|
||||
else if (inputEl.getAttribute('data-name') === 'color') parentEl.css('color', '#' + hex);
|
||||
if (inputEl.getAttribute('data-name') === 'bgColor') previewEl.css('background', '#' + hex);
|
||||
else if (inputEl.getAttribute('data-name') === 'color') previewEl.css('color', '#' + hex);
|
||||
modified(inputEl);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Permissions modal
|
||||
$('.permissions').on('click', function() {
|
||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||
Categories.launchPermissionsModal(cid);
|
||||
});
|
||||
|
||||
|
||||
$('.upload-button').on('click', function() {
|
||||
var inputEl = this;
|
||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', {cid:cid}, function(imageUrlOnServer) {
|
||||
inputEl.value = imageUrlOnServer;
|
||||
$(inputEl).parents('li[data-cid]').find('.preview-box').css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
|
||||
modified(inputEl);
|
||||
});
|
||||
});
|
||||
|
||||
$('.admin-categories').delegate('.delete-image', 'click', function() {
|
||||
var parent = $(this).parents('li[data-cid]'),
|
||||
inputEl = parent.find('.upload-button'),
|
||||
preview = parent.find('.preview-box'),
|
||||
bgColor = parent.find('.category_bgColor').val();
|
||||
|
||||
inputEl.value = '';
|
||||
modified(inputEl);
|
||||
|
||||
preview.css('background', bgColor);
|
||||
|
||||
$(this).hide();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Categories.launchPermissionsModal = function(cid) {
|
||||
var modal = $('#category-permissions-modal'),
|
||||
searchEl = modal.find('#permission-search'),
|
||||
resultsEl = modal.find('.search-results'),
|
||||
groupsResultsEl = modal.find('.groups-results'),
|
||||
searchDelay;
|
||||
|
||||
searchEl.off().on('keyup', function() {
|
||||
var searchEl = this,
|
||||
resultsFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
clearTimeout(searchDelay);
|
||||
|
||||
searchDelay = setTimeout(function() {
|
||||
socket.emit('api:admin.categories.search', searchEl.value, cid, function(err, results) {
|
||||
var numResults = results.length,
|
||||
resultObj;
|
||||
for(var x=0;x<numResults;x++) {
|
||||
resultObj = results[x];
|
||||
|
||||
liEl.setAttribute('data-uid', resultObj.uid);
|
||||
liEl.innerHTML = '<div class="pull-right">' +
|
||||
'<div class="btn-group">' +
|
||||
'<button type="button" data-priv="+r" class="btn btn-default' + (resultObj.privileges['+r'] ? ' active' : '') + '">Read</button>' +
|
||||
'<button type="button" data-priv="+w" class="btn btn-default' + (resultObj.privileges['+w'] ? ' active' : '') + '">Write</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<img src="' + resultObj.picture + '" /> ' + resultObj.username;
|
||||
|
||||
resultsFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
resultsEl.html(resultsFrag);
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
Categories.refreshPrivilegeList(cid);
|
||||
|
||||
resultsEl.off().on('click', '[data-priv]', function(e) {
|
||||
var btnEl = $(this),
|
||||
uid = btnEl.parents('li[data-uid]').attr('data-uid'),
|
||||
privilege = this.getAttribute('data-priv');
|
||||
e.preventDefault();
|
||||
|
||||
socket.emit('api:admin.categories.setPrivilege', cid, uid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
|
||||
btnEl.toggleClass('active', privileges[privilege]);
|
||||
|
||||
Categories.refreshPrivilegeList(cid);
|
||||
});
|
||||
});
|
||||
|
||||
modal.off().on('click', '.members li > img', function() {
|
||||
searchEl.val(this.getAttribute('title'));
|
||||
searchEl.keyup();
|
||||
});
|
||||
|
||||
// User Groups and privileges
|
||||
socket.emit('api:admin.categories.groupsearch', cid, function(err, results) {
|
||||
var groupsFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
var numResults = results.length,
|
||||
resultObj;
|
||||
|
||||
for(var x=0;x<numResults;x++) {
|
||||
resultObj = results[x];
|
||||
liEl.setAttribute('data-gid', resultObj.gid);
|
||||
liEl.innerHTML = '<div class="pull-right">' +
|
||||
'<div class="btn-group">' +
|
||||
'<button type="button" data-gpriv="+gr" class="btn btn-default' + (resultObj.privileges['+gr'] ? ' active' : '') + '">Read</button>' +
|
||||
'<button type="button" data-gpriv="+gw" class="btn btn-default' + (resultObj.privileges['+gw'] ? ' active' : '') + '">Write</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
' '+resultObj.name;
|
||||
|
||||
groupsFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
groupsResultsEl.html(groupsFrag);
|
||||
});
|
||||
|
||||
groupsResultsEl.off().on('click', '[data-gpriv]', function(e) {
|
||||
var btnEl = $(this),
|
||||
gid = btnEl.parents('li[data-gid]').attr('data-gid'),
|
||||
privilege = this.getAttribute('data-gpriv');
|
||||
e.preventDefault();
|
||||
socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
|
||||
btnEl.toggleClass('active', privileges[privilege]);
|
||||
});
|
||||
})
|
||||
|
||||
modal.modal();
|
||||
};
|
||||
|
||||
Categories.refreshPrivilegeList = function (cid) {
|
||||
var modalEl = $('#category-permissions-modal'),
|
||||
readMembers = modalEl.find('#category-permissions-read'),
|
||||
writeMembers = modalEl.find('#category-permissions-write');
|
||||
socket.emit('api:admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
|
||||
var readLength = privilegeList['+r'].length,
|
||||
writeLength = privilegeList['+w'].length,
|
||||
readFrag = document.createDocumentFragment(),
|
||||
writeFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li'),
|
||||
x, userObj;
|
||||
|
||||
if (readLength > 0) {
|
||||
for(x=0;x<readLength;x++) {
|
||||
userObj = privilegeList['+r'][x];
|
||||
liEl.setAttribute('data-uid', userObj.uid);
|
||||
|
||||
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
|
||||
readFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
liEl.className = 'empty';
|
||||
liEl.innerHTML = 'No users are in this list';
|
||||
readFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
if (writeLength > 0) {
|
||||
for(x=0;x<writeLength;x++) {
|
||||
userObj = privilegeList['+w'][x];
|
||||
liEl.setAttribute('data-uid', userObj.uid);
|
||||
|
||||
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
|
||||
writeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
liEl.className = 'empty';
|
||||
liEl.innerHTML = 'No users are in this list';
|
||||
writeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
readMembers.html(readFrag);
|
||||
writeMembers.html(writeFrag);
|
||||
});
|
||||
};
|
||||
|
||||
return Categories;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define(function() {
|
||||
var Admin = {};
|
||||
|
||||
Admin.init = function() {
|
||||
Admin.init = function() {
|
||||
ajaxify.register_events(['api:get_all_rooms']);
|
||||
socket.on('api:get_all_rooms', function(data) {
|
||||
|
||||
@@ -22,6 +22,14 @@ define(function() {
|
||||
|
||||
app.enterRoom('admin');
|
||||
socket.emit('api:get_all_rooms');
|
||||
|
||||
$('#logout-link').on('click', function() {
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: $('#csrf_token').val()
|
||||
}, function() {
|
||||
window.location.href = RELATIVE_PATH + '/';
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
return Admin;
|
||||
|
||||
@@ -13,7 +13,7 @@ define(function() {
|
||||
|
||||
socket.on('api:admin.plugins.toggle', function(status) {
|
||||
pluginTgl = document.querySelector('.plugins li[data-plugin-id="' + status.id + '"] button');
|
||||
pluginTgl.innerHTML = '<i class="icon-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';
|
||||
pluginTgl.innerHTML = '<i class="fa fa-power-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';
|
||||
|
||||
app.alert({
|
||||
alert_id: 'plugin_toggled_' + status.id,
|
||||
|
||||
@@ -32,12 +32,14 @@ define(['uploader'], function(uploader) {
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
fields[x].checked = app.config[key] === '1' ? true : false;
|
||||
fields[x].checked = parseInt(app.config[key], 10) === 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (fields[x].nodeName === 'TEXTAREA') {
|
||||
if (app.config[key]) fields[x].value = app.config[key];
|
||||
} else if (fields[x].nodeName === 'SELECT') {
|
||||
if (app.config[key]) fields[x].value = app.config[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +63,8 @@ define(['uploader'], function(uploader) {
|
||||
}
|
||||
} else if (fields[x].nodeName === 'TEXTAREA') {
|
||||
value = fields[x].value;
|
||||
} else if (fields[x].nodeName === 'SELECT') {
|
||||
value = fields[x].value;
|
||||
}
|
||||
|
||||
socket.emit('api:config.set', {
|
||||
@@ -71,13 +75,20 @@ define(['uploader'], function(uploader) {
|
||||
});
|
||||
|
||||
$('#uploadLogoBtn').on('click', function() {
|
||||
|
||||
uploader.open(config.relative_path + '/admin/uploadlogo', function(image) {
|
||||
uploader.open(RELATIVE_PATH + '/admin/uploadlogo', {}, function(image) {
|
||||
$('#logoUrl').val(image);
|
||||
});
|
||||
|
||||
uploader.hideAlerts();
|
||||
});
|
||||
|
||||
$('#uploadFaviconBtn').on('click', function() {
|
||||
uploader.open(RELATIVE_PATH + '/admin/uploadfavicon', {}, function(icon) {
|
||||
$('#faviconUrl').val(icon);
|
||||
});
|
||||
|
||||
uploader.hideAlerts();
|
||||
});
|
||||
};
|
||||
|
||||
Settings.remove = function(key) {
|
||||
|
||||
@@ -46,11 +46,11 @@ define(function() {
|
||||
|
||||
if(!topics.length) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
|
||||
|
||||
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
|
||||
this.innerHTML = '<i class="fa fa-refresh fa-spin"></i> Retrieving topics';
|
||||
socket.emit('api:admin.topics.getMore', {
|
||||
limit: 10,
|
||||
after: lastTid
|
||||
|
||||
@@ -19,7 +19,7 @@ define(function() {
|
||||
return parent.attr('data-uid');
|
||||
}
|
||||
|
||||
function updateUserButtons() {
|
||||
function updateUserBanButtons() {
|
||||
jQuery('.ban-btn').each(function(index, element) {
|
||||
var banBtn = $(element);
|
||||
var uid = getUID(banBtn);
|
||||
@@ -27,15 +27,37 @@ define(function() {
|
||||
banBtn.addClass('disabled');
|
||||
else if (isUserBanned(banBtn))
|
||||
banBtn.addClass('btn-warning');
|
||||
else if (!isUserAdmin(banBtn))
|
||||
banBtn.removeClass('disabled');
|
||||
else
|
||||
banBtn.removeClass('btn-warning');
|
||||
updateUserAdminButtons();
|
||||
});
|
||||
}
|
||||
|
||||
function updateUserAdminButtons() {
|
||||
jQuery('.admin-btn').each(function(index, element) {
|
||||
var adminBtn = $(element);
|
||||
var uid = getUID(adminBtn);
|
||||
if (isUserAdmin(adminBtn)) {
|
||||
adminBtn.attr('value', 'UnMake Admin').html('Remove Admin');
|
||||
if (uid === yourid) {
|
||||
adminBtn.addClass('disabled');
|
||||
}
|
||||
}
|
||||
else if (isUserBanned(adminBtn))
|
||||
adminBtn.addClass('disabled');
|
||||
else if (!isUserBanned(adminBtn))
|
||||
adminBtn.removeClass('disabled');
|
||||
else
|
||||
adminBtn.removeClass('btn-warning');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function initUsers() {
|
||||
|
||||
updateUserButtons();
|
||||
updateUserBanButtons();
|
||||
updateUserAdminButtons();
|
||||
|
||||
$('#users-container').on('click', '.ban-btn', function() {
|
||||
var banBtn = $(this);
|
||||
@@ -49,12 +71,14 @@ define(function() {
|
||||
socket.emit('api:admin.user.unbanUser', uid);
|
||||
banBtn.removeClass('btn-warning');
|
||||
parent.attr('data-banned', 0);
|
||||
updateUserAdminButtons();
|
||||
} else {
|
||||
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:admin.user.banUser', uid);
|
||||
banBtn.addClass('btn-warning');
|
||||
parent.attr('data-banned', 1);
|
||||
updateUserAdminButtons();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -62,6 +86,77 @@ define(function() {
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#users-container').on('click', '.admin-btn', function() {
|
||||
var adminBtn = $(this);
|
||||
var isAdmin = isUserAdmin(adminBtn);
|
||||
var parent = adminBtn.parents('.users-box');
|
||||
var isBanned = isUserBanned(adminBtn);
|
||||
var uid = getUID(adminBtn);
|
||||
|
||||
if(uid === yourid){
|
||||
app.alert({
|
||||
title: 'Error',
|
||||
message: 'You can\'t remove yourself as Administrator!',
|
||||
type: 'danger',
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
else if (!isAdmin) {
|
||||
socket.emit('api:admin.user.makeAdmin', uid);
|
||||
adminBtn.attr('value', 'UnMake Admin').html('Remove Admin');
|
||||
parent.attr('data-admin', 1);
|
||||
updateUserBanButtons();
|
||||
|
||||
} else if(uid !== yourid) {
|
||||
bootbox.confirm('Do you really want to remove this user as admin "' + parent.attr('data-username') + '"?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:admin.user.removeAdmin', uid);
|
||||
adminBtn.attr('value', 'Make Admin').html('Make Admin');
|
||||
parent.attr('data-admin', 0);
|
||||
updateUserBanButtons();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function handleUserCreate() {
|
||||
$('#createUser').on('click', function() {
|
||||
$('#create-modal').modal('show');
|
||||
});
|
||||
|
||||
$('#create-modal-go').on('click', function() {
|
||||
var username = $('#create-user-name').val(),
|
||||
email = $('#create-user-email').val(),
|
||||
password = $('#create-user-password').val(),
|
||||
passwordAgain = $('#create-user-password-again').val(),
|
||||
errorEl = $('#create-modal-error');
|
||||
|
||||
if(password !== passwordAgain) {
|
||||
return errorEl.html('<strong>Error</strong><p>Passwords must match!</p>').removeClass('hide');
|
||||
}
|
||||
|
||||
var user = {
|
||||
username: username,
|
||||
email: email,
|
||||
password: password
|
||||
};
|
||||
|
||||
socket.emit('api:admin.user.createUser', user, function(err, data) {
|
||||
if(err) {
|
||||
return errorEl.html('<strong>Error</strong><p>' + err + '</p>').removeClass('hide');
|
||||
}
|
||||
$('#create-modal').modal('hide');
|
||||
app.alertSuccess('User created!');
|
||||
ajaxify.go('admin/users');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +186,7 @@ define(function() {
|
||||
timeoutId = setTimeout(function() {
|
||||
var username = $('#search-user').val();
|
||||
|
||||
jQuery('.icon-spinner').removeClass('none');
|
||||
jQuery('.fa-spinner').removeClass('none');
|
||||
socket.emit('api:admin.user.search', username);
|
||||
|
||||
}, 250);
|
||||
@@ -99,6 +194,8 @@ define(function() {
|
||||
|
||||
initUsers();
|
||||
|
||||
handleUserCreate();
|
||||
|
||||
socket.removeAllListeners('api:admin.user.search');
|
||||
|
||||
socket.on('api:admin.user.search', function(data) {
|
||||
@@ -108,7 +205,7 @@ define(function() {
|
||||
userListEl = document.querySelector('.users');
|
||||
|
||||
userListEl.innerHTML = html;
|
||||
jQuery('.icon-spinner').addClass('none');
|
||||
jQuery('.fa-spinner').addClass('none');
|
||||
|
||||
if (data && data.length === 0) {
|
||||
$('#user-notfound-notify').html('User not found!')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
define(function () {
|
||||
var Category = {};
|
||||
define(['composer'], function(composer) {
|
||||
var Category = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
Category.init = function() {
|
||||
var cid = templates.get('category_id'),
|
||||
@@ -8,8 +9,7 @@ define(function () {
|
||||
googleEl = jQuery('#google-share'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url'),
|
||||
loadingMoreTopics = false;
|
||||
google_url = templates.get('google-share-url');
|
||||
|
||||
app.enterRoom('category_' + cid);
|
||||
|
||||
@@ -27,9 +27,7 @@ define(function () {
|
||||
});
|
||||
|
||||
$('#new_post').on('click', function () {
|
||||
require(['composer'], function (cmp) {
|
||||
cmp.push(0, cid);
|
||||
});
|
||||
composer.newTopic(cid);
|
||||
});
|
||||
|
||||
ajaxify.register_events([
|
||||
@@ -83,36 +81,39 @@ define(function () {
|
||||
Category.onNewTopic = function(data) {
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||
topics: [data]
|
||||
}),
|
||||
topic = $(html),
|
||||
container = $('#topics-container'),
|
||||
topics = $('#topics-container').children('.category-item'),
|
||||
numTopics = topics.length;
|
||||
});
|
||||
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var topic = $(translatedHTML),
|
||||
container = $('#topics-container'),
|
||||
topics = $('#topics-container').children('.category-item'),
|
||||
numTopics = topics.length;
|
||||
|
||||
if (numTopics > 0) {
|
||||
for (var x = 0; x < numTopics; x++) {
|
||||
if ($(topics[x]).find('.icon-pushpin').length) {
|
||||
if(x === numTopics - 1) {
|
||||
topic.insertAfter(topics[x]);
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
|
||||
if (numTopics > 0) {
|
||||
for (var x = 0; x < numTopics; x++) {
|
||||
if ($(topics[x]).find('.fa-thumb-tack').length) {
|
||||
if(x === numTopics - 1) {
|
||||
topic.insertAfter(topics[x]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
topic.insertBefore(topics[x]);
|
||||
break;
|
||||
}
|
||||
topic.insertBefore(topics[x]);
|
||||
break;
|
||||
} else {
|
||||
container.append(topic);
|
||||
}
|
||||
} else {
|
||||
container.append(topic);
|
||||
}
|
||||
|
||||
topic.hide().fadeIn('slow');
|
||||
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
|
||||
topic.hide().fadeIn('slow');
|
||||
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
|
||||
|
||||
addActiveUser(data);
|
||||
addActiveUser(data);
|
||||
|
||||
$('#topics-container span.timeago').timeago();
|
||||
$('#topics-container span.timeago').timeago();
|
||||
});
|
||||
}
|
||||
|
||||
function addActiveUser(data) {
|
||||
@@ -131,22 +132,29 @@ define(function () {
|
||||
}
|
||||
|
||||
Category.onTopicsLoaded = function(topics) {
|
||||
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
container = $('#topics-container');
|
||||
});
|
||||
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container');
|
||||
|
||||
container.append(html);
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
|
||||
$('#topics-container span.timeago').timeago();
|
||||
html = $(translatedHTML);
|
||||
container.append(html);
|
||||
|
||||
$('#topics-container span.timeago').timeago();
|
||||
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Category.loadMoreTopics = function(cid) {
|
||||
if (loadingMoreTopics) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadingMoreTopics = true;
|
||||
socket.emit('api:category.loadMore', {
|
||||
cid: cid,
|
||||
|
||||
@@ -3,10 +3,6 @@ define(['forum/accountheader'], function(header) {
|
||||
|
||||
AccountHeader.init = function() {
|
||||
header.init();
|
||||
|
||||
$('.user-favourite-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
};
|
||||
|
||||
return AccountHeader;
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
});
|
||||
|
||||
socket.on('api:updateHeader', function(data) {
|
||||
jQuery('#search-button').on('click', function() {
|
||||
jQuery('#search-fields').removeClass('hide').show();
|
||||
jQuery(this).hide();
|
||||
jQuery('#search-fields input').focus()
|
||||
|
||||
jQuery('#search-form').on('submit', function() {
|
||||
jQuery('#search-fields').hide();
|
||||
jQuery('#search-button').show();
|
||||
$('#search-button').on('click', function() {
|
||||
$('#search-fields').removeClass('hide').show();
|
||||
$(this).hide();
|
||||
$('#search-fields input').focus();
|
||||
|
||||
$('#search-form').on('submit', function() {
|
||||
$('#search-fields').hide();
|
||||
$('#search-button').show();
|
||||
});
|
||||
|
||||
$('#search-fields input').on('blur', function() {
|
||||
@@ -22,16 +23,17 @@
|
||||
});
|
||||
|
||||
var loggedInMenu = $('#logged-in-menu'),
|
||||
isLoggedIn = data.uid > 0;
|
||||
isLoggedIn = data.uid > 0,
|
||||
allowGuestSearching = (data.config || {}).allowGuestSearching === '1';
|
||||
|
||||
if (isLoggedIn) {
|
||||
jQuery('.nodebb-loggedin').show();
|
||||
jQuery('.nodebb-loggedout').hide();
|
||||
$('.nodebb-loggedin').show();
|
||||
$('.nodebb-loggedout').hide();
|
||||
|
||||
$('#logged-out-menu').addClass('hide');
|
||||
$('#logged-in-menu').removeClass('hide');
|
||||
|
||||
$('#search-button').show();
|
||||
$('#search-button').removeClass("hide").show();
|
||||
|
||||
var userLabel = loggedInMenu.find('#user_label');
|
||||
|
||||
@@ -46,10 +48,14 @@
|
||||
$('#logout-link').on('click', app.logout);
|
||||
}
|
||||
} else {
|
||||
$('#search-button').hide();
|
||||
if (allowGuestSearching) {
|
||||
$('#search-button').removeClass("hide").show();
|
||||
} else {
|
||||
$('#search-button').addClass("hide").hide();
|
||||
}
|
||||
|
||||
jQuery('.nodebb-loggedin').hide();
|
||||
jQuery('.nodebb-loggedout').show();
|
||||
$('.nodebb-loggedin').hide();
|
||||
$('.nodebb-loggedout').show();
|
||||
|
||||
$('#logged-out-menu').removeClass('hide');
|
||||
$('#logged-in-menu').addClass('hide');
|
||||
@@ -66,7 +72,8 @@
|
||||
var notifContainer = document.getElementsByClassName('notifications')[0],
|
||||
notifTrigger = notifContainer.querySelector('a'),
|
||||
notifList = document.getElementById('notif-list'),
|
||||
notifIcon = document.querySelector('.notifications a i');
|
||||
notifIcon = $('.notifications a');
|
||||
|
||||
notifTrigger.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (notifContainer.className.indexOf('open') === -1) {
|
||||
@@ -77,7 +84,6 @@
|
||||
numUnread = data.unread.length,
|
||||
x;
|
||||
notifList.innerHTML = '';
|
||||
console.log(data);
|
||||
if ((data.read.length + data.unread.length) > 0) {
|
||||
for (x = 0; x < numUnread; x++) {
|
||||
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
||||
@@ -105,12 +111,19 @@
|
||||
|
||||
notifList.appendChild(notifFrag);
|
||||
|
||||
if (data.unread.length > 0) notifIcon.className = 'icon-circle active';
|
||||
else notifIcon.className = 'icon-circle-blank';
|
||||
if (data.unread.length > 0) {
|
||||
notifIcon.toggleClass('active', true);
|
||||
} else {
|
||||
notifIcon.toggleClass('active', false);
|
||||
}
|
||||
|
||||
socket.emit('api:notifications.mark_all_read', null, function() {
|
||||
notifIcon.className = 'icon-circle-blank';
|
||||
utils.refreshTitle();
|
||||
notifIcon.toggleClass('active', false);
|
||||
app.refreshTitle();
|
||||
|
||||
// Update favicon + local count
|
||||
Tinycon.setBubble(0);
|
||||
localStorage.setItem('notifications:count', 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -135,8 +148,29 @@
|
||||
}
|
||||
});
|
||||
|
||||
var updateNotifCount = function(count) {
|
||||
// Update notification icon, if necessary
|
||||
if (count > 0) {
|
||||
notifIcon.toggleClass('active', true);
|
||||
} else {
|
||||
notifIcon.toggleClass('active', false);
|
||||
}
|
||||
|
||||
// Update the favicon + saved local count
|
||||
Tinycon.setBubble(count);
|
||||
localStorage.setItem('notifications:count', count);
|
||||
};
|
||||
|
||||
socket.emit('api:notifications.getCount', function(err, count) {
|
||||
if (!err) {
|
||||
updateNotifCount(count);
|
||||
} else {
|
||||
updateNotifCount(0);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('event:new_notification', function() {
|
||||
document.querySelector('.notifications a i').className = 'icon-circle active';
|
||||
notifIcon.toggleClass('active', true);
|
||||
app.alert({
|
||||
alert_id: 'new_notif',
|
||||
title: 'New notification',
|
||||
@@ -144,26 +178,93 @@
|
||||
type: 'warning',
|
||||
timeout: 2000
|
||||
});
|
||||
utils.refreshTitle();
|
||||
app.refreshTitle();
|
||||
|
||||
if (ajaxify.currentPage === 'notifications') {
|
||||
ajaxify.refresh();
|
||||
}
|
||||
|
||||
// Update the favicon + local storage
|
||||
var savedCount = parseInt(localStorage.getItem('notifications:count'),10) || 0;
|
||||
updateNotifCount(savedCount+1);
|
||||
});
|
||||
socket.on('event:notifications.updateCount', function(count) {
|
||||
updateNotifCount(count);
|
||||
});
|
||||
|
||||
// Chats Dropdown
|
||||
var chatsToggleEl = $('#chat_dropdown'),
|
||||
chatsListEl = $('#chat-list'),
|
||||
chatDropdownEl = chatsToggleEl.parent();
|
||||
chatsToggleEl.on('click', function() {
|
||||
if (chatDropdownEl.hasClass('open')) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.on('chatMessage', function(data) {
|
||||
socket.emit('api:chats.list', function(chats) {
|
||||
var chatsFrag = document.createDocumentFragment(),
|
||||
chatEl = document.createElement('li'),
|
||||
numChats = chats.length,
|
||||
x, userObj;
|
||||
|
||||
if (numChats > 0) {
|
||||
for(x=0;x<numChats;x++) {
|
||||
userObj = chats[x];
|
||||
chatEl.setAttribute('data-uid', userObj.uid);
|
||||
chatEl.innerHTML = '<a href="javascript:app.openChat(\'' + userObj.username + '\', ' + userObj.uid + ');"><img src="' + userObj.picture + '" title="' + userObj.username + '" />' + userObj.username + '</a>';
|
||||
|
||||
chatsFrag.appendChild(chatEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
chatEl.innerHTML = '<a href="#">No Recent Chats</a>';
|
||||
chatsFrag.appendChild(chatEl.cloneNode(true));
|
||||
}
|
||||
|
||||
chatsListEl.empty();
|
||||
chatsListEl.html(chatsFrag);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('event:chats.receive', function(data) {
|
||||
require(['chat'], function(chat) {
|
||||
var modal = null;
|
||||
if (chat.modalExists(data.fromuid)) {
|
||||
modal = chat.getModal(data.fromuid);
|
||||
chat.appendChatMessage(modal, data.message, data.timestamp);
|
||||
|
||||
if (modal.is(":visible")) {
|
||||
chat.load(modal.attr('UUID'));
|
||||
} else {
|
||||
chat.toggleNew(modal.attr('UUID'), true);
|
||||
}
|
||||
|
||||
if (!modal.is(":visible") || !app.isFocused) {
|
||||
app.alternatingTitle(data.username + ' has messaged you');
|
||||
}
|
||||
} else {
|
||||
modal = chat.createModal(data.username, data.fromuid);
|
||||
chat.toggleNew(modal.attr('UUID'), true);
|
||||
app.alternatingTitle(data.username + ' has messaged you');
|
||||
}
|
||||
|
||||
chat.load(modal.attr('UUID'));
|
||||
});
|
||||
});
|
||||
|
||||
require(['mobileMenu'], function(mobileMenu) {
|
||||
mobileMenu.init();
|
||||
});
|
||||
}());
|
||||
function updateUnreadCount(count) {
|
||||
var badge = $('#numUnreadBadge');
|
||||
badge.html(count > 20 ? '20+' : count);
|
||||
|
||||
if (count > 0) {
|
||||
badge
|
||||
.removeClass('badge-inverse')
|
||||
.addClass('badge-important');
|
||||
} else {
|
||||
badge
|
||||
.removeClass('badge-important')
|
||||
.addClass('badge-inverse');
|
||||
}
|
||||
}
|
||||
|
||||
socket.on('event:unread.updateCount', updateUnreadCount);
|
||||
socket.emit('api:unread.count', updateUnreadCount);
|
||||
|
||||
}());
|
||||
|
||||
@@ -2,23 +2,6 @@ define(function() {
|
||||
var Login = {};
|
||||
|
||||
Login.init = function() {
|
||||
// Alternate Logins
|
||||
var altLoginEl = document.querySelector('.alt-logins');
|
||||
altLoginEl.addEventListener('click', function(e) {
|
||||
var target;
|
||||
switch (e.target.nodeName) {
|
||||
case 'LI':
|
||||
target = e.target;
|
||||
break;
|
||||
case 'I':
|
||||
target = e.target.parentNode;
|
||||
break;
|
||||
}
|
||||
if (target) {
|
||||
document.location.href = target.getAttribute('data-url');
|
||||
}
|
||||
});
|
||||
|
||||
$('#login').on('click', function() {
|
||||
var loginData = {
|
||||
'username': $('#username').val(),
|
||||
@@ -26,18 +9,22 @@ define(function() {
|
||||
'_csrf': $('#csrf-token').val()
|
||||
};
|
||||
|
||||
$('#login').attr('disabled', 'disabled').html('Logging in...');
|
||||
$('#login-error-notify').hide();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: RELATIVE_PATH + '/login',
|
||||
data: loginData,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
|
||||
if (!data.success) {
|
||||
$('#login-error-notify').show();
|
||||
$('#login').removeAttr('disabled').html('Login');
|
||||
} else {
|
||||
$('#login-error-notify').hide();
|
||||
|
||||
if(!app.previousUrl) {
|
||||
app.previousUrl = '/';
|
||||
$('#login').html('Redirecting...');
|
||||
if(!app.previousUrl) {
|
||||
app.previousUrl = '/';
|
||||
}
|
||||
|
||||
if(app.previousUrl.indexOf('/reset/') != -1)
|
||||
@@ -50,10 +37,10 @@ define(function() {
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').show();
|
||||
$('#login').removeAttr('disabled').html('Login');
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
timeout: 2000
|
||||
async: true
|
||||
});
|
||||
|
||||
return false;
|
||||
|
||||
@@ -81,16 +81,20 @@ define(function() {
|
||||
}
|
||||
|
||||
Recent.onTopicsLoaded = function(topics) {
|
||||
|
||||
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
container = $('#topics-container');
|
||||
});
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container');
|
||||
|
||||
$('#category-no-topics').remove();
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
html = $(html);
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
|
||||
});
|
||||
}
|
||||
|
||||
Recent.loadMoreTopics = function() {
|
||||
|
||||
@@ -12,7 +12,7 @@ define(function() {
|
||||
password_notify = $('#password-notify'),
|
||||
password_confirm_notify = $('#password-confirm-notify'),
|
||||
validationError = false,
|
||||
successIcon = '<i class="icon icon-ok"></i>';
|
||||
successIcon = '<i class="fa fa-check"></i>';
|
||||
|
||||
$('#referrer').val(app.previousUrl);
|
||||
|
||||
@@ -41,10 +41,11 @@ define(function() {
|
||||
|
||||
if (!utils.isEmailValid(emailEl.val())) {
|
||||
showError(email_notify, 'Invalid email address.');
|
||||
} else
|
||||
} else {
|
||||
socket.emit('user.email.exists', {
|
||||
email: emailEl.val()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
emailEl.on('blur', function() {
|
||||
@@ -134,11 +135,6 @@ define(function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Alternate Logins
|
||||
$('.alt-logins li').on('click', function(e) {
|
||||
document.location.href = $(this).attr('data-url');
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
validationError = false;
|
||||
|
||||
@@ -151,7 +147,9 @@ define(function() {
|
||||
}
|
||||
|
||||
register.on('click', function(e) {
|
||||
if (validateForm()) e.preventDefault();
|
||||
if (validateForm()) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
define(function() {
|
||||
define(['composer'], function(composer) {
|
||||
var Topic = {},
|
||||
infiniteLoaderActive = false;
|
||||
infiniteLoaderActive = false,
|
||||
pagination;
|
||||
|
||||
function showBottomPostBar() {
|
||||
if($('#post-container .post-row').length > 1) {
|
||||
$('.topic-main-buttons').removeClass('hide').parent().removeClass('hide');
|
||||
}
|
||||
}
|
||||
|
||||
Topic.init = function() {
|
||||
var expose_tools = templates.get('expose_tools'),
|
||||
tid = templates.get('topic_id'),
|
||||
postListEl = document.getElementById('post-container'),
|
||||
editBtns = document.querySelectorAll('#post-container .post-buttons .edit, #post-container .post-buttons .edit i'),
|
||||
thread_state = {
|
||||
locked: templates.get('locked'),
|
||||
deleted: templates.get('deleted'),
|
||||
pinned: templates.get('pinned')
|
||||
},
|
||||
topic_name = templates.get('topic_name'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url');
|
||||
topic_name = templates.get('topic_name');
|
||||
|
||||
|
||||
function fixDeleteStateForPosts() {
|
||||
@@ -29,31 +30,13 @@ define(function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
|
||||
app.addCommasToNumbers();
|
||||
|
||||
app.enterRoom('topic_' + tid);
|
||||
|
||||
if($('#post-container .sub-posts').length) {
|
||||
$('.topic-main-buttons').removeClass('hide').parent().removeClass('hide');
|
||||
}
|
||||
|
||||
$('.twitter-share').on('click', function () {
|
||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.facebook-share').on('click', function () {
|
||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.google-share').on('click', function () {
|
||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
showBottomPostBar();
|
||||
|
||||
// Resetting thread state
|
||||
if (thread_state.locked === '1') set_locked_state(true);
|
||||
@@ -119,7 +102,7 @@ define(function() {
|
||||
|
||||
var loadingEl = document.getElementById('categories-loading');
|
||||
if (loadingEl) {
|
||||
socket.once('api:categories.get', function(data) {
|
||||
socket.emit('api:categories.get', function(data) {
|
||||
// Render categories
|
||||
var categoriesFrag = document.createDocumentFragment(),
|
||||
categoryEl = document.createElement('li'),
|
||||
@@ -135,8 +118,10 @@ define(function() {
|
||||
categoriesEl.className = 'category-list';
|
||||
for (x = 0; x < numCategories; x++) {
|
||||
info = data.categories[x];
|
||||
categoryEl.className = info.blockclass + (info.disabled === '1' ? ' disabled' : '');
|
||||
categoryEl.innerHTML = '<i class="' + info.icon + '"></i> ' + info.name;
|
||||
categoryEl.style.background = info.bgColor;
|
||||
categoryEl.style.color = info.color || '#fff';
|
||||
categoryEl.className = info.disabled === '1' ? ' disabled' : '';
|
||||
categoryEl.innerHTML = '<i class="fa ' + info.icon + '"></i> ' + info.name;
|
||||
categoryEl.setAttribute('data-cid', info.cid);
|
||||
categoriesFrag.appendChild(categoryEl.cloneNode(true));
|
||||
}
|
||||
@@ -158,7 +143,7 @@ define(function() {
|
||||
commitEl.disabled = true;
|
||||
$(cancelEl).fadeOut(250);
|
||||
$(moveThreadModal).find('.modal-header button').fadeOut(250);
|
||||
commitEl.innerHTML = 'Moving <i class="icon-spin icon-refresh"></i>';
|
||||
commitEl.innerHTML = 'Moving <i class="fa-spin fa-refresh"></i>';
|
||||
|
||||
socket.once('api:topic.move', function(data) {
|
||||
moveThreadModal.modal('hide');
|
||||
@@ -187,7 +172,6 @@ define(function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
socket.emit('api:categories.get');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -196,7 +180,7 @@ define(function() {
|
||||
|
||||
|
||||
// Follow Thread State
|
||||
var followEl = $('.main-post .follow'),
|
||||
var followEl = $('.posts .follow'),
|
||||
set_follow_state = function(state, quiet) {
|
||||
if (state && !followEl.hasClass('btn-success')) {
|
||||
followEl.addClass('btn-success');
|
||||
@@ -278,13 +262,19 @@ define(function() {
|
||||
|
||||
if ($(selection.baseNode).parents('.post-content').length > 0) {
|
||||
var snippet = selection.toString();
|
||||
if (snippet.length > 0) selectionText = '> ' + snippet.replace(/\n/g, '\n> ');
|
||||
if (snippet.length > 0) {
|
||||
selectionText = '> ' + snippet.replace(/\n/g, '\n> ');
|
||||
}
|
||||
}
|
||||
|
||||
var username = '',
|
||||
post = $(this).parents('li[data-pid]');
|
||||
if(post.length) {
|
||||
username = '@' + post.attr('data-username') + ' ';
|
||||
}
|
||||
|
||||
if (thread_state.locked !== '1') {
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(tid, null, null, selectionText.length > 0 ? selectionText + '\n\n' : '');
|
||||
});
|
||||
composer.newReply(tid, topic_name, selectionText.length > 0 ? selectionText + '\n\n' + username : '' + username);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -292,15 +282,11 @@ define(function() {
|
||||
if (thread_state.locked !== '1') {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
|
||||
socket.once('api:posts.getRawPost', function(data) {
|
||||
socket.emit('api:posts.getRawPost', {pid: pid}, function(data) {
|
||||
|
||||
quoted = '> ' + data.post.replace(/\n/g, '\n> ') + '\n\n';
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(tid, null, null, quoted);
|
||||
});
|
||||
});
|
||||
socket.emit('api:posts.getRawPost', {
|
||||
pid: pid
|
||||
|
||||
composer.newReply(tid, topic_name, quoted);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -309,8 +295,7 @@ define(function() {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
var uid = $(this).parents('li').attr('data-uid');
|
||||
|
||||
var element = $(this).find('i');
|
||||
if (element.attr('class') == 'icon-star-empty') {
|
||||
if ($(this).attr('data-favourited') == 'false') {
|
||||
socket.emit('api:posts.favourite', {
|
||||
pid: pid,
|
||||
room_id: app.currentRoom
|
||||
@@ -331,16 +316,31 @@ define(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$('#post-container').delegate('.edit', 'click', function(e) {
|
||||
var pid = $(this).parents('li').attr('data-pid'),
|
||||
main = $(this).parents('.main-post');
|
||||
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(null, null, pid);
|
||||
});
|
||||
$('#post-container').on('click', '.twitter-share', function () {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
window.open('https://twitter.com/intent/tweet?url=' + encodeURIComponent(window.location.href + '#' + pid) + '&text=' + topic_name, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#post-container').delegate('.delete', 'click', function(e) {
|
||||
$('#post-container').on('click', '.facebook-share', function () {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
window.open('https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(window.location.href + '#' + pid), '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#post-container').on('click', '.google-share', function () {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
window.open('https://plus.google.com/share?url=' + encodeURIComponent(window.location.href + '#' + pid), '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#post-container').on('click', '.edit', function(e) {
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
|
||||
composer.editPost(pid);
|
||||
});
|
||||
|
||||
$('#post-container').on('click', '.delete', function(e) {
|
||||
var pid = $(this).parents('li').attr('data-pid'),
|
||||
postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]')),
|
||||
deleteAction = !postEl.hasClass('deleted') ? true : false,
|
||||
@@ -369,11 +369,27 @@ define(function() {
|
||||
}
|
||||
});
|
||||
|
||||
$('#post-container').on('click', '.fork-post', function(e) {
|
||||
var post = $(this).parents('li'),
|
||||
pid = post.attr('data-pid');
|
||||
|
||||
socket.emit('api:topic.createTopicFromPost', {pid:pid}, function(err) {
|
||||
if(err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
post.fadeOut(500, function() {
|
||||
post.remove();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('#post-container').on('click', '.chat', function(e) {
|
||||
var username = $(this).parents('li.row').attr('data-username');
|
||||
var touid = $(this).parents('li.row').attr('data-uid');
|
||||
|
||||
app.openChat(username, touid);
|
||||
$(this).parents('.btn-group').find('.dropdown-toggle').click();
|
||||
return false;
|
||||
});
|
||||
|
||||
ajaxify.register_events([
|
||||
@@ -446,7 +462,7 @@ define(function() {
|
||||
activeEl.find('.anonymous-box').remove();
|
||||
if(anonymousCount || remainingUsers) {
|
||||
|
||||
var anonLink = $('<div class="anonymous-box inline-block"><i class="icon-user"></i></div>');
|
||||
var anonLink = $('<div class="anonymous-box inline-block"><i class="fa fa-user"></i></div>');
|
||||
activeEl.append(anonLink);
|
||||
|
||||
var title = '';
|
||||
@@ -474,7 +490,21 @@ define(function() {
|
||||
adjust_rep(-1, data.pid, data.uid);
|
||||
});
|
||||
|
||||
socket.on('event:new_post', createNewPosts);
|
||||
socket.on('event:new_post', function(data) {
|
||||
var posts = data.posts;
|
||||
for (var p in posts) {
|
||||
if (posts.hasOwnProperty(p)) {
|
||||
var post = posts[p],
|
||||
postcount = jQuery('.user_postcount_' + post.uid),
|
||||
ptotal = parseInt(postcount.html(), 10);
|
||||
|
||||
ptotal += 1;
|
||||
postcount.html(ptotal);
|
||||
}
|
||||
}
|
||||
|
||||
createNewPosts(data);
|
||||
});
|
||||
|
||||
socket.on('event:topic_deleted', function(data) {
|
||||
if (data.tid === tid && data.status === 'ok') {
|
||||
@@ -539,20 +569,22 @@ define(function() {
|
||||
|
||||
socket.on('api:posts.favourite', function(data) {
|
||||
if (data.status === 'ok' && data.pid) {
|
||||
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||
if (favEl) {
|
||||
favEl.className = 'icon-star';
|
||||
$(favEl).parent().addClass('btn-warning');
|
||||
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
|
||||
if(favBtn.length) {
|
||||
favBtn.addClass('btn-warning')
|
||||
.attr('data-favourited', true)
|
||||
.find('i').attr('class', 'fa fa-star');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:posts.unfavourite', function(data) {
|
||||
if (data.status === 'ok' && data.pid) {
|
||||
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||
if (favEl) {
|
||||
favEl.className = 'icon-star-empty';
|
||||
$(favEl).parent().removeClass('btn-warning');
|
||||
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
|
||||
if(favBtn.length) {
|
||||
favBtn.removeClass('btn-warning')
|
||||
.attr('data-favourited', false)
|
||||
.find('i').attr('class', 'fa fa-star-o');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -598,11 +630,11 @@ define(function() {
|
||||
x;
|
||||
|
||||
if (locked === true) {
|
||||
lockThreadEl.html('<i class="icon-unlock"></i> Unlock Thread');
|
||||
lockThreadEl.html('<i class="fa fa-unlock"></i> Unlock Thread');
|
||||
threadReplyBtn.attr('disabled', true);
|
||||
threadReplyBtn.html('Locked <i class="icon-lock"></i>');
|
||||
threadReplyBtn.html('Locked <i class="fa fa-lock"></i>');
|
||||
for (x = 0; x < numPosts; x++) {
|
||||
postReplyBtns[x].innerHTML = 'Locked <i class="icon-lock"></i>';
|
||||
postReplyBtns[x].innerHTML = 'Locked <i class="fa fa-lock"></i>';
|
||||
quoteBtns[x].style.display = 'none';
|
||||
editBtns[x].style.display = 'none';
|
||||
deleteBtns[x].style.display = 'none';
|
||||
@@ -620,11 +652,11 @@ define(function() {
|
||||
|
||||
thread_state.locked = '1';
|
||||
} else {
|
||||
lockThreadEl.html('<i class="icon-lock"></i> Lock Thread');
|
||||
lockThreadEl.html('<i class="fa fa-lock"></i> Lock Thread');
|
||||
threadReplyBtn.attr('disabled', false);
|
||||
threadReplyBtn.html('Reply');
|
||||
for (x = 0; x < numPosts; x++) {
|
||||
postReplyBtns[x].innerHTML = 'Reply <i class="icon-reply"></i>';
|
||||
postReplyBtns[x].innerHTML = 'Reply <i class="fa fa-reply"></i>';
|
||||
quoteBtns[x].style.display = 'inline-block';
|
||||
editBtns[x].style.display = 'inline-block';
|
||||
deleteBtns[x].style.display = 'inline-block';
|
||||
@@ -652,7 +684,7 @@ define(function() {
|
||||
deleteNotice = document.getElementById('thread-deleted') || document.createElement('div');
|
||||
|
||||
if (deleted) {
|
||||
deleteTextEl.html('<i class="icon-comment"></i> Restore Thread');
|
||||
deleteTextEl.html('<i class="fa fa-comment"></i> Restore Thread');
|
||||
threadEl.addClass('deleted');
|
||||
|
||||
// Spawn a 'deleted' notice at the top of the page
|
||||
@@ -663,7 +695,7 @@ define(function() {
|
||||
|
||||
thread_state.deleted = '1';
|
||||
} else {
|
||||
deleteTextEl.html('<i class="icon-trash"></i> Delete Thread');
|
||||
deleteTextEl.html('<i class="fa fa-trash-o"></i> Delete Thread');
|
||||
threadEl.removeClass('deleted');
|
||||
deleteNotice.parentNode.removeChild(deleteNotice);
|
||||
|
||||
@@ -675,7 +707,7 @@ define(function() {
|
||||
var pinEl = $('.pin_thread');
|
||||
|
||||
if (pinned) {
|
||||
pinEl.html('<i class="icon-pushpin"></i> Unpin Thread');
|
||||
pinEl.html('<i class="fa fa-thumb-tack"></i> Unpin Thread');
|
||||
if (alert) {
|
||||
app.alert({
|
||||
'alert_id': 'thread_pin',
|
||||
@@ -688,7 +720,7 @@ define(function() {
|
||||
|
||||
thread_state.pinned = '1';
|
||||
} else {
|
||||
pinEl.html('<i class="icon-pushpin"></i> Pin Thread');
|
||||
pinEl.html('<i class="fa fa-thumb-tack"></i> Pin Thread');
|
||||
if (alert) {
|
||||
app.alert({
|
||||
'alert_id': 'thread_pin',
|
||||
@@ -764,77 +796,76 @@ define(function() {
|
||||
|
||||
|
||||
|
||||
var postAuthorImage, mobileAuthorOverlay, pagination;
|
||||
var postcount = templates.get('postcount');
|
||||
|
||||
function updateHeader() {
|
||||
if (pagination == null) {
|
||||
jQuery('.pagination-block i:first').on('click', function() {
|
||||
app.scrollToTop();
|
||||
});
|
||||
jQuery('.pagination-block i:last').on('click', function() {
|
||||
app.scrollToBottom();
|
||||
});
|
||||
}
|
||||
|
||||
jQuery('.mobile-author-overlay').css('bottom', '0px');
|
||||
postAuthorImage = postAuthorImage || document.getElementById('mobile-author-image');
|
||||
mobileAuthorOverlay = mobileAuthorOverlay || document.getElementById('mobile-author-overlay');
|
||||
pagination = pagination || document.getElementById('pagination');
|
||||
|
||||
pagination.parentNode.style.display = 'block';
|
||||
|
||||
var windowHeight = jQuery(window).height();
|
||||
var scrollTop = jQuery(window).scrollTop();
|
||||
var scrollBottom = scrollTop + windowHeight;
|
||||
|
||||
if (scrollTop < 50 && postcount > 1) {
|
||||
localStorage.removeItem("topic:" + tid + ":bookmark");
|
||||
postAuthorImage.src = (jQuery('.main-post .avatar img').attr('src'));
|
||||
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery('.main-post').attr('data-username') + ', ' + jQuery('.main-post').find('.relativeTimeAgo').html();
|
||||
pagination.innerHTML = '0 out of ' + postcount;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var count = 0, smallestNonNegative = 0;
|
||||
|
||||
jQuery('.sub-posts').each(function() {
|
||||
count++;
|
||||
this.postnumber = count;
|
||||
|
||||
|
||||
var el = jQuery(this);
|
||||
var elTop = el.offset().top;
|
||||
var height = Math.floor(el.height());
|
||||
var elBottom = elTop + (height < 300 ? height : 300);
|
||||
|
||||
var inView = ((elBottom >= scrollTop) && (elTop <= scrollBottom) && (elBottom <= scrollBottom) && (elTop >= scrollTop));
|
||||
|
||||
|
||||
if (inView) {
|
||||
if(elTop - scrollTop > smallestNonNegative) {
|
||||
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid'));
|
||||
smallestNonNegative = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
pagination.innerHTML = this.postnumber + ' out of ' + postcount;
|
||||
postAuthorImage.src = (jQuery(this).find('.profile-image-block img').attr('src'));
|
||||
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery(this).attr('data-username') + ', ' + jQuery(this).find('.relativeTimeAgo').html();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
if (scrollTop + windowHeight == jQuery(document).height()) {
|
||||
pagination.innerHTML = postcount + ' out of ' + postcount;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
Topic.postCount = templates.get('postcount');
|
||||
|
||||
window.onscroll = updateHeader;
|
||||
window.onload = updateHeader;
|
||||
};
|
||||
|
||||
function updateHeader() {
|
||||
if (pagination == null) {
|
||||
jQuery('.pagination-block i:first').on('click', function() {
|
||||
app.scrollToTop();
|
||||
});
|
||||
jQuery('.pagination-block i:last').on('click', function() {
|
||||
app.scrollToBottom();
|
||||
});
|
||||
}
|
||||
pagination = pagination || document.getElementById('pagination');
|
||||
|
||||
var windowHeight = jQuery(window).height();
|
||||
var scrollTop = jQuery(window).scrollTop();
|
||||
var scrollBottom = scrollTop + windowHeight;
|
||||
var progressBar = $('.progress-bar');
|
||||
var progressBarContainer = $('.progress-container');
|
||||
var tid = templates.get('topic_id');
|
||||
|
||||
pagination.parentNode.style.display = 'block';
|
||||
progressBarContainer.css('display', '');
|
||||
|
||||
if (scrollTop < jQuery('.posts > .post-row:first-child').height() && Topic.postCount > 1) {
|
||||
localStorage.removeItem("topic:" + tid + ":bookmark");
|
||||
pagination.innerHTML = '1 out of ' + Topic.postCount;
|
||||
progressBar.width(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var count = 0, smallestNonNegative = 0;
|
||||
|
||||
jQuery('.posts > .post-row:not(".deleted")').each(function() {
|
||||
count++;
|
||||
this.postnumber = count;
|
||||
|
||||
|
||||
var el = jQuery(this);
|
||||
var elTop = el.offset().top;
|
||||
var height = Math.floor(el.height());
|
||||
var elBottom = elTop + (height < 300 ? height : 300);
|
||||
|
||||
var inView = ((elBottom >= scrollTop) && (elTop <= scrollBottom) && (elBottom <= scrollBottom) && (elTop >= scrollTop));
|
||||
|
||||
|
||||
if (inView) {
|
||||
if(elTop - scrollTop > smallestNonNegative) {
|
||||
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid'));
|
||||
smallestNonNegative = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
pagination.innerHTML = (this.postnumber-1) + ' out of ' + Topic.postCount;
|
||||
progressBar.width(((this.postnumber-1) / Topic.postCount * 100) + '%');
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
if (scrollTop + windowHeight == jQuery(document).height()) {
|
||||
pagination.innerHTML = Topic.postCount + ' out of ' + Topic.postCount;
|
||||
progressBar.width('100%');
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
Topic.scrollToPost = function(pid) {
|
||||
if (!pid) {
|
||||
return;
|
||||
@@ -871,11 +902,8 @@ define(function() {
|
||||
}
|
||||
|
||||
function createNewPosts(data, infiniteLoaded) {
|
||||
if(!data || (data.posts && !data.posts.length))
|
||||
if(!data || (data.posts && !data.posts.length)) {
|
||||
return;
|
||||
|
||||
if (data.posts[0].uid !== app.uid) {
|
||||
data.posts[0].display_moderator_tools = 'none';
|
||||
}
|
||||
|
||||
function removeAlreadyAddedPosts() {
|
||||
@@ -890,7 +918,7 @@ define(function() {
|
||||
$('#post-container li[data-pid]').each(function() {
|
||||
if(parseInt(firstPid, 10) > parseInt($(this).attr('data-pid'), 10)) {
|
||||
after = $(this);
|
||||
if(after.hasClass('main-post')) {
|
||||
if(after.next().length && after.next().hasClass('post-bar')) {
|
||||
after = after.next();
|
||||
}
|
||||
} else {
|
||||
@@ -904,13 +932,16 @@ define(function() {
|
||||
if(!data.posts.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var insertAfter = findInsertionPoint();
|
||||
|
||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
|
||||
|
||||
var regexp = new RegExp("<!--[\\s]*IF @first[\\s]*-->([\\s\\S]*?)<!--[\\s]*ENDIF @first[\\s]*-->", 'g');
|
||||
html = html.replace(regexp, '');
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var translated = $(translatedHTML);
|
||||
|
||||
if(!infiniteLoaded) {
|
||||
translated.removeClass('infiniteloaded');
|
||||
}
|
||||
@@ -930,11 +961,18 @@ define(function() {
|
||||
$('span.timeago').timeago();
|
||||
$('.post-content img').addClass('img-responsive');
|
||||
updatePostCount();
|
||||
showBottomPostBar();
|
||||
});
|
||||
}
|
||||
|
||||
function updatePostCount() {
|
||||
$('#topic-post-count').html($('#post-container li[data-pid]:not(.deleted)').length);
|
||||
socket.emit('api:topics.postcount', templates.get('topic_id'), function(err, postcount) {
|
||||
if(!err) {
|
||||
Topic.postCount = postcount;
|
||||
$('#topic-post-count').html(Topic.postCount);
|
||||
updateHeader();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function loadMorePosts(tid, callback) {
|
||||
@@ -952,7 +990,7 @@ define(function() {
|
||||
|
||||
socket.emit('api:topic.loadMore', {
|
||||
tid: tid,
|
||||
after: $('#post-container .post-row.infiniteloaded').length
|
||||
after: parseInt($('#post-container .post-row.infiniteloaded').last().attr('data-index'), 10) + 1
|
||||
}, function (data) {
|
||||
infiniteLoaderActive = false;
|
||||
if (data.posts.length) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
define(function() {
|
||||
var Unread = {};
|
||||
var Unread = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
Unread.init = function() {
|
||||
var loadingMoreTopics = false;
|
||||
|
||||
app.enter_room('recent_posts');
|
||||
app.enterRoom('recent_posts');
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
@@ -75,13 +74,18 @@ define(function() {
|
||||
|
||||
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
container = $('#topics-container');
|
||||
});
|
||||
|
||||
$('#category-no-topics').remove();
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container');
|
||||
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
html = $(translatedHTML);
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
|
||||
});
|
||||
}
|
||||
|
||||
function loadMoreTopics() {
|
||||
@@ -109,8 +113,9 @@ define(function() {
|
||||
});
|
||||
|
||||
|
||||
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20)
|
||||
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20) {
|
||||
$('#load-more-btn').show();
|
||||
}
|
||||
|
||||
$('#load-more-btn').on('click', function() {
|
||||
loadMoreTopics();
|
||||
|
||||
@@ -36,7 +36,7 @@ define(function() {
|
||||
var username = $('#search-user').val();
|
||||
|
||||
if (username == '') {
|
||||
jQuery('#user-notfound-notify').html('<i class="icon icon-circle-blank"></i>');
|
||||
jQuery('#user-notfound-notify').html('<i class="fa fa-circle-o"></i>');
|
||||
jQuery('#user-notfound-notify').parent().removeClass('btn-warning label-warning btn-success label-success');
|
||||
return;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ define(function() {
|
||||
if (lastSearch === username) return;
|
||||
lastSearch = username;
|
||||
|
||||
jQuery('#user-notfound-notify').html('<i class="icon-spinner icon-spin"></i>');
|
||||
jQuery('#user-notfound-notify').html('<i class="fa fa-spinner fa-spin"></i>');
|
||||
|
||||
setTimeout(function() {
|
||||
socket.emit('api:admin.user.search', username);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
define(['taskbar'], function(taskbar) {
|
||||
define(['taskbar', 'string'], function(taskbar, S) {
|
||||
|
||||
var module = {};
|
||||
|
||||
@@ -67,7 +67,8 @@ define(['taskbar'], function(taskbar) {
|
||||
chatModal.find('.close').on('click', function(e) {
|
||||
clearInterval(chatModal.intervalId);
|
||||
chatModal.intervalId = 0;
|
||||
chatModal.hide();
|
||||
chatModal.remove();
|
||||
chatModal.data('modal', null);
|
||||
taskbar.discard('chat', uuid);
|
||||
});
|
||||
|
||||
@@ -81,13 +82,16 @@ define(['taskbar'], function(taskbar) {
|
||||
checkOnlineStatus(chatModal);
|
||||
});
|
||||
|
||||
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with ' + username});
|
||||
taskbar.push('chat', chatModal.attr('UUID'), {
|
||||
title:'<i class="fa fa-comment"></i> ' + username,
|
||||
state: ''
|
||||
});
|
||||
|
||||
return chatModal;
|
||||
}
|
||||
|
||||
module.center = function(chatModal) {
|
||||
chatModal.css("position", "fixed");
|
||||
chatModal.css("top", "100px");
|
||||
chatModal.css("left", Math.max(0, (($(window).width() - $(chatModal).outerWidth()) / 2) + $(window).scrollLeft()) + "px");
|
||||
return chatModal;
|
||||
}
|
||||
@@ -97,6 +101,9 @@ define(['taskbar'], function(taskbar) {
|
||||
chatModal.show();
|
||||
module.bringModalToTop(chatModal);
|
||||
checkOnlineStatus(chatModal);
|
||||
taskbar.updateActive(uuid);
|
||||
scrollToBottom(chatModal.find('#chat-content'));
|
||||
chatModal.find('#chat-message-input').focus();
|
||||
}
|
||||
|
||||
module.minimize = function(uuid) {
|
||||
@@ -108,7 +115,7 @@ define(['taskbar'], function(taskbar) {
|
||||
}
|
||||
|
||||
function getChatMessages(chatModal, callback) {
|
||||
socket.emit('getChatMessages', {touid:chatModal.touid}, function(messages) {
|
||||
socket.emit('api:chats.get', {touid:chatModal.touid}, function(messages) {
|
||||
for(var i = 0; i<messages.length; ++i) {
|
||||
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
|
||||
}
|
||||
@@ -132,10 +139,10 @@ define(['taskbar'], function(taskbar) {
|
||||
}
|
||||
|
||||
function sendMessage(chatModal) {
|
||||
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
|
||||
var msg = S(chatModal.find('#chat-message-input').val()).stripTags().s;
|
||||
if(msg.length) {
|
||||
msg = msg +'\n';
|
||||
socket.emit('sendChatMessage', { touid:chatModal.touid, message:msg});
|
||||
socket.emit('api:chats.send', { touid:chatModal.touid, message:msg});
|
||||
chatModal.find('#chat-message-input').val('');
|
||||
}
|
||||
}
|
||||
@@ -146,10 +153,18 @@ define(['taskbar'], function(taskbar) {
|
||||
var date = new Date(parseInt(timestamp, 10));
|
||||
|
||||
chatContent.append('[' + date.toLocaleTimeString() + '] ' + message);
|
||||
scrollToBottom(chatContent);
|
||||
};
|
||||
|
||||
function scrollToBottom(chatContent) {
|
||||
chatContent.scrollTop(
|
||||
chatContent[0].scrollHeight - chatContent.height()
|
||||
);
|
||||
}
|
||||
|
||||
module.toggleNew = function(uuid, state) {
|
||||
taskbar.toggleNew(uuid, state);
|
||||
};
|
||||
|
||||
return module;
|
||||
});
|
||||
@@ -1,76 +1,444 @@
|
||||
define(['taskbar'], function(taskbar) {
|
||||
var composer = {
|
||||
initialized: false,
|
||||
active: undefined,
|
||||
taskbar: taskbar,
|
||||
posts: {},
|
||||
postContainer: undefined,
|
||||
posts: {}
|
||||
};
|
||||
|
||||
var uploadsInProgress = [];
|
||||
function allowed() {
|
||||
if(!(parseInt(app.uid, 10) > 0 || parseInt(config.allowGuestPosting, 10) === 1)) {
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
timeout: 5000,
|
||||
alert_id: 'post_error',
|
||||
title: 'Please Log In to Post',
|
||||
message: 'Posting is currently restricted to registered members only, click here to log in',
|
||||
clickfn: function() {
|
||||
ajaxify.go('login');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function createImagePlaceholder(img) {
|
||||
var text = $('.post-window textarea').val(),
|
||||
textarea = $('.post-window textarea'),
|
||||
imgText = "";
|
||||
composer.newTopic = function(cid) {
|
||||
if(allowed()) {
|
||||
push({
|
||||
cid: cid,
|
||||
title: '',
|
||||
body: '',
|
||||
modified: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
text += imgText;
|
||||
textarea.val(text + " ");
|
||||
uploadsInProgress.push(1);
|
||||
socket.emit("api:posts.uploadImage", img, function(err, data) {
|
||||
composer.newReply = function(tid, title, text) {
|
||||
if(allowed()) {
|
||||
push({
|
||||
tid: tid,
|
||||
title: title,
|
||||
body: text,
|
||||
modified: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var currentText = textarea.val();
|
||||
imgText = "";
|
||||
composer.editPost = function(pid) {
|
||||
if(allowed()) {
|
||||
socket.emit('api:composer.push', {
|
||||
pid: pid
|
||||
}, function(threadData) {
|
||||
push({
|
||||
pid: pid,
|
||||
title: threadData.title,
|
||||
body: threadData.body,
|
||||
modified: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(!err)
|
||||
textarea.val(currentText.replace(imgText, ""));
|
||||
else
|
||||
textarea.val(currentText.replace(imgText, ""));
|
||||
uploadsInProgress.pop();
|
||||
function push(post) {
|
||||
var uuid = utils.generateUUID();
|
||||
|
||||
taskbar.push('composer', uuid, {
|
||||
title: post.title ? post.title : 'New Topic',
|
||||
icon: post.picture
|
||||
});
|
||||
|
||||
composer.posts[uuid] = post;
|
||||
|
||||
composer.load(uuid);
|
||||
}
|
||||
|
||||
composer.load = function(post_uuid) {
|
||||
if($('#cmp-uuid-' + post_uuid).length) {
|
||||
composer.activateReposition(post_uuid);
|
||||
} else {
|
||||
composer.createNewComposer(post_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
composer.createNewComposer = function(post_uuid) {
|
||||
|
||||
templates.preload_template('composer', function() {
|
||||
|
||||
var composerTemplate = templates['composer'].parse({});
|
||||
composerTemplate = $(composerTemplate);
|
||||
|
||||
composerTemplate.attr('id', 'cmp-uuid-' + post_uuid);
|
||||
|
||||
$(document.body).append(composerTemplate);
|
||||
|
||||
composer.activateReposition(post_uuid);
|
||||
|
||||
var postContainer = $(composerTemplate[0]);
|
||||
|
||||
if(config.allowFileUploads || config.imgurClientIDSet)
|
||||
initializeFileReader(post_uuid);
|
||||
|
||||
var postData = composer.posts[post_uuid],
|
||||
titleEl = postContainer.find('.title'),
|
||||
bodyEl = postContainer.find('textarea');
|
||||
|
||||
if (parseInt(postData.tid) > 0) {
|
||||
titleEl.val('Replying to: ' + postData.title);
|
||||
titleEl.prop('readOnly', true);
|
||||
} else if (parseInt(postData.pid) > 0) {
|
||||
titleEl.val(postData.title);
|
||||
titleEl.prop('readOnly', true);
|
||||
socket.emit('api:composer.editCheck', postData.pid, function(editCheck) {
|
||||
if (editCheck.titleEditable) {
|
||||
postContainer.find('input').prop('readonly', false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
titleEl.val(postData.title);
|
||||
titleEl.prop('readOnly', false);
|
||||
}
|
||||
|
||||
bodyEl.val(postData.body);
|
||||
|
||||
postContainer.on('change', 'input, textarea', function() {
|
||||
composer.posts[post_uuid].modified = true;
|
||||
});
|
||||
|
||||
postContainer.on('click', '.action-bar button', function() {
|
||||
var action = $(this).attr('data-action');
|
||||
|
||||
switch(action) {
|
||||
case 'post':
|
||||
composer.post(post_uuid);
|
||||
break;
|
||||
case 'discard':
|
||||
if (composer.posts[post_uuid].modified) {
|
||||
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
|
||||
if (discard) {
|
||||
composer.discard(post_uuid);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
composer.discard(post_uuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
postContainer.on('click', '.formatting-bar span', function() {
|
||||
var postContentEl = postContainer.find('textarea'),
|
||||
iconClass = $(this).find('i').attr('class'),
|
||||
cursorEnd = postContentEl.val().length,
|
||||
selectionStart = postContentEl[0].selectionStart,
|
||||
selectionEnd = postContentEl[0].selectionEnd,
|
||||
selectionLength = selectionEnd - selectionStart;
|
||||
|
||||
|
||||
function insertIntoInput(element, value) {
|
||||
var start = postContentEl[0].selectionStart;
|
||||
element.val(element.val().slice(0, start) + value + element.val().slice(start, element.val().length));
|
||||
postContentEl[0].selectionStart = postContentEl[0].selectionEnd = start + value.length;
|
||||
}
|
||||
|
||||
switch(iconClass) {
|
||||
case 'fa fa-bold':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "**bolded text**");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '**' + postContentEl.val().slice(selectionStart, selectionEnd) + '**' + postContentEl.val().slice(selectionEnd));
|
||||
postContentEl[0].selectionStart = selectionStart + 2;
|
||||
postContentEl[0].selectionEnd = selectionEnd + 2;
|
||||
}
|
||||
break;
|
||||
case 'fa fa-italic':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "*italicised text*");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '*' + postContentEl.val().slice(selectionStart, selectionEnd) + '*' + postContentEl.val().slice(selectionEnd));
|
||||
postContentEl[0].selectionStart = selectionStart + 1;
|
||||
postContentEl[0].selectionEnd = selectionEnd + 1;
|
||||
}
|
||||
break;
|
||||
case 'fa fa-list':
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "\n\n* list item");
|
||||
break;
|
||||
case 'fa fa-link':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "[link text](link url)");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.val(postContentEl.val().slice(0, selectionStart) + '[' + postContentEl.val().slice(selectionStart, selectionEnd) + '](link url)' + postContentEl.val().slice(selectionEnd));
|
||||
postContentEl[0].selectionStart = selectionStart + selectionLength + 3;
|
||||
postContentEl[0].selectionEnd = selectionEnd + 11;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
postContainer.on('click', '.formatting-bar span .fa-picture-o, .formatting-bar span .fa-upload', function() {
|
||||
$('#files').click();
|
||||
});
|
||||
|
||||
$('#files').on('change', function(e) {
|
||||
var files = e.target.files;
|
||||
if(files) {
|
||||
for (var i=0; i<files.length; i++) {
|
||||
loadFile(post_uuid, files[i]);
|
||||
}
|
||||
}
|
||||
$('#fileForm')[0].reset();
|
||||
});
|
||||
|
||||
|
||||
var resizeActive = false,
|
||||
resizeCenterX = 0,
|
||||
resizeOffset = 0,
|
||||
resizeStart = function(e) {
|
||||
bodyRect = document.body.getBoundingClientRect();
|
||||
resizeRect = resizeEl.getBoundingClientRect();
|
||||
resizeCenterX = resizeRect.left + (resizeRect.width/2);
|
||||
resizeOffset = resizeCenterX - e.clientX;
|
||||
resizeSnaps.half = bodyRect.width / 2;
|
||||
resizeSnaps.none = bodyRect.width;
|
||||
resizeActive = true;
|
||||
|
||||
$(document.body).on('mousemove', resizeAction);
|
||||
document.body.addEventListener('touchmove', resizeTouchAction);
|
||||
},
|
||||
resizeStop = function() {
|
||||
resizeActive = false;
|
||||
$(document.body).off('mousemove', resizeAction);
|
||||
document.body.removeEventListener('touchmove', resizeTouchAction);
|
||||
},
|
||||
resizeTouchAction = function(e) {
|
||||
e.preventDefault();
|
||||
resizeAction(e.touches[0]);
|
||||
},
|
||||
resizeAction = function(e) {
|
||||
if (resizeActive) {
|
||||
position = (e.clientX + resizeOffset);
|
||||
if (Math.abs(position - resizeSnaps.half) <= 15) {
|
||||
// Half snap
|
||||
postContainer.css('width', resizeSnaps.half);
|
||||
resizeSavePosition(resizeSnaps.half);
|
||||
} else if (Math.abs(position - resizeSnaps.none) <= 30) {
|
||||
// Minimize snap
|
||||
postContainer.css('width', bodyRect.width - resizeSnaps.none + 15);
|
||||
resizeSavePosition(resizeSnaps.none);
|
||||
} else if (position <= 30) {
|
||||
// Full snap
|
||||
postContainer.css('width', bodyRect.width - 15);
|
||||
resizeSavePosition(bodyRect.width - 15);
|
||||
} else {
|
||||
// OH SNAP, NO SNAPS!
|
||||
postContainer.css('width', bodyRect.width - position);
|
||||
resizeSavePosition(bodyRect.width - position);
|
||||
}
|
||||
}
|
||||
},
|
||||
resizeSavePosition = function(px) {
|
||||
var percentage = px/bodyRect.width;
|
||||
localStorage.setItem('composer:resizePercentage', percentage);
|
||||
},
|
||||
resizeSnaps = {
|
||||
none: 0,
|
||||
half: 0,
|
||||
full: 0
|
||||
},
|
||||
resizeRect, bodyRect;
|
||||
|
||||
var resizeEl = postContainer.find('.resizer')[0];
|
||||
|
||||
resizeEl.addEventListener('mousedown', resizeStart);
|
||||
resizeEl.addEventListener('mouseup', resizeStop);
|
||||
resizeEl.addEventListener('touchstart', function(e) {
|
||||
e.preventDefault();
|
||||
resizeStart(e.touches[0]);
|
||||
});
|
||||
resizeEl.addEventListener('touchend', function(e) {
|
||||
e.preventDefault();
|
||||
resizeStop();
|
||||
});
|
||||
// .on('mousedown touchstart', resizeStart)
|
||||
// .on('mouseup touchend', resizeStop)
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
if (composer.active !== undefined) {
|
||||
composer.activateReposition(composer.active);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loadFile(file) {
|
||||
var reader = new FileReader(),
|
||||
dropDiv = $('.post-window .imagedrop'),
|
||||
uuid = dropDiv.parents('[data-uuid]').attr('data-uuid');
|
||||
composer.activateReposition = function(post_uuid) {
|
||||
|
||||
$(reader).on('loadend', function(e) {
|
||||
var bin = this.result;
|
||||
bin = bin.split(',')[1];
|
||||
if(composer.active && composer.active !== post_uuid) {
|
||||
composer.minimize(composer.active);
|
||||
}
|
||||
|
||||
var img = {
|
||||
name: file.name,
|
||||
data: bin
|
||||
};
|
||||
var percentage = localStorage.getItem('composer:resizePercentage'),
|
||||
bodyRect = document.body.getBoundingClientRect(),
|
||||
postContainer = $('#cmp-uuid-' + post_uuid);
|
||||
|
||||
createImagePlaceholder(img);
|
||||
composer.active = post_uuid;
|
||||
|
||||
dropDiv.hide();
|
||||
});
|
||||
if (percentage) {
|
||||
if (bodyRect.width >= 768) {
|
||||
postContainer.css('width', Math.floor(bodyRect.width * percentage) + 'px');
|
||||
} else {
|
||||
postContainer.css('width', '100%');
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
if(config.imgurClientIDSet) {
|
||||
postContainer.find('.upload-instructions').removeClass('hide');
|
||||
postContainer.find('.img-upload-btn').removeClass('hide');
|
||||
}
|
||||
|
||||
if(config.allowFileUploads) {
|
||||
postContainer.find('.file-upload-btn').removeClass('hide');
|
||||
}
|
||||
|
||||
postContainer.css('visibility', 'visible');
|
||||
|
||||
composer.focusElements(post_uuid);
|
||||
}
|
||||
|
||||
function initializeFileReader() {
|
||||
jQuery.event.props.push( "dataTransfer" );
|
||||
composer.focusElements = function(post_uuid) {
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
postData = composer.posts[post_uuid],
|
||||
titleEl = postContainer.find('.title'),
|
||||
bodyEl = postContainer.find('textarea');
|
||||
|
||||
if ((parseInt(postData.tid) || parseInt(postData.pid)) > 0) {
|
||||
bodyEl.focus();
|
||||
bodyEl.selectionStart = bodyEl.val().length;
|
||||
bodyEl.selectionEnd = bodyEl.val().length;
|
||||
} else if (parseInt(postData.cid) > 0) {
|
||||
titleEl.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
composer.post = function(post_uuid) {
|
||||
var postData = composer.posts[post_uuid],
|
||||
postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
titleEl = postContainer.find('.title'),
|
||||
bodyEl = postContainer.find('textarea');
|
||||
|
||||
titleEl.val(titleEl.val().trim());
|
||||
bodyEl.val(bodyEl.val().trim());
|
||||
|
||||
if(postData.uploadsInProgress && postData.uploadsInProgress.length) {
|
||||
return composerAlert('Still uploading', 'Please wait for uploads to complete.');
|
||||
} else if (titleEl.val().length < parseInt(config.minimumTitleLength, 10)) {
|
||||
return composerAlert('Title too short', 'Please enter a longer title. At least ' + config.minimumTitleLength+ ' characters.');
|
||||
} else if (titleEl.val().length > parseInt(config.maximumTitleLength, 10)) {
|
||||
return composerAlert('Title too long', 'Please enter a shorter title. Titles can\'t be longer than ' + config.maximumTitleLength + ' characters.');
|
||||
} else if (bodyEl.val().length < parseInt(config.minimumPostLength, 10)) {
|
||||
return composerAlert('Content too short', 'Please enter a longer post. At least ' + config.minimumPostLength + ' characters.');
|
||||
}
|
||||
|
||||
// Still here? Let's post.
|
||||
if (parseInt(postData.cid) > 0) {
|
||||
socket.emit('api:topics.post', {
|
||||
'title' : titleEl.val(),
|
||||
'content' : bodyEl.val(),
|
||||
'category_id' : postData.cid
|
||||
});
|
||||
} else if (parseInt(postData.tid) > 0) {
|
||||
socket.emit('api:posts.reply', {
|
||||
'topic_id' : postData.tid,
|
||||
'content' : bodyEl.val()
|
||||
});
|
||||
} else if (parseInt(postData.pid) > 0) {
|
||||
socket.emit('api:posts.edit', {
|
||||
pid: postData.pid,
|
||||
content: bodyEl.val(),
|
||||
title: titleEl.val()
|
||||
});
|
||||
}
|
||||
|
||||
composer.discard(post_uuid);
|
||||
}
|
||||
|
||||
function composerAlert(title, message) {
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
timeout: 2000,
|
||||
title: title,
|
||||
message: message,
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
composer.discard = function(post_uuid) {
|
||||
if (composer.posts[post_uuid]) {
|
||||
$('#cmp-uuid-' + post_uuid).remove();
|
||||
delete composer.posts[post_uuid];
|
||||
composer.active = undefined;
|
||||
taskbar.discard('composer', post_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
composer.minimize = function(post_uuid) {
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid);
|
||||
postContainer.css('visibility', 'hidden');
|
||||
composer.active = undefined;
|
||||
taskbar.minimize('composer', post_uuid);
|
||||
}
|
||||
|
||||
function initializeFileReader(post_uuid) {
|
||||
if(jQuery.event.props.indexOf('dataTransfer') === -1) {
|
||||
jQuery.event.props.push('dataTransfer');
|
||||
}
|
||||
|
||||
var draggingDocument = false;
|
||||
|
||||
if(window.FileReader) {
|
||||
var drop = $('.post-window .imagedrop'),
|
||||
textarea = $('.post-window textarea');
|
||||
var postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
drop = postContainer.find('.imagedrop'),
|
||||
textarea = postContainer.find('textarea');
|
||||
|
||||
$(document).on('dragstart', function(e) {
|
||||
$(document).off('dragstart').on('dragstart', function(e) {
|
||||
draggingDocument = true;
|
||||
}).on('dragend', function(e) {
|
||||
}).off('dragend').on('dragend', function(e) {
|
||||
draggingDocument = false;
|
||||
});
|
||||
|
||||
textarea.on('dragenter', function(e) {
|
||||
if(draggingDocument)
|
||||
if(draggingDocument) {
|
||||
return;
|
||||
}
|
||||
drop.css('top', textarea.position().top + 'px');
|
||||
drop.css('height', textarea.height());
|
||||
drop.css('line-height', textarea.height() + 'px');
|
||||
drop.show();
|
||||
|
||||
drop.on('dragleave', function(ev) {
|
||||
@@ -89,320 +457,85 @@ define(['taskbar'], function(taskbar) {
|
||||
|
||||
drop.on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
var uuid = drop.parents('[data-uuid]').attr('data-uuid'),
|
||||
dt = e.dataTransfer,
|
||||
var dt = e.dataTransfer,
|
||||
files = dt.files;
|
||||
|
||||
for (var i=0; i<files.length; i++) {
|
||||
loadFile(files[i]);
|
||||
loadFile(post_uuid, files[i]);
|
||||
}
|
||||
|
||||
if(!files.length)
|
||||
if(!files.length) {
|
||||
drop.hide();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
composer.init = function() {
|
||||
if (!composer.initialized) {
|
||||
var taskbar = document.getElementById('taskbar');
|
||||
function loadFile(post_uuid, file) {
|
||||
var reader = new FileReader(),
|
||||
dropDiv = $('#cmp-uuid-' + post_uuid).find('.imagedrop');
|
||||
|
||||
composer.postContainer = document.createElement('div');
|
||||
composer.postContainer.className = 'post-window row';
|
||||
composer.postContainer.innerHTML = '<div class="col-md-5">' +
|
||||
'<input type="text" tabIndex="1" placeholder="Enter your topic title here..." />' +
|
||||
'<div class="btn-toolbar formatting-bar">' +
|
||||
'<div class="btn-group">' +
|
||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-bold"></i></span>' +
|
||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-italic"></i></span>' +
|
||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-list"></i></span>' +
|
||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-link"></i></span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<textarea tabIndex="2"></textarea>' +
|
||||
'<div class="imagedrop"><div>Drag and Drop Images Here</div></div>'+
|
||||
'<div class="btn-toolbar action-bar">' +
|
||||
'<div class="btn-group" style="float: right; margin-right: -8px">' +
|
||||
'<button data-action="minimize" class="btn hidden-xs" tabIndex="4"><i class="icon-download-alt"></i> Minimize</button>' +
|
||||
'<button class="btn" data-action="discard" tabIndex="5"><i class="icon-remove"></i> Discard</button>' +
|
||||
'<button data-action="post" class="btn" tabIndex="3"><i class="icon-ok"></i> Submit</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
$(reader).on('loadend', function(e) {
|
||||
var regex = /^data:.*;base64,(.*)$/;
|
||||
var matches = this.result.match(regex);
|
||||
|
||||
document.body.insertBefore(composer.postContainer, taskbar);
|
||||
var fileData = {
|
||||
name: file.name,
|
||||
data: matches[1]
|
||||
};
|
||||
|
||||
if(config.imgurClientIDSet)
|
||||
initializeFileReader();
|
||||
dropDiv.hide();
|
||||
|
||||
socket.on('api:composer.push', function(threadData) {
|
||||
if (!threadData.error) {
|
||||
var uuid = utils.generateUUID();
|
||||
|
||||
composer.taskbar.push('composer', uuid, {
|
||||
title: (!threadData.cid ? (threadData.title || '') : 'New Topic'),
|
||||
icon: threadData.picture
|
||||
});
|
||||
|
||||
composer.posts[uuid] = {
|
||||
tid: threadData.tid,
|
||||
cid: threadData.cid,
|
||||
pid: threadData.pid,
|
||||
title: threadData.title || '',
|
||||
body: threadData.body || '',
|
||||
modified: false
|
||||
};
|
||||
composer.load(uuid);
|
||||
} else {
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
timeout: 5000,
|
||||
alert_id: 'post_error',
|
||||
title: 'Please Log In to Post',
|
||||
message: 'Posting is currently restricted to registered members only, click here to log in',
|
||||
clickfn: function() {
|
||||
ajaxify.go('login');
|
||||
}
|
||||
});
|
||||
if(file.type.match('image.*')) {
|
||||
uploadFile('api:posts.uploadImage', post_uuid, fileData);
|
||||
} else {
|
||||
if(file.size > parseInt(config.maximumFileSize, 10) * 1024) {
|
||||
return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs');
|
||||
}
|
||||
});
|
||||
uploadFile('api:posts.uploadFile', post_uuid, fileData);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:composer.editCheck', function(editCheck) {
|
||||
if (editCheck.titleEditable === true) composer.postContainer.querySelector('input').readOnly = false;
|
||||
});
|
||||
|
||||
// Post Window events
|
||||
var jPostContainer = $(composer.postContainer),
|
||||
postContentEl = composer.postContainer.querySelector('textarea');
|
||||
|
||||
jPostContainer.on('change', 'input, textarea', function() {
|
||||
var uuid = $(this).parents('.post-window')[0].getAttribute('data-uuid');
|
||||
if (this.nodeName === 'INPUT') composer.posts[uuid].title = this.value;
|
||||
else if (this.nodeName === 'TEXTAREA') composer.posts[uuid].body = this.value;
|
||||
|
||||
// Mark this post window as having been changed
|
||||
composer.posts[uuid].modified = true;
|
||||
});
|
||||
|
||||
jPostContainer.on('click', '.action-bar button', function() {
|
||||
var action = this.getAttribute('data-action'),
|
||||
uuid = $(this).parents('.post-window').attr('data-uuid');
|
||||
switch(action) {
|
||||
case 'post': composer.post(uuid); break;
|
||||
case 'minimize': composer.minimize(uuid); break;
|
||||
case 'discard':
|
||||
if (composer.posts[uuid].modified) {
|
||||
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
|
||||
if (discard) composer.discard(uuid);
|
||||
});
|
||||
} else {
|
||||
composer.discard(uuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
jPostContainer.on('click', '.formatting-bar span', function() {
|
||||
var iconClass = this.querySelector('i').className,
|
||||
cursorEnd = postContentEl.value.length,
|
||||
selectionStart = postContentEl.selectionStart,
|
||||
selectionEnd = postContentEl.selectionEnd,
|
||||
selectionLength = selectionEnd - selectionStart;
|
||||
|
||||
function insertIntoInput(element, value) {
|
||||
var start = postContentEl.selectionStart;
|
||||
element.value = element.value.slice(0, start) + value + element.value.slice(start, element.value.length);
|
||||
postContentEl.selectionStart = postContentEl.selectionEnd = start + value.length;
|
||||
}
|
||||
|
||||
switch(iconClass) {
|
||||
case 'icon-bold':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "**bolded text**");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '**' + postContentEl.value.slice(selectionStart, selectionEnd) + '**' + postContentEl.value.slice(selectionEnd);
|
||||
postContentEl.selectionStart = selectionStart + 2;
|
||||
postContentEl.selectionEnd = selectionEnd + 2;
|
||||
}
|
||||
break;
|
||||
case 'icon-italic':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "*italicised text*");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '*' + postContentEl.value.slice(selectionStart, selectionEnd) + '*' + postContentEl.value.slice(selectionEnd);
|
||||
postContentEl.selectionStart = selectionStart + 1;
|
||||
postContentEl.selectionEnd = selectionEnd + 1;
|
||||
}
|
||||
break;
|
||||
case 'icon-list':
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "\n\n* list item");
|
||||
break;
|
||||
case 'icon-link':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
insertIntoInput(postContentEl, "[link text](link url)");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '[' + postContentEl.value.slice(selectionStart, selectionEnd) + '](link url)' + postContentEl.value.slice(selectionEnd);
|
||||
postContentEl.selectionStart = selectionStart + selectionLength + 3;
|
||||
postContentEl.selectionEnd = selectionEnd + 11;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
if (composer.active !== undefined) composer.reposition(composer.active);
|
||||
});
|
||||
|
||||
composer.initialized = true;
|
||||
}
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
composer.push = function(tid, cid, pid, text) {
|
||||
socket.emit('api:composer.push', {
|
||||
tid: tid, // Replying
|
||||
cid: cid, // Posting
|
||||
pid: pid, // Editing
|
||||
body: text // Predefined text
|
||||
|
||||
function uploadFile(method, post_uuid, img) {
|
||||
var linkStart = method === 'api:posts.uploadImage' ? '!' : '',
|
||||
postContainer = $('#cmp-uuid-' + post_uuid),
|
||||
textarea = postContainer.find('textarea'),
|
||||
text = textarea.val(),
|
||||
imgText = linkStart + '[' + img.name + '](uploading...)';
|
||||
|
||||
text += imgText;
|
||||
textarea.val(text + " ");
|
||||
|
||||
if(!composer.posts[post_uuid].uploadsInProgress) {
|
||||
composer.posts[post_uuid].uploadsInProgress = [];
|
||||
}
|
||||
|
||||
composer.posts[post_uuid].uploadsInProgress.push(1);
|
||||
|
||||
socket.emit(method, img, function(err, data) {
|
||||
|
||||
var currentText = textarea.val();
|
||||
|
||||
if(err) {
|
||||
textarea.val(currentText.replace(imgText, linkStart + '[' + img.name + '](upload error)'));
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
textarea.val(currentText.replace(imgText, linkStart + '[' + data.name + '](' + data.url + ')'));
|
||||
|
||||
composer.posts[post_uuid].uploadsInProgress.pop();
|
||||
});
|
||||
}
|
||||
|
||||
composer.load = function(post_uuid) {
|
||||
var post_data = composer.posts[post_uuid],
|
||||
titleEl = composer.postContainer.querySelector('input'),
|
||||
bodyEl = composer.postContainer.querySelector('textarea');
|
||||
|
||||
composer.reposition(post_uuid);
|
||||
composer.active = post_uuid;
|
||||
|
||||
composer.postContainer.setAttribute('data-uuid', post_uuid);
|
||||
if (parseInt(post_data.tid) > 0) {
|
||||
titleEl.value = 'Replying to: ' + post_data.title;
|
||||
titleEl.readOnly = true;
|
||||
} else if (parseInt(post_data.pid) > 0) {
|
||||
titleEl.value = post_data.title;
|
||||
titleEl.readOnly = true;
|
||||
socket.emit('api:composer.editCheck', post_data.pid);
|
||||
} else {
|
||||
titleEl.value = post_data.title;
|
||||
titleEl.readOnly = false;
|
||||
}
|
||||
bodyEl.value = post_data.body;
|
||||
|
||||
|
||||
// Direct user focus to the correct element
|
||||
if ((parseInt(post_data.tid) || parseInt(post_data.pid)) > 0) {
|
||||
bodyEl.focus();
|
||||
bodyEl.selectionStart = bodyEl.value.length;
|
||||
bodyEl.selectionEnd = bodyEl.value.length;
|
||||
} else if (parseInt(post_data.cid) > 0) {
|
||||
titleEl.focus();
|
||||
}
|
||||
}
|
||||
|
||||
composer.reposition = function(post_uuid) {
|
||||
var postWindowEl = composer.postContainer.querySelector('.col-md-5'),
|
||||
taskbarBtn = document.querySelector('#taskbar [data-uuid="' + post_uuid + '"]'),
|
||||
btnRect = taskbarBtn.getBoundingClientRect(),
|
||||
taskbarRect = document.getElementById('taskbar').getBoundingClientRect(),
|
||||
windowRect, leftPos;
|
||||
|
||||
composer.postContainer.style.display = 'block';
|
||||
windowRect = postWindowEl.getBoundingClientRect();
|
||||
leftPos = btnRect.left + btnRect.width - windowRect.width;
|
||||
postWindowEl.style.left = (leftPos > 0 ? leftPos : 0) + 'px';
|
||||
composer.postContainer.style.bottom = taskbarRect.height + "px";
|
||||
}
|
||||
|
||||
composer.post = function(post_uuid) {
|
||||
// Check title and post length
|
||||
var postData = composer.posts[post_uuid],
|
||||
titleEl = composer.postContainer.querySelector('input'),
|
||||
bodyEl = composer.postContainer.querySelector('textarea');
|
||||
|
||||
titleEl.value = titleEl.value.trim();
|
||||
bodyEl.value = bodyEl.value.trim();
|
||||
|
||||
if(uploadsInProgress.length) {
|
||||
return app.alert({
|
||||
type: 'warning',
|
||||
timeout: 2000,
|
||||
title: 'Still uploading',
|
||||
message: "Please wait for uploads to complete.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
if (titleEl.value.length < config.minimumTitleLength) {
|
||||
return app.alert({
|
||||
type: 'danger',
|
||||
timeout: 2000,
|
||||
title: 'Title too short',
|
||||
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
if (bodyEl.value.length < config.minimumPostLength) {
|
||||
return app.alert({
|
||||
type: 'danger',
|
||||
timeout: 2000,
|
||||
title: 'Content too short',
|
||||
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
// Still here? Let's post.
|
||||
if (parseInt(postData.cid) > 0) {
|
||||
socket.emit('api:topics.post', {
|
||||
'title' : titleEl.value,
|
||||
'content' : bodyEl.value,
|
||||
'category_id' : postData.cid
|
||||
});
|
||||
} else if (parseInt(postData.tid) > 0) {
|
||||
socket.emit('api:posts.reply', {
|
||||
'topic_id' : postData.tid,
|
||||
'content' : bodyEl.value
|
||||
});
|
||||
} else if (parseInt(postData.pid) > 0) {
|
||||
socket.emit('api:posts.edit', {
|
||||
pid: postData.pid,
|
||||
content: bodyEl.value,
|
||||
title: titleEl.value
|
||||
});
|
||||
}
|
||||
|
||||
composer.discard(post_uuid);
|
||||
}
|
||||
|
||||
composer.discard = function(post_uuid) {
|
||||
if (composer.posts[post_uuid]) {
|
||||
$(composer.postContainer).find('.imagedrop').hide();
|
||||
delete composer.posts[post_uuid];
|
||||
uploadsInProgress.length = 0;
|
||||
composer.minimize();
|
||||
taskbar.discard('composer', post_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
composer.minimize = function(uuid) {
|
||||
composer.postContainer.style.display = 'none';
|
||||
composer.active = undefined;
|
||||
taskbar.minimize('composer', uuid);
|
||||
}
|
||||
|
||||
composer.init();
|
||||
|
||||
return {
|
||||
push: composer.push,
|
||||
newTopic: composer.newTopic,
|
||||
newReply: composer.newReply,
|
||||
editPost: composer.editPost,
|
||||
load: composer.load,
|
||||
minimize: composer.minimize
|
||||
};
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
define(function() {
|
||||
var mobileMenu = {};
|
||||
|
||||
|
||||
var categories = null,
|
||||
overlay = null,
|
||||
menuBtn = null,
|
||||
postBtn = null,
|
||||
initialized = false;
|
||||
|
||||
|
||||
function loadCategories(callback) {
|
||||
if (categories) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
jQuery.getJSON(RELATIVE_PATH+'/api/home', function(data) {
|
||||
categories = data.categories;
|
||||
initialized = true;
|
||||
|
||||
if (callback) {
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function displayCategories() {
|
||||
var baseIcon = document.createElement('a'),
|
||||
baseImage = document.createElement('i'),
|
||||
baseName = document.createElement('span');
|
||||
|
||||
baseIcon.className = 'mobile-menu-icon';
|
||||
|
||||
for (var i=0, ii=categories.length; i<ii; i++) {
|
||||
var icon = baseIcon.cloneNode(true),
|
||||
image = baseImage.cloneNode(true),
|
||||
name = baseName.cloneNode(true);
|
||||
|
||||
var category = categories[i];
|
||||
|
||||
image.className = category.icon + ' icon-3x';
|
||||
name.innerHTML = '<br />' + category.name;
|
||||
icon.appendChild(image);
|
||||
icon.appendChild(name);
|
||||
icon.src = 'category/' + category.slug;
|
||||
|
||||
icon.onclick = function() {
|
||||
jQuery('.mobile-menu-icon').toggleClass('menu-visible');
|
||||
|
||||
setTimeout(function() {
|
||||
jQuery(overlay).toggleClass('menu-visible');
|
||||
}, 200);
|
||||
|
||||
ajaxify.go(this.src);
|
||||
}
|
||||
|
||||
overlay.appendChild(icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function animateIcons() {
|
||||
jQuery(overlay).toggleClass('menu-visible');
|
||||
setTimeout(function() {
|
||||
jQuery('.mobile-menu-icon').toggleClass('menu-visible');
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
||||
mobileMenu.onNavigate = function() {
|
||||
if (initialized == false) return false;
|
||||
|
||||
var cid = templates.get('category_id'),
|
||||
tid = templates.get('topic_id');
|
||||
|
||||
if (cid) {
|
||||
postBtn.style.display = 'inline-block';
|
||||
postBtn.onclick = function() {
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(0, cid);
|
||||
});
|
||||
};
|
||||
postBtn.children[0].className = 'icon-plus icon-2x';
|
||||
} else if (tid) {
|
||||
postBtn.style.display = 'inline-block';
|
||||
postBtn.onclick = function() {
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(tid);
|
||||
});
|
||||
};
|
||||
postBtn.children[0].className = 'icon-reply icon-2x'
|
||||
} else {
|
||||
postBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
mobileMenu.init = function() {
|
||||
return; // disabling until this can be pluginified.
|
||||
overlay = overlay || document.getElementById('mobile-menu-overlay');
|
||||
menuBtn = menuBtn || document.getElementById('mobile-menu-btn');
|
||||
postBtn = postBtn || document.getElementById('mobile-post-btn');
|
||||
|
||||
menuBtn.onclick = function() {
|
||||
animateIcons();
|
||||
}
|
||||
|
||||
loadCategories(function() {
|
||||
displayCategories();
|
||||
mobileMenu.onNavigate();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
init: mobileMenu.init,
|
||||
onNavigate: mobileMenu.onNavigate
|
||||
}
|
||||
});
|
||||
3
public/src/modules/string.js
Normal file
3
public/src/modules/string.js
Normal file
File diff suppressed because one or more lines are too long
@@ -25,6 +25,8 @@ define(function() {
|
||||
if (_btn.className.indexOf('active') === -1) {
|
||||
taskbar.minimizeAll();
|
||||
module.load(uuid);
|
||||
taskbar.toggleNew(uuid, false);
|
||||
app.alternatingTitle('');
|
||||
|
||||
// Highlight the button
|
||||
$(taskbar.tasklist).removeClass('active');
|
||||
@@ -69,7 +71,7 @@ define(function() {
|
||||
'</a>';
|
||||
btnEl.setAttribute('data-module', module);
|
||||
btnEl.setAttribute('data-uuid', uuid);
|
||||
btnEl.className = options.state || 'active';
|
||||
btnEl.className = options.state !== undefined ? options.state : 'active';
|
||||
|
||||
if (!options.state || options.state === 'active') taskbar.minimizeAll();
|
||||
taskbar.tasklist.appendChild(btnEl);
|
||||
@@ -82,14 +84,27 @@ define(function() {
|
||||
},
|
||||
minimizeAll: function() {
|
||||
$(taskbar.tasklist.querySelectorAll('.active')).removeClass('active');
|
||||
},
|
||||
toggleNew: function(uuid, state) {
|
||||
var btnEl = $(taskbar.tasklist.querySelector('[data-uuid="' + uuid + '"]'));
|
||||
btnEl.toggleClass('new', state);
|
||||
},
|
||||
updateActive: function(uuid) {
|
||||
var tasks = $(taskbar.tasklist).find('li');
|
||||
tasks.removeClass('active');
|
||||
tasks.filter('[data-uuid="' + uuid + '"]').addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
if (!taskbar.initialized) taskbar.init();
|
||||
if (!taskbar.initialized) {
|
||||
taskbar.init();
|
||||
}
|
||||
|
||||
return {
|
||||
push: taskbar.push,
|
||||
discard: taskbar.discard,
|
||||
minimize: taskbar.minimize
|
||||
minimize: taskbar.minimize,
|
||||
toggleNew: taskbar.toggleNew,
|
||||
updateActive: taskbar.updateActive
|
||||
}
|
||||
});
|
||||
@@ -2,12 +2,13 @@ define(function() {
|
||||
|
||||
var module = {};
|
||||
|
||||
module.open = function(route, callback) {
|
||||
module.open = function(route, params, callback) {
|
||||
$('#upload-picture-modal').modal('show').removeClass('hide');
|
||||
module.hideAlerts();
|
||||
|
||||
$('#uploadForm')[0].reset();
|
||||
$('#uploadForm').attr('action', route);
|
||||
$('#uploadForm').find('#params').val(JSON.stringify(params));
|
||||
|
||||
$('#pictureUploadSubmitBtn').off('click').on('click', function() {
|
||||
$('#uploadForm').submit();
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
templates.prepare = function (raw_tpl, data) {
|
||||
templates.prepare = function (raw_tpl) {
|
||||
var template = {};
|
||||
template.html = raw_tpl;
|
||||
template.parse = parse;
|
||||
@@ -78,7 +78,9 @@
|
||||
global.templates[file] = new template;
|
||||
|
||||
loaded--;
|
||||
if (loaded == 0) templates.ready();
|
||||
if (loaded === 0) {
|
||||
templates.ready();
|
||||
}
|
||||
});
|
||||
}(templatesToLoad[t]));
|
||||
}
|
||||
@@ -122,12 +124,37 @@
|
||||
return '';
|
||||
}
|
||||
|
||||
templates.preload_template = function(tpl_name, callback) {
|
||||
|
||||
if(templates[tpl_name]) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
// TODO: This should be "load_template", and the current load_template
|
||||
// should be named something else
|
||||
// TODO: The "Date.now()" in the line below is only there for development purposes.
|
||||
// It should be removed at some point.
|
||||
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_name + '.tpl?v=' + Date.now(), function (html) {
|
||||
var template = function () {
|
||||
this.toString = function () {
|
||||
return this.html;
|
||||
};
|
||||
}
|
||||
|
||||
template.prototype.parse = parse;
|
||||
template.prototype.html = String(html);
|
||||
template.prototype.blocks = {};
|
||||
|
||||
templates[tpl_name] = new template;
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
templates.load_template = function (callback, url, template) {
|
||||
var location = document.location || window.location,
|
||||
api_url = (url === '' || url === '/') ? 'home' : url,
|
||||
tpl_url = templates.get_custom_map(api_url.split('?')[0]),
|
||||
trimmed = api_url;
|
||||
tpl_url = templates.get_custom_map(api_url.split('?')[0]);
|
||||
|
||||
if (!tpl_url) {
|
||||
tpl_url = templates.getTemplateNameFromUrl(api_url);
|
||||
@@ -138,19 +165,7 @@
|
||||
var timestamp = new Date().getTime(); //debug
|
||||
|
||||
if (!templates[tpl_url]) {
|
||||
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_url + '.tpl?v=' + timestamp, function (html) {
|
||||
var template = function () {
|
||||
this.toString = function () {
|
||||
return this.html;
|
||||
};
|
||||
}
|
||||
|
||||
template.prototype.parse = parse;
|
||||
template.prototype.html = String(html);
|
||||
template.prototype.blocks = {};
|
||||
|
||||
templates[tpl_url] = new template;
|
||||
|
||||
templates.preload_template(tpl_url, function() {
|
||||
parse_template();
|
||||
});
|
||||
} else {
|
||||
@@ -167,11 +182,13 @@
|
||||
template_data = data;
|
||||
parse_template();
|
||||
}).fail(function (data) {
|
||||
if(data && data.status == 404) {
|
||||
ajaxify.go('404');
|
||||
return;
|
||||
if (data && data.status == 404) {
|
||||
return ajaxify.go('404');
|
||||
} else if (data && data.status === 403) {
|
||||
return ajaxify.go('403');
|
||||
} else {
|
||||
app.alertError(data.responseJSON.error);
|
||||
}
|
||||
app.alertError("Can't load template data!");
|
||||
});
|
||||
|
||||
function parse_template() {
|
||||
@@ -239,7 +256,7 @@
|
||||
}
|
||||
|
||||
function makeConditionalRegex(block) {
|
||||
return new RegExp("<!--[\\s]*IF " + block + "[\\s]*-->[\\s\\S]*<!--[\\s]*ENDIF " + block + "[\\s]*-->", 'g');
|
||||
return new RegExp("<!--[\\s]*IF " + block + "[\\s]*-->([\\s\\S]*?)<!--[\\s]*ENDIF " + block + "[\\s]*-->", 'g');
|
||||
}
|
||||
|
||||
function getBlock(regex, block, template) {
|
||||
@@ -248,9 +265,12 @@
|
||||
|
||||
if (self.blocks && block !== undefined) self.blocks[block] = data[0];
|
||||
|
||||
var begin = new RegExp("(\r\n)*<!-- BEGIN " + block + " -->(\r\n)*", "g"),
|
||||
end = new RegExp("(\r\n)*<!-- END " + block + " -->(\r\n)*", "g"),
|
||||
|
||||
data = data[0]
|
||||
.replace("<!--[\\s]*BEGIN " + block + "[\\s]*-->", "")
|
||||
.replace("<!--[\\s]*END " + block + "[\\s]*-->", "");
|
||||
.replace(begin, "")
|
||||
.replace(end, "");
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -262,7 +282,7 @@
|
||||
var template = this.html,
|
||||
regex, block;
|
||||
|
||||
return (function parse(data, namespace, template) {
|
||||
return (function parse(data, namespace, template, blockInfo) {
|
||||
if (!data || data.length == 0) {
|
||||
template = '';
|
||||
}
|
||||
@@ -289,44 +309,51 @@
|
||||
result = "";
|
||||
|
||||
do {
|
||||
result += parse(data[d][i], namespace, block);
|
||||
result += parse(data[d][i], namespace, block, {iterator: i, total: numblocks});
|
||||
} while (i++ < numblocks);
|
||||
|
||||
namespace = namespace.replace(d + '.', '');
|
||||
template = setBlock(regex, result, template);
|
||||
} else if (data[d] instanceof Object) {
|
||||
namespace += d + '.';
|
||||
|
||||
regex = makeRegex(d),
|
||||
block = getBlock(regex, namespace, template)
|
||||
if (block == null) continue;
|
||||
|
||||
block = parse(data[d], namespace, block);
|
||||
template = setBlock(regex, block, template);
|
||||
template = parse(data[d], d + '.', template);
|
||||
} else {
|
||||
var conditional = makeConditionalRegex(namespace + d);
|
||||
function checkConditional(key, value) {
|
||||
var conditional = makeConditionalRegex(key),
|
||||
matches = template.match(conditional);
|
||||
|
||||
var conditionalBlock = conditional.exec(template);
|
||||
|
||||
if (conditionalBlock !== null) {
|
||||
conditionalBlock = conditionalBlock[0].split(/<!-- ELSE -->/);
|
||||
|
||||
if (conditionalBlock[1]) {
|
||||
// there is an else statement
|
||||
if (!data[d]) {
|
||||
template = template.replace(conditional, conditionalBlock[1]);
|
||||
} else {
|
||||
template = template.replace(conditional, conditionalBlock[0]);
|
||||
}
|
||||
|
||||
} else {
|
||||
// regular if
|
||||
if (!data[d]) {
|
||||
template = template.replace(conditional, '');
|
||||
if (matches !== null) {
|
||||
for (var i = 0, ii = matches.length; i < ii; i++) {
|
||||
var conditionalBlock = matches[i].split(/<!-- ELSE -->/);
|
||||
|
||||
if (conditionalBlock[1]) {
|
||||
// there is an else statement
|
||||
if (!value) {
|
||||
template = template.replace(matches[i], conditionalBlock[1].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
|
||||
} else {
|
||||
template = template.replace(matches[i], conditionalBlock[0].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
|
||||
}
|
||||
} else {
|
||||
// regular if statement
|
||||
if (!value) {
|
||||
template = template.replace(matches[i], '');
|
||||
} else {
|
||||
template = template.replace(matches[i], matches[i].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkConditional(namespace + d, data[d]);
|
||||
checkConditional('!' + namespace + d, !data[d]);
|
||||
|
||||
if (blockInfo) {
|
||||
checkConditional('@first', blockInfo.iterator === 0);
|
||||
checkConditional('!@first', blockInfo.iterator !== 0);
|
||||
checkConditional('@last', blockInfo.iterator === blockInfo.total);
|
||||
checkConditional('!@last', blockInfo.iterator !== blockInfo.total);
|
||||
}
|
||||
|
||||
template = replace(namespace + d, data[d], template);
|
||||
}
|
||||
}
|
||||
@@ -335,8 +362,12 @@
|
||||
if (namespace) {
|
||||
var regex = new RegExp("{" + namespace + "[\\s\\S]*?}", 'g');
|
||||
template = template.replace(regex, '');
|
||||
namespace = '';
|
||||
}
|
||||
|
||||
// clean up all undefined conditionals
|
||||
template = template.replace(/<!-- IF([^@]*?)ENDIF([^@]*?)-->/gi, '');
|
||||
|
||||
return template;
|
||||
|
||||
})(data, "", template);
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
var parsedKey = keys[key].replace('[[', '').replace(']]', '').split(':');
|
||||
if (!(parsedKey[0] && parsedKey[1])) continue;
|
||||
|
||||
|
||||
var languageFile = parsedKey[0];
|
||||
parsedKey = parsedKey[1].split(',')[0];
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(function(module) {
|
||||
'use strict';
|
||||
|
||||
var utils, fs;
|
||||
var utils, fs, XRegExp;
|
||||
|
||||
if ('undefined' === typeof window) {
|
||||
fs = require('fs');
|
||||
XRegExp = require('xregexp').XRegExp;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +57,10 @@
|
||||
var now = +new Date(),
|
||||
difference = now - Math.floor(parseFloat(timestamp));
|
||||
|
||||
if(difference < 0) {
|
||||
difference = 0;
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 1000);
|
||||
|
||||
if (difference < 60) {
|
||||
@@ -88,19 +93,13 @@
|
||||
|
||||
//http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
|
||||
slugify: function(str) {
|
||||
var invalidChars = XRegExp('[^\\p{L} 0-9\-]', 'g');
|
||||
|
||||
str = str.replace(/^\s+|\s+$/g, ''); // trim
|
||||
str = str.toLowerCase();
|
||||
|
||||
// remove accents, swap ñ for n, etc
|
||||
var from = "àáäâèéëêìíïîıòóöôùúüûñçşğ·/_,:;";
|
||||
var to = "aaaaeeeeiiiiioooouuuuncsg------";
|
||||
for (var i = 0, l = from.length; i < l; i++) {
|
||||
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
||||
}
|
||||
|
||||
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
||||
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
||||
.replace(/-+/g, '-'); // collapse dashes
|
||||
str = XRegExp.replace(str, invalidChars, '');
|
||||
str = str.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
||||
str = str.replace(/-+/g, '-'); // collapse dashes
|
||||
|
||||
return str;
|
||||
},
|
||||
@@ -119,18 +118,6 @@
|
||||
isPasswordValid: function(password) {
|
||||
return password && password.indexOf(' ') === -1;
|
||||
},
|
||||
|
||||
// Blatently stolen from: http://phpjs.org/functions/strip_tags/
|
||||
'strip_tags': function(input, allowed) {
|
||||
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
||||
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
||||
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
||||
|
||||
return input.replace(commentsAndPhpTags, '').replace(tags, function($0, $1) {
|
||||
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
||||
});
|
||||
},
|
||||
|
||||
buildMetaTags: function(tagsArr) {
|
||||
var tags = '',
|
||||
tag;
|
||||
@@ -169,52 +156,23 @@
|
||||
return tags;
|
||||
},
|
||||
|
||||
refreshTitle: function(url) {
|
||||
if (!url) {
|
||||
var a = document.createElement('a');
|
||||
a.href = document.location;
|
||||
url = a.pathname.slice(1);
|
||||
}
|
||||
var notificationIcon;
|
||||
|
||||
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
|
||||
document.title = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
|
||||
notificationIcon = notificationIcon || document.querySelector('.notifications a i');
|
||||
if (numNotifications > 0 && notificationIcon) {
|
||||
notificationIcon.className = 'icon-circle active';
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.getJSON(RELATIVE_PATH + '/api/unread/total', function(data) {
|
||||
var badge = jQuery('#numUnreadBadge');
|
||||
badge.html(data.count > 20 ? '20+' : data.count);
|
||||
|
||||
if (data.count > 0) {
|
||||
badge
|
||||
.removeClass('badge-inverse')
|
||||
.addClass('badge-important');
|
||||
} else {
|
||||
badge
|
||||
.removeClass('badge-important')
|
||||
.addClass('badge-inverse');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
isRelativeUrl: function(url) {
|
||||
var firstChar = url.slice(0, 1);
|
||||
return (firstChar === '.' || firstChar === '/');
|
||||
},
|
||||
|
||||
makeNumberHumanReadable: function(num) {
|
||||
num = parseInt(num, 10);
|
||||
if (num > 999999) {
|
||||
return (num / 1000000).toFixed(1) + 'm';
|
||||
var n = parseInt(num, 10);
|
||||
if(!n) {
|
||||
return num;
|
||||
}
|
||||
else if(num > 999) {
|
||||
return (num / 1000).toFixed(1) + 'k';
|
||||
if (n > 999999) {
|
||||
return (n / 1000000).toFixed(1) + 'm';
|
||||
}
|
||||
return num;
|
||||
else if(n > 999) {
|
||||
return (n / 1000).toFixed(1) + 'k';
|
||||
}
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
5
public/templates/500.tpl
Normal file
5
public/templates/500.tpl
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="alert alert-danger">
|
||||
<strong>[[global:500.title]]</strong>
|
||||
<p>[[global:500.message]]</p>
|
||||
<p>{errorMessage}</p>
|
||||
</div>
|
||||
@@ -13,69 +13,96 @@
|
||||
<img src="{picture}" class="user-profile-picture img-thumbnail"/>
|
||||
</div>
|
||||
<div class="account-online-status">
|
||||
<span><i class="icon-circle-blank"></i> <span>offline</span></span>
|
||||
<span><i class="fa fa-circle-o"></i> <span>[[user:offline]]</span></span>
|
||||
</div>
|
||||
<div class="{show_banned}">
|
||||
<span class="label label-danger">banned</span>
|
||||
<!-- IF banned -->
|
||||
<div>
|
||||
<span class="label label-danger">[[user:banned]]</span>
|
||||
</div>
|
||||
<!-- ENDIF banned -->
|
||||
<div>
|
||||
<a id="chat-btn" href="#" class="btn btn-default hide">Chat</a>
|
||||
</div>
|
||||
<div id="user-actions">
|
||||
<a id="follow-btn" href="#" class="btn btn-default">Follow</a>
|
||||
<a id="unfollow-btn" href="#" class="btn btn-default">Unfollow</a>
|
||||
<a id="follow-btn" href="#" class="btn btn-default hide">Follow</a>
|
||||
<a id="unfollow-btn" href="#" class="btn btn-default hide">Unfollow</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="inline-block">
|
||||
<div class="account-bio-block">
|
||||
<span class="account-bio-label">email</span><i class="icon-eye-close {emailClass}" title="Email hidden"></i>
|
||||
<span class="account-bio-label">[[user:email]]</span><i class="fa fa-eye-slash {emailClass}" title="[[user:email_hidden]]"></i>
|
||||
<!-- IF email -->
|
||||
<span>{email}</span>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-eye-slash" title="[[user:email_hidden]]"></i> [[user:hidden]]
|
||||
<!-- ENDIF email -->
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">full name</span>
|
||||
|
||||
<!-- IF fullname -->
|
||||
<span class="account-bio-label">[[user:fullname]]</span>
|
||||
<span>{fullname}</span>
|
||||
<br/>
|
||||
<!-- ENDIF fullname -->
|
||||
|
||||
<span class="account-bio-label">website</span>
|
||||
<!-- IF website -->
|
||||
<span class="account-bio-label">[[user:website]]</span>
|
||||
<span><a href="{website}">{websiteName}</a></span>
|
||||
<br/>
|
||||
<!-- ENDIF website -->
|
||||
|
||||
<span class="account-bio-label">location</span>
|
||||
<!-- IF location -->
|
||||
<span class="account-bio-label">[[user:location]]</span>
|
||||
<span>{location}</span>
|
||||
<br/>
|
||||
<!-- ENDIF location -->
|
||||
|
||||
<span class="account-bio-label">age</span>
|
||||
<!-- IF age -->
|
||||
<span class="account-bio-label">[[user:age]]</span>
|
||||
<span>{age}</span>
|
||||
<br/>
|
||||
<!-- ENDIF age -->
|
||||
|
||||
<hr/>
|
||||
<span class="account-bio-label">joined</span>
|
||||
<span class="account-bio-label">[[user:joined]]</span>
|
||||
<span class="timeago" title="{joindate}"></span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">profile views</span>
|
||||
<span class="account-bio-label">[[user:lastonline]]</span>
|
||||
<span class="timeago" title="{lastonline}"></span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">[[user:profile_views]]</span>
|
||||
<span class="formatted-number">{profileviews}</span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">reputation</span>
|
||||
<span class="account-bio-label">[[user:reputation]]</span>
|
||||
<span class="formatted-number">{reputation}</span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">posts</span>
|
||||
<span class="account-bio-label">[[user:posts]]</span>
|
||||
<span class="formatted-number">{postcount}</span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">followers</span>
|
||||
<span class="account-bio-label">[[user:followers]]</span>
|
||||
<span class="formatted-number">{followerCount}</span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">following</span>
|
||||
<span class="account-bio-label">[[user:following]]</span>
|
||||
<span class="formatted-number">{followingCount}</span>
|
||||
<br/>
|
||||
|
||||
<hr/>
|
||||
<span class="account-bio-label">signature</span>
|
||||
<!-- IF !disableSignatures -->
|
||||
<!-- IF signature -->
|
||||
<span class="account-bio-label">[[user:signature]]</span>
|
||||
<div class="post-signature">
|
||||
<span id='signature'>{signature}</span>
|
||||
</div>
|
||||
<!-- ENDIF signature -->
|
||||
<!-- ENDIF !disableSignatures -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,4 +124,4 @@
|
||||
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
<input type="hidden" template-variable="theirid" value="{theirid}" />
|
||||
<input type="hidden" template-type="boolean" template-variable="isFollowing" value="{isFollowing}" />
|
||||
<input type="hidden" template-type="boolean" template-variable="isFollowing" value="{isFollowing}" />
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
<div class="well account">
|
||||
|
||||
<div class="well">
|
||||
|
||||
<div id="change-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Change Picture" aria-hidden="true">
|
||||
<div id="change-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="[[user:change_picture]]" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Change Picture</h3>
|
||||
<h3 id="myModalLabel">[[user:change_picture]]</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="gravatar-box">
|
||||
<img id="user-gravatar-picture" src="" class="img-thumbnail user-profile-picture">
|
||||
<span class="user-picture-label">Gravatar</span>
|
||||
<i class='icon-ok icon-2x'></i>
|
||||
<span class="user-picture-label">[[user:gravatar]]</span>
|
||||
<i class='fa fa-check fa-2x'></i>
|
||||
</div>
|
||||
<br/>
|
||||
<div id="uploaded-box">
|
||||
<img id="user-uploaded-picture" src="" class="img-thumbnail user-profile-picture">
|
||||
<span class="user-picture-label">Uploaded picture</span>
|
||||
<i class='icon-ok icon-2x'></i>
|
||||
<span class="user-picture-label">[[user:uploaded_picture]]</span>
|
||||
<i class='fa fa-check fa-2x'></i>
|
||||
</div>
|
||||
|
||||
<a id="uploadPictureBtn" href="#">Upload new picture</a>
|
||||
<a id="uploadPictureBtn" href="#">[[user:upload_new_picture]]</a>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
@@ -33,8 +32,8 @@
|
||||
|
||||
<div class="account-username-box" data-userslug="{userslug}">
|
||||
<span class="account-username">
|
||||
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||
<a href="/user/{userslug}/edit">edit</a>
|
||||
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
|
||||
<a href="/user/{userslug}/edit">[[user:edit]]</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +41,7 @@
|
||||
<div class="col-md-2" style="text-align: center; margin-bottom:20px;">
|
||||
<div class="account-picture-block text-center">
|
||||
<img id="user-current-picture" class="user-profile-picture img-thumbnail" src="{picture}" /><br /><br />
|
||||
<a id="changePictureBtn" href="#" class="btn btn-primary">change picture</a>
|
||||
<a id="changePictureBtn" href="#" class="btn btn-primary">[[user:change_picture]]</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,51 +49,53 @@
|
||||
<div>
|
||||
<form class='form-horizontal'>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputEmail">Email</label>
|
||||
<label class="control-label" for="inputEmail">[[user:email]]</label>
|
||||
<div class="controls">
|
||||
<input class="form-control" type="text" id="inputEmail" placeholder="Email" value="{email}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputFullname">Full Name</label>
|
||||
<label class="control-label" for="inputFullname">[[user:fullname]]</label>
|
||||
<div class="controls">
|
||||
<input class="form-control" type="text" id="inputFullname" placeholder="Full Name" value="{fullname}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputWebsite">Website</label>
|
||||
<label class="control-label" for="inputWebsite">[[user:website]]</label>
|
||||
<div class="controls">
|
||||
<input class="form-control" type="text" id="inputWebsite" placeholder="http://website.com" value="{website}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputLocation">Location</label>
|
||||
<label class="control-label" for="inputLocation">[[user:location]]</label>
|
||||
<div class="controls">
|
||||
<input class="form-control" type="text" id="inputLocation" placeholder="Location" value="{location}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputBirthday">Birthday</label>
|
||||
<label class="control-label" for="inputBirthday">[[user:birthday]]</label>
|
||||
<div class="controls">
|
||||
<input class="form-control" type="date" id="inputBirthday" placeholder="mm/dd/yyyy" value="{birthday}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IF !disableSignatures -->
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputSignature">Signature</label>
|
||||
<label class="control-label" for="inputSignature">[[user:signature]]</label> <small><label id="signatureCharCountLeft"></label></small>
|
||||
<div class="controls">
|
||||
<textarea class="form-control" id="inputSignature" placeholder="max 150 chars" rows="5">{signature}</textarea>
|
||||
<textarea class="form-control" id="inputSignature" rows="5">{signature}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ENDIF !disableSignatures -->
|
||||
|
||||
<input type="hidden" id="inputUID" value="{uid}"><br />
|
||||
|
||||
<div class="form-actions">
|
||||
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
|
||||
<a id="submitBtn" href="#" class="btn btn-primary">[[global:save_changes]]</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
@@ -114,23 +115,27 @@
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputNewPassword">Password</label>
|
||||
<div class="controls">
|
||||
<label class="control-label" for="inputNewPassword">[[user:password]]</label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="password" id="inputNewPassword" placeholder="New Password" value="">
|
||||
<div id="password-notify" class="alert alert-danger hide"></div>
|
||||
<span class="input-group-addon">
|
||||
<span id="password-notify"><i class="fa fa-circle-o"></i></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="inputNewPasswordAgain">Confirm Password</label>
|
||||
<div class="controls">
|
||||
<label class="control-label" for="inputNewPasswordAgain">[[user:confirm_password]]</label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="password" id="inputNewPasswordAgain" placeholder="Confirm Password" value="">
|
||||
<div id="password-confirm-notify" class="alert alert-danger hide"></div>
|
||||
<span class="input-group-addon">
|
||||
<span id="password-confirm-notify"><i class="fa fa-circle-o"></i></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-actions">
|
||||
<a id="changePasswordBtn" href="#" class="btn btn-primary">Change Password</a>
|
||||
<a id="changePasswordBtn" href="#" class="btn btn-primary">[[user:change_password]]</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
<div class="well">
|
||||
<div class="well account">
|
||||
|
||||
<div class="account-username-box" data-userslug="{userslug}">
|
||||
<span class="account-username">
|
||||
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||
<a href="/user/{userslug}/settings">settings</a>
|
||||
<a href="/user/{userslug}">{username}</a> <i class="fa fa-chevron-right"></i>
|
||||
<a href="/user/{userslug}/settings">[[user:settings]]</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +12,7 @@
|
||||
<h4>privacy</h4>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="showemailCheckBox" type="checkbox" {showemail}> Show my email
|
||||
<input id="showemailCheckBox" type="checkbox" {showemail}> [[user:show_email]]
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,6 +22,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
|
||||
<a id="submitBtn" href="#" class="btn btn-primary">[[global:save_changes]]</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,6 @@
|
||||
|
||||
|
||||
<!-- IF redis -->
|
||||
<h1>Redis</h1>
|
||||
<hr />
|
||||
<div id="admin-redis-info">
|
||||
@@ -21,4 +24,29 @@
|
||||
<span>Keyspace Hits</span> <span class="text-right">{keyspace_hits}</span><br/>
|
||||
<span>Keyspace Misses</span> <span class="text-right">{keyspace_misses}</span><br/>
|
||||
</div>
|
||||
<hr />
|
||||
<h3>Raw Info </h3>
|
||||
<div class="highlight">
|
||||
<pre>{raw}</pre>
|
||||
</div>
|
||||
<!-- ENDIF redis -->
|
||||
|
||||
<!-- IF mongo -->
|
||||
<h1>Mongo</h1>
|
||||
<hr />
|
||||
<div id="admin-redis-info">
|
||||
|
||||
<span>Collections</span> <span class="text-right">{collections}</span><br/>
|
||||
<span>Objects</span> <span class="text-right">{objects}</span><br/>
|
||||
<span>Avg. Object Size</span> <span class="text-right">{avgObjSize} kb</span><br/>
|
||||
<hr/>
|
||||
<span>Data Size</span> <span class="text-right">{dataSize} kb</span><br/>
|
||||
<span>Storage Size</span> <span class="text-right">{storageSize} kb</span><br/>
|
||||
<span>File Size</span> <span class="text-right">{fileSize} kb</span><br/>
|
||||
</div>
|
||||
<hr />
|
||||
<h3>Raw Info </h3>
|
||||
<div class="highlight">
|
||||
<pre>{raw}</pre>
|
||||
</div>
|
||||
<!-- ENDIF mongo -->
|
||||
5
public/templates/admin/events.tpl
Normal file
5
public/templates/admin/events.tpl
Normal file
@@ -0,0 +1,5 @@
|
||||
<h1>Events</h1>
|
||||
|
||||
<pre>
|
||||
{eventdata}
|
||||
</pre>
|
||||
@@ -17,6 +17,7 @@
|
||||
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
|
||||
</div>
|
||||
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
||||
<input type="hidden" id="params" name="params">
|
||||
</form>
|
||||
|
||||
<div id="upload-progress-box" class="progress progress-striped">
|
||||
|
||||
@@ -54,13 +54,13 @@
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a href="/admin/index"><i class="icon-home"></i> Home</a>
|
||||
<a href="/admin/index"><i class="fa fa-home" title="Home"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings"><i class="icon-cogs"></i> Settings</a>
|
||||
<a href="/admin/settings"><i class="fa fa-cogs" title="Settings"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" target="_top"><i class="icon-book"></i> Forum</a>
|
||||
<a href="/" target="_top"><i class="fa fa-book" title="Forum"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" id="reconnect"></a>
|
||||
@@ -91,31 +91,35 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="col-sm-3">
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">NodeBB</li>
|
||||
<li class='active'>
|
||||
<a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a>
|
||||
</li>
|
||||
<li><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
|
||||
<li><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
|
||||
<li><a href="{relative_path}/admin/groups"><i class="icon-group"></i> Groups</a></li>
|
||||
<li><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
|
||||
<li><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
|
||||
<li><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
|
||||
<li><a href='{relative_path}/admin/settings'><i class='icon-cogs'></i> Settings</a></li>
|
||||
<li><a href='{relative_path}/admin/redis'><i class='icon-hdd'></i> Redis</a></li>
|
||||
<li><a href='{relative_path}/admin/logger'><i class='icon-th'></i> Logger</a></li>
|
||||
<li><a href="{relative_path}/admin/motd"><i class="icon-comment"></i> MOTD</a></li>
|
||||
<li class="active"><a href="{relative_path}/admin/index"><i class="fa fa-fw fa-home"></i> Home</a></li>
|
||||
<li><a href="{relative_path}/admin/categories/active"><i class="fa fa-fw fa-folder"></i> Categories</a></li>
|
||||
<li><a href="{relative_path}/admin/users/latest"><i class="fa fa-fw fa-user"></i> Users</a></li>
|
||||
<li><a href="{relative_path}/admin/groups"><i class="fa fa-fw fa-group"></i> Groups</a></li>
|
||||
<li><a href="{relative_path}/admin/topics"><i class="fa fa-fw fa-book"></i> Topics</a></li>
|
||||
<li><a href="{relative_path}/admin/themes"><i class="fa fa-fw fa-th"></i> Themes</a></li>
|
||||
<li><a href="{relative_path}/admin/plugins"><i class="fa fa-fw fa-code-fork"></i> Plugins</a></li>
|
||||
<li><a href="{relative_path}/admin/settings"><i class="fa fa-fw fa-cogs"></i> Settings</a></li>
|
||||
<li><a href="{relative_path}/admin/database"><i class="fa fa-fw fa-hdd-o"></i> Database</a></li>
|
||||
<li><a href="{relative_path}/admin/logger"><i class="fa fa-fw fa-th"></i> Logger</a></li>
|
||||
<li><a href="{relative_path}/admin/motd"><i class="fa fa-fw fa-comment"></i> MOTD</a></li>
|
||||
<li><a href="{relative_path}/admin/events"><i class="fa fa-fw fa-calendar-o"></i> Events</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">Social Authentication</li>
|
||||
<li><a href='{relative_path}/admin/twitter'><i class='icon-twitter-sign'></i> Twitter</a></li>
|
||||
<li><a href='{relative_path}/admin/facebook'><i class='icon-facebook-sign'></i> Facebook</a></li>
|
||||
<li><a href='{relative_path}/admin/gplus'><i class='icon-google-plus-sign'></i> Google+</a></li>
|
||||
<li><a href="{relative_path}/admin/twitter"><i class="fa fa-fw fa-twitter-square"></i> Twitter</a></li>
|
||||
<li><a href="{relative_path}/admin/facebook"><i class="fa fa-fw fa-facebook-square"></i> Facebook</a></li>
|
||||
<li><a href="{relative_path}/admin/gplus"><i class="fa fa-fw fa-google-plus-square"></i> Google+</a></li>
|
||||
<!-- BEGIN authentication -->
|
||||
<li>
|
||||
<a href="{relative_path}/admin{authentication.route}"><i class="fa fa-fw {authentication.icon}"></i> {authentication.name}</a>
|
||||
</li>
|
||||
<!-- END authentication -->
|
||||
</ul>
|
||||
</div>
|
||||
<div class="well sidebar-nav">
|
||||
@@ -123,7 +127,7 @@
|
||||
<li class="nav-header">Plugins</li>
|
||||
<!-- BEGIN plugins -->
|
||||
<li>
|
||||
<a href='{relative_path}/admin{plugins.route}'><i class="{plugins.icon}"></i> {plugins.name}</a>
|
||||
<a href="{relative_path}/admin{plugins.route}"><i class="fa fa-fw {plugins.icon}"></i> {plugins.name}</a>
|
||||
</li>
|
||||
<!-- END plugins -->
|
||||
</ul>
|
||||
@@ -132,18 +136,18 @@
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">Unit Tests</li>
|
||||
<ul class="nav nav-list">
|
||||
<li><a href='{relative_path}/admin/testing/categories'>Categories</a></li>
|
||||
<!--<li><a href='{relative_path}/admin/testing/topics'>Topics</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/posts'>Posts</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/accounts'>Accounts</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/chat'>Chat</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/notifications'>Notifications</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/friends'>Friends</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/feed'>RSS Feed</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/emails'>Emails</a></li>-->
|
||||
<li><a href="{relative_path}/admin/testing/categories">Categories</a></li>
|
||||
<!--<li><a href="{relative_path}/admin/testing/topics">Topics</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/posts">Posts</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/accounts">Accounts</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/chat">Chat</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/notifications">Notifications</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/friends">Friends</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/feed">RSS Feed</a></li>
|
||||
<li><a href="{relative_path}/admin/testing/emails">Emails</a></li>-->
|
||||
</ul>
|
||||
</ul>
|
||||
</div><!--/.well -->
|
||||
</div><!--/span-->
|
||||
|
||||
<div class="col-md-9" id="content">
|
||||
<div class="col-sm-9" id="content">
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<h1>Welcome to NodeBB</h1>
|
||||
<br />
|
||||
<p>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-comment"></i> NodeBB Forum</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Plugins</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Themes</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-twitter"></i> dcplabs</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-comment"></i> NodeBB Forum</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-github-alt"></i> Get Plugins</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-github-alt"></i> Get Themes</a>
|
||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="fa fa-twitter"></i> dcplabs</a>
|
||||
</p>
|
||||
<p><small>You are running <strong>NodeBB v{version}</strong>. Always make sure that your <strong>NodeBB</strong> is up to date for the latest security patches and bug fixes.</small></p>
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
<input type="text" class="form-control" placeholder="Keywords describing your community, comma-seperated" data-field="keywords" /><br />
|
||||
<label>Site Logo</label>
|
||||
<input id="logoUrl" type="text" class="form-control" placeholder="Path to a logo to display on forum header" data-field="brand:logo" /><br />
|
||||
<input id="uploadLogoBtn" type="button" class="btn btn-default" value="Upload"></input> <br />
|
||||
<input id="uploadLogoBtn" type="button" class="btn btn-default" value="Upload Logo"></input> <br />
|
||||
<label>Imgur Client ID</label>
|
||||
<input type="text" class="form-control" placeholder="Imgur ClientID for image uploads" data-field="imgurClientID" /><br />
|
||||
<label>Maximum User Image Size</label>
|
||||
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" />
|
||||
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" /><br />
|
||||
<label>Favicon</label><br />
|
||||
<input id="faviconUrl" type="text" class="form-control" placeholder="favicon.ico" data-field="brand:favicon" /><br />
|
||||
<input id="uploadFaviconBtn" type="button" class="btn btn-default" value="Upload Favicon"></input> <br />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -26,6 +29,11 @@
|
||||
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
|
||||
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_topic"><br />
|
||||
<strong>Manage Content</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_content"><br />
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="privileges:disabled"> <strong>Disable Privilege Threshold System</strong>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -55,15 +63,38 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form>
|
||||
<h3>Profile Settings</h3>
|
||||
<div class="alert alert-warning">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="profile:convertProfileImageToPNG"> <strong>Convert profile image uploads to PNG</strong>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form>
|
||||
<h3>User Settings</h3>
|
||||
<div class="alert alert-warning">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowRegistration" checked> <strong>Allow registration</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="disableSignatures"> <strong>Disable signatures</strong>
|
||||
</label>
|
||||
</div>
|
||||
<strong>Minimum Username Length</strong><br />
|
||||
<input type="text" class="form-control" value="2" data-field="minimumUsernameLength"><br />
|
||||
<strong>Maximum Username Length</strong><br />
|
||||
<input type="text" class="form-control" value="16" data-field="maximumUsernameLength"><br />
|
||||
<strong>Minimum Password Length</strong><br />
|
||||
<input type="text" class="form-control" value="6" data-field="minimumPasswordLength"><br />
|
||||
<strong>Maximum Signature Length</strong><br />
|
||||
<input type="text" class="form-control" value="255" data-field="maximumSignatureLength"><br />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -72,17 +103,35 @@
|
||||
<div class="alert alert-warning">
|
||||
<strong>Post Delay</strong><br /> <input type="text" class="form-control" value="10000" data-field="postDelay"><br />
|
||||
<strong>Minimum Title Length</strong><br /> <input type="text" class="form-control" value="3" data-field="minimumTitleLength"><br />
|
||||
<strong>Maximum Title Length</strong><br /> <input type="text" class="form-control" value="255" data-field="maximumTitleLength"><br />
|
||||
<strong>Minimum Post Length</strong><br /> <input type="text" class="form-control" value="8" data-field="minimumPostLength"><br />
|
||||
<strong>Chat Messages To Display</strong><br /> <input type="text" class="form-control" value="50" data-field="chatMessagesToDisplay"><br />
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowGuestPosting"> <strong>Allow guests to post without logging in</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowGuestSearching"> <strong>Allow guests to search without logging in</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="disableSocialButtons"> <strong>Disable social buttons</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowFileUploads"> <strong>Allow users to upload regular files</strong>
|
||||
</label>
|
||||
</div>
|
||||
<strong>Maximum File Size</strong><br /> <input type="text" class="form-control" value="2048" data-field="maximumFileSize"><br />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
The following themes are currently installed in this NodeBB instance.
|
||||
</p>
|
||||
<ul class="themes" id="installed_themes">
|
||||
<li><i class="icon-refresh icon-spin"></i> Checking for installed themes...</li>
|
||||
<li><i class="fa fa-refresh fa-spin"></i> Checking for installed themes...</li>
|
||||
</ul>
|
||||
|
||||
<h3>Bootswatch Themes</h3>
|
||||
@@ -15,7 +15,7 @@
|
||||
with Bootstrap as a base theme.
|
||||
</p>
|
||||
<ul class="themes" id="bootstrap_themes">
|
||||
<li><i class="icon-refresh icon-spin"></i> Loading Themes</li>
|
||||
<li><i class="fa fa-refresh fa-spin"></i> Loading Themes</li>
|
||||
</ul>
|
||||
|
||||
<h3>Revert to Default</h3>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<!-- BEGIN topics -->
|
||||
<li data-tid="{topics.tid}" data-locked="{topics.locked}" data-pinned="{topics.pinned}" data-deleted="{topics.deleted}">
|
||||
<div class="btn-group pull-right">
|
||||
<button data-action="pin" class="btn"><i class="icon-pushpin"></i></button>
|
||||
<button data-action="lock" class="btn"><i class="icon-lock"></i></button>
|
||||
<button data-action="delete" class="btn"><i class="icon-trash"></i></button>
|
||||
<button data-action="pin" class="btn"><i class="fa fa-thumb-tack"></i></button>
|
||||
<button data-action="lock" class="btn"><i class="fa fa-lock"></i></button>
|
||||
<button data-action="delete" class="btn"><i class="fa fa-trash-o"></i></button>
|
||||
</div>
|
||||
<a target="_blank" href="{relative_path}/topic/{topics.slug}">{topics.title}</a>
|
||||
<ul>
|
||||
<li><i class="icon-time"></i> Posted <span class="timeago" title="{topics.relativeTime}"></span> by {topics.username}</li>
|
||||
<li><i class="icon-comments"></i> {topics.postcount} post(s)</li>
|
||||
<li><i class="fa fa-clock-o"></i> Posted <span class="timeago" title="{topics.relativeTime}"></span> by {topics.username}</li>
|
||||
<li><i class="fa fa-comments"></i> {topics.postcount} post(s)</li>
|
||||
</ul>
|
||||
<div class="clear"></div>
|
||||
</li>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<h1>Users</h1>
|
||||
|
||||
<button id="createUser" class="btn btn-primary">Create User</button>
|
||||
<hr />
|
||||
<ul class="nav nav-pills">
|
||||
<li class='active'><a href='/admin/users/latest'>Latest Users</a></li>
|
||||
@@ -10,7 +12,7 @@
|
||||
<br />
|
||||
<div class="search {search_display} well">
|
||||
<input class="form-control" id="search-user" type="text" placeholder="Enter a username to search"/><br />
|
||||
<i class="icon-spinner icon-spin none"></i>
|
||||
<i class="fa fa-spinner fa-spin none"></i>
|
||||
<span id="user-notfound-notify" class="label label-danger hide">User not found!</span><br/>
|
||||
</div>
|
||||
|
||||
@@ -24,13 +26,16 @@
|
||||
<a href="/user/{users.userslug}">{users.username}</a>
|
||||
<br/>
|
||||
<div title="reputation">
|
||||
<i class='icon-star'></i>
|
||||
<i class='fa fa-star'></i>
|
||||
<span id='reputation'>{users.reputation}</span>
|
||||
</div>
|
||||
<div title="post count">
|
||||
<i class='icon-pencil'></i>
|
||||
<i class='fa fa-pencil'></i>
|
||||
<span id='postcount'>{users.postcount}</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="btn btn-default admin-btn">Make Admin</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="btn btn-default ban-btn">Ban</a>
|
||||
</div>
|
||||
@@ -38,6 +43,47 @@
|
||||
<!-- END users -->
|
||||
</ul>
|
||||
|
||||
<div class="modal fade" id="create-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Create User</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-danger hide" id="create-modal-error"></div>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="group-name">User Name</label>
|
||||
<input type="text" class="form-control" id="create-user-name" placeholder="User Name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="group-name">Email</label>
|
||||
<input type="text" class="form-control" id="create-user-email" placeholder="Email of this user" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="group-name">Password</label>
|
||||
<input type="password" class="form-control" id="create-user-password" placeholder="Password" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="group-name">Password Confirm</label>
|
||||
<input type="password" class="form-control" id="create-user-password-again" placeholder="Password" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" id="create-modal-go">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="text-center {loadmore_display}">
|
||||
<button id="load-more-users-btn" class="btn btn-primary">Load More</button>
|
||||
</div>
|
||||
|
||||
@@ -3,19 +3,20 @@
|
||||
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
|
||||
</li>
|
||||
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||
<span itemprop="title">{category_name} <a target="_blank" href="../{category_id}.rss"><i class="icon-rss-sign"></i></a></span>
|
||||
<span itemprop="title">{category_name} <a target="_blank" href="../{category_id}.rss"><i class="fa fa-rss-square"></i></a></span>
|
||||
</li>
|
||||
<div id="category_active_users"></div>
|
||||
</ol>
|
||||
|
||||
<div>
|
||||
<button id="new_post" class="btn btn-primary btn-lg {show_topic_button}">[[category:new_topic_button]]</button>
|
||||
|
||||
<button id="new_post" class="btn btn-primary {show_topic_button}">[[category:new_topic_button]]</button>
|
||||
<!-- IF !disableSocialButtons -->
|
||||
<div class="inline-block pull-right">
|
||||
<a href="#" id="facebook-share"><i class="icon-facebook-sign icon-2x"></i></a>
|
||||
<a href="#" id="twitter-intent"><i class="icon-twitter-sign icon-2x"></i></a>
|
||||
<a href="#" id="google-share"><i class="icon-google-plus-sign icon-2x"></i></a>
|
||||
<a href="#" id="facebook-share"><i class="fa fa-facebook-square fa-2x"></i></a>
|
||||
<a href="#" id="twitter-intent"><i class="fa fa-twitter-square fa-2x"></i></a>
|
||||
<a href="#" id="google-share"><i class="fa fa-google-plus-square fa-2x"></i></a>
|
||||
</div>
|
||||
<!-- ENDIF !disableSocialButtons -->
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
@@ -38,38 +39,38 @@
|
||||
<meta itemprop="name" content="{topics.title}">
|
||||
|
||||
<span class="topic-title">
|
||||
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||
<strong><i class="fa {topics.pin-icon}"></i> <i class="fa {topics.lock-icon}"></i></strong>
|
||||
{topics.title}
|
||||
</span>
|
||||
</h3>
|
||||
</a>
|
||||
<small>
|
||||
<span class="topic-stats">
|
||||
posts
|
||||
<strong>{topics.postcount}</strong>
|
||||
[[category:posts]]
|
||||
<strong class="human-readable-number" title="{topics.postcount}">{topics.postcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span class="topic-stats">
|
||||
views
|
||||
<strong>{topics.viewcount}</strong>
|
||||
[[category:views]]
|
||||
<strong class="human-readable-number" title="{topics.viewcount}">{topics.viewcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span>
|
||||
<a href="/user/{topics.userslug}">
|
||||
<img class="teaser-pic" src="{topics.picture}" title="{topics.username}"/>
|
||||
</a>
|
||||
posted <span class="timeago" title="{topics.relativeTime}"></span>
|
||||
[[category:posted]] <span class="timeago" title="{topics.relativeTime}"></span>
|
||||
</span>
|
||||
|
||||
<span class="pull-right hidden-xs">
|
||||
<!-- IF topics.unreplied -->
|
||||
No one has replied
|
||||
[[category:no_replies]]
|
||||
<!-- ELSE -->
|
||||
<a href="/user/{topics.teaser_userslug}">
|
||||
<img class="teaser-pic" src="{topics.teaser_userpicture}" title="{topics.teaser_username}"/>
|
||||
</a>
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
replied
|
||||
[[category:replied]]
|
||||
</a>
|
||||
<span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
<!-- ENDIF topics.unreplied -->
|
||||
@@ -83,43 +84,35 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3 {show_sidebar} category-sidebar">
|
||||
|
||||
<div class="sidebar-block img-thumbnail">
|
||||
<div class="block-header">
|
||||
[[category:sidebar.recent_replies]]
|
||||
</div>
|
||||
<div class="block-content recent-replies">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">[[category:sidebar.recent_replies]]</div>
|
||||
<div class="panel-body recent-replies">
|
||||
<ul id="category_recent_replies"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-block img-thumbnail">
|
||||
<div class="block-header">
|
||||
[[category:sidebar.active_participants]]
|
||||
</div>
|
||||
<div class="block-content active-users">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">[[category:sidebar.active_participants]]</div>
|
||||
<div class="panel-body active-users">
|
||||
<!-- BEGIN active_users -->
|
||||
<a data-uid="{active_users.uid}" href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded user-img" /></a>
|
||||
<!-- END active_users -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-block img-thumbnail {moderator_block_class}">
|
||||
<div class="block-header">
|
||||
[[category:sidebar.moderators]]
|
||||
</div>
|
||||
<div class="block-content">
|
||||
|
||||
<div class="panel panel-default {moderator_block_class}">
|
||||
<div class="panel-heading">[[category:sidebar.moderators]]</div>
|
||||
<div class="panel-body moderators">
|
||||
<!-- BEGIN moderators -->
|
||||
<a href="/user/{moderators.userslug}"><img title="{moderators.username}" src="{moderators.picture}" class="img-rounded" /></a>
|
||||
<!-- END moderators -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BEGIN sidebars -->
|
||||
<div class="sidebar-block img-thumbnail {sidebars.block_class}">
|
||||
<div class="block-header">
|
||||
{sidebars.header}
|
||||
</div>
|
||||
<div class="block-content">
|
||||
{sidebars.content}
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel panel-default {sidebars.block_class}">{sidebars.header}</div>
|
||||
<div class="panel-body">{sidebars.content}</div>
|
||||
</div>
|
||||
<!-- END sidebars -->
|
||||
</div>
|
||||
@@ -128,4 +121,4 @@
|
||||
<input type="hidden" template-variable="category_id" value="{category_id}" />
|
||||
<input type="hidden" template-variable="twitter-intent-url" value="{twitter-intent-url}" />
|
||||
<input type="hidden" template-variable="facebook-share-url" value="{facebook-share-url}" />
|
||||
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
|
||||
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
|
||||
|
||||
36
public/templates/composer.tpl
Normal file
36
public/templates/composer.tpl
Normal file
@@ -0,0 +1,36 @@
|
||||
<div class="composer">
|
||||
<div class="composer-container">
|
||||
<input class="title" type="text" tabIndex="1" placeholder="Enter your topic title here..." />
|
||||
<div class="btn-toolbar formatting-bar">
|
||||
<div class="btn-group">
|
||||
<span class="btn btn-link" tabindex="-1"><i class="fa fa-bold"></i></span>
|
||||
<span class="btn btn-link" tabindex="-1"><i class="fa fa-italic"></i></span>
|
||||
<span class="btn btn-link" tabindex="-1"><i class="fa fa-list"></i></span>
|
||||
<span class="btn btn-link" tabindex="-1"><i class="fa fa-link"></i></span>
|
||||
<span class="btn btn-link img-upload-btn hide" tabindex="-1">
|
||||
<i class="fa fa-picture-o"></i>
|
||||
</span>
|
||||
<span class="btn btn-link file-upload-btn hide" tabindex="-1">
|
||||
<i class="fa fa-upload"></i>
|
||||
</span>
|
||||
<form id="fileForm">
|
||||
<input type="file" id="files" name="files[]" multiple class="hide"/>
|
||||
</form>
|
||||
</div>
|
||||
<!-- <div class="btn btn-link pull-right">Preview</div> -->
|
||||
</div>
|
||||
<textarea tabIndex="2"></textarea>
|
||||
<div class="preview"></div>
|
||||
<div class="imagedrop"><div>Drag and Drop Images Here</div></div>
|
||||
<div class="text-center upload-instructions hide">
|
||||
<small>Upload images by dragging & dropping them</small>
|
||||
</div>
|
||||
<div class="btn-toolbar action-bar">
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-default" data-action="discard" tabIndex="5"><i class="fa fa-times"></i> Discard</button>
|
||||
<button data-action="post" class="btn btn-default" tabIndex="3"><i class="fa fa-check"></i> Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resizer"><div class="trigger"><i class="fa fa-chevron-left"></i></div></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,7 +4,8 @@
|
||||
"^admin/topics.*": "admin/topics",
|
||||
"^admin/categories.*": "admin/categories",
|
||||
"^admin/users.*": "admin/users",
|
||||
"^admin/redis.*": "admin/redis",
|
||||
"^admin/database.*": "admin/database",
|
||||
"^admin/events.*": "admin/events",
|
||||
"^admin/index.*": "admin/index",
|
||||
"^admin/themes.*": "admin/themes",
|
||||
"^admin/plugins/?$": "admin/plugins",
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<strong>{title}</strong>
|
||||
<p>{text}</p>
|
||||
<p>
|
||||
<a href="/">NodeBB Home</a>
|
||||
<a href="/">[[notification:back_to_home]]</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user