mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-16 21:40:23 +01:00
Compare commits
1413 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
7955a5d53a | ||
|
|
c261babf17 | ||
|
|
b90eef6d19 | ||
|
|
5c597ca218 | ||
|
|
3dbcf8112d | ||
|
|
5357ad61db | ||
|
|
ff50917c29 | ||
|
|
48835d8c44 | ||
|
|
e9c66bb35a | ||
|
|
23eb7824ac | ||
|
|
494b9d23ac | ||
|
|
64ae9ac033 | ||
|
|
a72fc69997 | ||
|
|
a16f93cbd5 | ||
|
|
81e5cf0cf3 | ||
|
|
01102d5982 | ||
|
|
2174aec0e1 | ||
|
|
46bad118de | ||
|
|
2d7228fa40 | ||
|
|
a1839d90fd | ||
|
|
0cc136c3f6 | ||
|
|
cd1e26418d | ||
|
|
dab4f07258 | ||
|
|
501dc56fd3 | ||
|
|
253271127d | ||
|
|
f2da892b38 | ||
|
|
6dd72f480c | ||
|
|
3caf8b4a67 | ||
|
|
39f2efbef8 | ||
|
|
288341945d | ||
|
|
d02bd72764 | ||
|
|
7d3adb9275 | ||
|
|
156950ac2f | ||
|
|
83f18c1915 | ||
|
|
332730575f | ||
|
|
08ef67e824 | ||
|
|
7e71fb218c | ||
|
|
a7216caa3b | ||
|
|
87309601ce | ||
|
|
53db9db50f | ||
|
|
23628668b7 | ||
|
|
6ac685b194 | ||
|
|
db8c43ca97 | ||
|
|
bff0c8fdaf | ||
|
|
6f2b809385 | ||
|
|
455479bd54 | ||
|
|
03b34a449d | ||
|
|
08e51c8942 | ||
|
|
4aef5bfb72 | ||
|
|
34c74770ce | ||
|
|
da8d198676 | ||
|
|
33868804fd | ||
|
|
22a3794c51 | ||
|
|
1058d54c52 | ||
|
|
90ce539683 | ||
|
|
99c2fbd947 | ||
|
|
866d813218 | ||
|
|
f1df8c2479 | ||
|
|
6f1523c279 | ||
|
|
163cdaf70c | ||
|
|
a9ce8393e4 | ||
|
|
f04e30c4d4 | ||
|
|
9d0f8b4543 | ||
|
|
d631a4b2e5 | ||
|
|
2cf55dcf9f | ||
|
|
9fbb139e67 | ||
|
|
11e3b0da7d | ||
|
|
0b922d3f60 | ||
|
|
7e4faa3270 | ||
|
|
635fba1e45 | ||
|
|
7c950cc350 | ||
|
|
cc0fe66e3e | ||
|
|
b2d6ce59cf | ||
|
|
586a181e0a | ||
|
|
33150943df | ||
|
|
28dab60232 | ||
|
|
71ef76b108 | ||
|
|
64008ef5d8 | ||
|
|
1859154370 | ||
|
|
fa4067e885 | ||
|
|
c8c355b319 | ||
|
|
51355a53d9 | ||
|
|
1f3f672d3f | ||
|
|
7c3fa30c13 | ||
|
|
cbbb7a7c8e | ||
|
|
6893bd8b04 | ||
|
|
22eabf6620 | ||
|
|
a827888ee3 | ||
|
|
54d94f5988 | ||
|
|
7c1b6d6ad2 | ||
|
|
8c4f776122 | ||
|
|
84fa704b25 | ||
|
|
535379d9d7 | ||
|
|
d2927e2be2 | ||
|
|
bd04b2f921 | ||
|
|
27fce2363d | ||
|
|
01340c87bd | ||
|
|
77c2f551d3 | ||
|
|
18009ebb39 | ||
|
|
e6bb66705d | ||
|
|
88154c3ebf | ||
|
|
1c80a1bad5 | ||
|
|
79c52dfe84 | ||
|
|
411ba3542c | ||
|
|
fa9636a62a | ||
|
|
69fefc0625 | ||
|
|
e598ffa993 | ||
|
|
d99577ffb2 | ||
|
|
40108f92c9 | ||
|
|
a42b30fd40 | ||
|
|
37497fc5a0 | ||
|
|
9bea23bbfe | ||
|
|
4e39c50144 | ||
|
|
7e50bcba0c | ||
|
|
f81c583d86 | ||
|
|
5647d55147 | ||
|
|
4ce6ac5af9 | ||
|
|
d770963b69 | ||
|
|
625b96ba73 | ||
|
|
37877ed531 | ||
|
|
1f2ef2a7e4 | ||
|
|
885eec79c3 | ||
|
|
aa1994be67 | ||
|
|
4552e6286e | ||
|
|
d7856bcd4f | ||
|
|
7ea852fae3 | ||
|
|
c67c37bb20 | ||
|
|
7d1aa02fd1 | ||
|
|
2309ab2002 | ||
|
|
b87840d4c9 | ||
|
|
b5c22c7ff7 | ||
|
|
3b3e8348e4 | ||
|
|
259ad42b31 | ||
|
|
51cb33bccc | ||
|
|
2a8a62a253 | ||
|
|
82ae80090e | ||
|
|
1d6135150f | ||
|
|
41f98d29b7 | ||
|
|
7b5a6bd3c9 | ||
|
|
fe15366524 | ||
|
|
1cbbb3873f | ||
|
|
5e1ab7989a | ||
|
|
0e5724cd2c | ||
|
|
89e9d56dee | ||
|
|
58f9c2c18d | ||
|
|
1ec6726459 | ||
|
|
6b4520e526 | ||
|
|
98f20564de | ||
|
|
4da819b02b | ||
|
|
dc90db74c0 | ||
|
|
c5bc2dd64f | ||
|
|
bbb045698d | ||
|
|
d9e364cd86 | ||
|
|
b179991be4 | ||
|
|
05de4870b0 | ||
|
|
01f0131f5d | ||
|
|
d69847c54e | ||
|
|
cc78f6f155 | ||
|
|
1e2100902c | ||
|
|
4353a9da25 | ||
|
|
e480b1bace | ||
|
|
5a96f5f64b | ||
|
|
7296b701fa | ||
|
|
a21d91d870 | ||
|
|
6931695e64 | ||
|
|
e12d02f29c | ||
|
|
404865c32e | ||
|
|
75879c47c5 | ||
|
|
f946918176 | ||
|
|
6ca3df2431 | ||
|
|
c8ec095d99 | ||
|
|
0179a55ee4 | ||
|
|
04ed1df0ef | ||
|
|
de66ee1a89 | ||
|
|
e8c4bda984 | ||
|
|
7074b75b9d | ||
|
|
857756f636 | ||
|
|
e4c62200de | ||
|
|
89ec677d54 | ||
|
|
8ff656430d | ||
|
|
db22394976 | ||
|
|
ef5548a749 | ||
|
|
14c3bb7d63 | ||
|
|
1a415b60be | ||
|
|
85fa68bd92 | ||
|
|
e41ca491ff | ||
|
|
bb5962cda0 | ||
|
|
2de878821b | ||
|
|
5bea2999ef | ||
|
|
67e9bf74a7 | ||
|
|
ed42012058 | ||
|
|
9b7c9e4a81 | ||
|
|
85daacdf7a | ||
|
|
17ea41fdae | ||
|
|
ffd2a18837 | ||
|
|
5d7f38f99f | ||
|
|
e762267e03 | ||
|
|
a71870de28 | ||
|
|
7eba0b85f4 | ||
|
|
30a45ee78e | ||
|
|
ca9cd36067 | ||
|
|
1d5a208896 | ||
|
|
60e2938b58 | ||
|
|
89540172b2 | ||
|
|
bbb716723f | ||
|
|
842cd17979 | ||
|
|
e0e32efd26 | ||
|
|
a127fcd056 | ||
|
|
c614af2cd9 | ||
|
|
c2abff6e6d | ||
|
|
4444d2ee6a | ||
|
|
463bc1374c | ||
|
|
d9a60fc2ef | ||
|
|
22a3b227a3 | ||
|
|
12f3f1a45c | ||
|
|
84d4c2944c | ||
|
|
0a9b918c75 | ||
|
|
8ddf200ce7 | ||
|
|
207ff98211 | ||
|
|
1fb09a9c8c | ||
|
|
67f9b22c86 | ||
|
|
8b5cf0c696 | ||
|
|
26d9cc56d3 | ||
|
|
930a9c8bca | ||
|
|
51a9bd9e56 | ||
|
|
ac12bd0b8f | ||
|
|
d7651d1504 | ||
|
|
7e1f996079 | ||
|
|
1af4a9abb4 | ||
|
|
ed7c9348b7 | ||
|
|
ccf4ed1235 | ||
|
|
b22ee67612 | ||
|
|
b5a953b16c | ||
|
|
7613f02eff | ||
|
|
78a3dd68ea | ||
|
|
afc0e25b26 | ||
|
|
82e14eef35 | ||
|
|
81e9c9807f | ||
|
|
02e2b53a1d | ||
|
|
babe9b6f54 | ||
|
|
52f198481b | ||
|
|
252187f1fe | ||
|
|
99812c33e7 | ||
|
|
97c5f6009d | ||
|
|
5e15f8683e | ||
|
|
fba1f7ae05 | ||
|
|
865e5ae3a3 | ||
|
|
1af98835b1 | ||
|
|
6eadf67add | ||
|
|
f3f280d008 | ||
|
|
aecbe6d316 | ||
|
|
63419d7ca9 | ||
|
|
3480a1d60e | ||
|
|
190712e250 | ||
|
|
a662330b1b | ||
|
|
04ee1d137d | ||
|
|
27f421587e | ||
|
|
f9f0bd8685 | ||
|
|
53b12f50a7 | ||
|
|
63d49463da | ||
|
|
549017d035 | ||
|
|
45feef5884 | ||
|
|
24592cc696 | ||
|
|
c640c550fd | ||
|
|
0565b7b8c8 | ||
|
|
1691c74727 | ||
|
|
f6be3eacfc | ||
|
|
790df903ac | ||
|
|
25e6f72921 | ||
|
|
ab1015b11e | ||
|
|
55e990f71d | ||
|
|
40a8150519 | ||
|
|
87744302ba | ||
|
|
17083dc5e6 | ||
|
|
b29616fbd8 | ||
|
|
468688615f | ||
|
|
f4faee4283 | ||
|
|
62c85274a3 | ||
|
|
db2917193e | ||
|
|
705571de8c | ||
|
|
2ee29683a7 | ||
|
|
51395dda91 | ||
|
|
9babef0095 | ||
|
|
e9545c9a7f | ||
|
|
619214e462 | ||
|
|
31b600686a | ||
|
|
bccc4e8019 | ||
|
|
7039a4d762 | ||
|
|
7b7f0115e5 | ||
|
|
24e79b3f4e | ||
|
|
5c70b2b307 | ||
|
|
65a8de7845 | ||
|
|
44d2297546 | ||
|
|
a41280707e | ||
|
|
a8f2fd66ae | ||
|
|
7e8ddbadfb | ||
|
|
80aeb3677d | ||
|
|
f92bbdaefa | ||
|
|
fc73f16425 | ||
|
|
c1f47f536d | ||
|
|
9166c82dc2 | ||
|
|
3decc8b9b1 | ||
|
|
bac5da30e7 | ||
|
|
baf379c6d7 | ||
|
|
e9b6cdb37a | ||
|
|
9d36d2c749 | ||
|
|
5945ab1a0a | ||
|
|
40319a66ff | ||
|
|
754aef8a84 | ||
|
|
0613b530e8 | ||
|
|
5e9819b96f | ||
|
|
b46e334a40 | ||
|
|
af49845ae6 | ||
|
|
4cb8241334 | ||
|
|
530e6cb20e | ||
|
|
e0adc03588 | ||
|
|
e48f6e6d9b | ||
|
|
04ff4df5d7 | ||
|
|
d789e96d79 | ||
|
|
45761fd48b | ||
|
|
cb6a47a5d9 | ||
|
|
67dbdfd80d | ||
|
|
dee99c1752 | ||
|
|
a0c7e187f5 | ||
|
|
938503bd56 | ||
|
|
33bda6fd16 | ||
|
|
929336cb57 | ||
|
|
883aca038b | ||
|
|
77e03dc18d | ||
|
|
230ed1ab11 | ||
|
|
b31fa856d0 | ||
|
|
98b97b9898 | ||
|
|
41cf7c6814 | ||
|
|
da3a2f436c | ||
|
|
569a7178d7 | ||
|
|
7e7497c3bd | ||
|
|
905c78d5a3 | ||
|
|
37b1cb009a | ||
|
|
56586e1fda | ||
|
|
2040fcdba4 | ||
|
|
d24b57ae86 | ||
|
|
db72102de7 | ||
|
|
e8801a75f3 | ||
|
|
918826ff48 | ||
|
|
fa2fe5c941 | ||
|
|
8ef2761f53 | ||
|
|
9375369b88 | ||
|
|
ce77c82b0c | ||
|
|
1e39ae2f1e | ||
|
|
c143894547 | ||
|
|
37450ff00c | ||
|
|
ca9c468edd | ||
|
|
d6570d1496 | ||
|
|
bf677522a9 | ||
|
|
fd89f71fc0 | ||
|
|
83477ece18 | ||
|
|
32990794ce | ||
|
|
4b5bae4f9b | ||
|
|
2b07917020 | ||
|
|
338acb8fc2 | ||
|
|
2a4b228e19 | ||
|
|
c6c3ab94b1 | ||
|
|
8671516b95 | ||
|
|
5710ab47ae | ||
|
|
e3b0eb29f1 | ||
|
|
795594b6a6 | ||
|
|
e91da53d9e | ||
|
|
f807df84d8 | ||
|
|
7f32d5741d | ||
|
|
30c7113bd8 | ||
|
|
a63732027f | ||
|
|
13d8f51f6a | ||
|
|
5d48ed5fb4 | ||
|
|
4b89b3e2ed | ||
|
|
1ee24517e3 | ||
|
|
64e35c734e | ||
|
|
08130e8088 | ||
|
|
0c5937805b | ||
|
|
d315829eaf | ||
|
|
6dad1c3bbb | ||
|
|
3577c11c89 | ||
|
|
8326c223ab | ||
|
|
73de5f78fe | ||
|
|
4e59b85073 | ||
|
|
9af26db57a | ||
|
|
8e4ca8e474 | ||
|
|
79de3976bf | ||
|
|
4b80f13373 | ||
|
|
6210c6dbf4 | ||
|
|
97592eede6 | ||
|
|
73dafa6aff | ||
|
|
6c3e121b6c | ||
|
|
95ee7fb49f | ||
|
|
b3f73eace1 | ||
|
|
07a497362a | ||
|
|
afa078d00c | ||
|
|
3fd7d9a604 | ||
|
|
80a0d2d8d8 | ||
|
|
27f4fdd179 | ||
|
|
d1a94a91c2 | ||
|
|
69a31dcdd9 | ||
|
|
a2a6bf87f7 | ||
|
|
bd1e95b655 | ||
|
|
278f9bfc03 | ||
|
|
a3a8950afd | ||
|
|
f95913e623 | ||
|
|
8e4b51fba4 | ||
|
|
84915a1843 | ||
|
|
4b0e915698 | ||
|
|
b2e81b5d17 | ||
|
|
ef47f3fd15 | ||
|
|
f88f72abd2 | ||
|
|
715c14b78d | ||
|
|
4af7da3451 | ||
|
|
63ff572076 | ||
|
|
129af904f6 | ||
|
|
8cc71d2b47 | ||
|
|
0b299b2fe7 | ||
|
|
b1cef5f73d | ||
|
|
42067ce53c | ||
|
|
2bdf12fb67 | ||
|
|
c00b138bf2 | ||
|
|
1155eaf1f1 | ||
|
|
52f2e193d6 | ||
|
|
f5619a9b29 | ||
|
|
057608bac0 | ||
|
|
57465eb277 | ||
|
|
01e04d60a9 | ||
|
|
be8d9be832 | ||
|
|
07d07020f0 | ||
|
|
7c1f7e7a23 | ||
|
|
a3f6fee41f | ||
|
|
0414ec7f83 | ||
|
|
12af2a7ff6 | ||
|
|
4d6881fa65 | ||
|
|
019e8e0d14 | ||
|
|
763bd775c4 | ||
|
|
585e07bc79 | ||
|
|
b911d8d075 | ||
|
|
d583122c64 | ||
|
|
3968877b1e | ||
|
|
46f03de9f6 | ||
|
|
0e18ec022c | ||
|
|
64117ab613 | ||
|
|
038e04dee6 | ||
|
|
b49c7b8609 | ||
|
|
948949c571 | ||
|
|
f173a79a0d | ||
|
|
994791add6 | ||
|
|
d177e71b46 | ||
|
|
fcab1501f8 | ||
|
|
eb022220f4 | ||
|
|
f48687528e | ||
|
|
9007f9de9e | ||
|
|
55d84d0f9b | ||
|
|
90b4d688f8 | ||
|
|
aacd42f4bc | ||
|
|
51d7dda5a7 | ||
|
|
1c32acf7b6 | ||
|
|
22c73f3c12 | ||
|
|
9613ea9018 | ||
|
|
3d4802ac68 | ||
|
|
59c9bdb3a5 | ||
|
|
d7953eb779 | ||
|
|
48a7c48f7b | ||
|
|
7a919fbac4 | ||
|
|
181220621e | ||
|
|
249c45dfe2 | ||
|
|
b19d84f1a7 | ||
|
|
865edb70c2 | ||
|
|
e78369f0fa | ||
|
|
d40a6a5c3f | ||
|
|
cb7768d095 | ||
|
|
4290516d29 | ||
|
|
6a7a2301ee | ||
|
|
9a79c58e33 | ||
|
|
4c39c1ec30 | ||
|
|
571cb8b44f | ||
|
|
4207792ffd | ||
|
|
f5c4f98834 | ||
|
|
9f67282a79 | ||
|
|
ee71c1cf0d | ||
|
|
06f2284bcd | ||
|
|
8cbe79655a | ||
|
|
a4c1d733b7 | ||
|
|
839649d42f | ||
|
|
504e2aac4a | ||
|
|
eafb41602c | ||
|
|
2dcc4172c4 | ||
|
|
f96a711298 | ||
|
|
ad28b9b339 | ||
|
|
8dd8536f6b | ||
|
|
7bf5b2ec57 | ||
|
|
aa731aa894 | ||
|
|
c58cb257dc | ||
|
|
06f59cf853 | ||
|
|
83b4b5434f | ||
|
|
9de5214a2f | ||
|
|
f08067bab2 | ||
|
|
1160f39cb0 | ||
|
|
d633ecd160 | ||
|
|
4cea313060 | ||
|
|
9b7f8076eb | ||
|
|
571259f241 | ||
|
|
607ee8bbc1 | ||
|
|
36d2f74887 | ||
|
|
cdaf409a99 | ||
|
|
fba487d8a2 | ||
|
|
3ab7306199 | ||
|
|
2e4e94d5f8 | ||
|
|
3348ed3524 | ||
|
|
942a21b4be | ||
|
|
9c14618d55 | ||
|
|
7d50551392 | ||
|
|
f2c1a92513 | ||
|
|
fe6595cd2a | ||
|
|
c2aac916aa | ||
|
|
e161b5387b | ||
|
|
585e5cd88f | ||
|
|
1637ffc5dc | ||
|
|
a28797ee03 | ||
|
|
49e28f9d1e | ||
|
|
4a7cd664fd | ||
|
|
253e11d55b | ||
|
|
eb1c1c78d4 | ||
|
|
0b0d64b52e | ||
|
|
1ae51ef5ea | ||
|
|
de1e3230f5 | ||
|
|
1fbc038e64 | ||
|
|
cd63dd429b | ||
|
|
fbfdf561fc | ||
|
|
83d5a84edd | ||
|
|
5abf02c6d1 | ||
|
|
b8037845d6 | ||
|
|
c80e2552b2 | ||
|
|
1a1fea535b | ||
|
|
5c7da4b686 | ||
|
|
b6ee89a6d8 | ||
|
|
2d8e6bd980 | ||
|
|
a173d61464 | ||
|
|
8f04a136c8 | ||
|
|
b7675e1ec7 | ||
|
|
964fbfe2bb | ||
|
|
8fb8956c0d | ||
|
|
c11920ac08 | ||
|
|
9a4eb26246 | ||
|
|
0d9958afe7 | ||
|
|
d6dd74b50a | ||
|
|
d5437ca8fa | ||
|
|
14720057c2 | ||
|
|
170ed8cc01 | ||
|
|
25576eb35a | ||
|
|
66cb1fb6ad | ||
|
|
bcc65fd879 | ||
|
|
99440585e6 | ||
|
|
290d69d14a | ||
|
|
4fce06677f | ||
|
|
f53cd8b5b6 | ||
|
|
da59f47624 | ||
|
|
521586f08f | ||
|
|
f39a7ada7c | ||
|
|
bae9f46d8b | ||
|
|
d7ea24e218 | ||
|
|
e621d7e601 | ||
|
|
aa6eff4c54 | ||
|
|
f36583e676 | ||
|
|
0a0a91d4b2 | ||
|
|
6c70f9e308 | ||
|
|
b25c3d8b67 | ||
|
|
bade99d069 | ||
|
|
776b51fef7 | ||
|
|
da2d014f00 | ||
|
|
7fdf83089d | ||
|
|
043aafd7b7 | ||
|
|
3254979568 | ||
|
|
6fd202fe36 | ||
|
|
5f00f1e18e | ||
|
|
c940ce3329 | ||
|
|
2366e2b209 | ||
|
|
2b7fd3c9d1 | ||
|
|
d3e37d1716 | ||
|
|
d2b858c997 | ||
|
|
de34c7580f | ||
|
|
bcb492751c | ||
|
|
e26cc79819 | ||
|
|
98cb2d4c17 | ||
|
|
2fc569715c | ||
|
|
3eb594df43 | ||
|
|
8243019a60 | ||
|
|
5a10f7fcfe | ||
|
|
5e89caf358 | ||
|
|
35b40ef650 | ||
|
|
56b7d6cb7c | ||
|
|
8b8a890ac9 | ||
|
|
5645bcee2d | ||
|
|
a631707db4 | ||
|
|
451ffafb9e | ||
|
|
b5274a0d91 | ||
|
|
db4dc03abc | ||
|
|
6be5bcc4c8 | ||
|
|
21efda4a84 | ||
|
|
082375f129 | ||
|
|
1204859263 | ||
|
|
c8b5d1561e | ||
|
|
6912e77d25 | ||
|
|
d84d096e7e | ||
|
|
29c17fd32e | ||
|
|
d721320af5 | ||
|
|
efef9c864c | ||
|
|
27cb837b08 | ||
|
|
047fcbe63f | ||
|
|
dbe0b1551b | ||
|
|
8f7b047b7a | ||
|
|
a38ace0df9 | ||
|
|
0b0b06e8b9 | ||
|
|
f83b61903a | ||
|
|
881fa41bb7 | ||
|
|
f9442db96f | ||
|
|
64521494ce | ||
|
|
e75e3399ab | ||
|
|
e5ef498164 | ||
|
|
24e4be77d8 | ||
|
|
0d55f2ef32 | ||
|
|
8ec3371139 | ||
|
|
ccca4d2914 | ||
|
|
28704a6164 | ||
|
|
cf4ba9d1d3 | ||
|
|
c69e30c146 | ||
|
|
fd32d75d3b | ||
|
|
afa228fd91 | ||
|
|
a01a7ae5fc | ||
|
|
64b071f277 | ||
|
|
af246ad0d7 | ||
|
|
56a87329ec | ||
|
|
eddddc694d | ||
|
|
ce61138351 | ||
|
|
564662ee00 | ||
|
|
678db837fd | ||
|
|
c789f4230d | ||
|
|
1b9e451a6f | ||
|
|
1780b343b4 | ||
|
|
aea3181d27 | ||
|
|
c44461e33f | ||
|
|
221b9bc149 | ||
|
|
dc41c6bc0d | ||
|
|
828d937dec | ||
|
|
cf889cfe25 | ||
|
|
6bab2523d5 | ||
|
|
d714b5c592 | ||
|
|
08316496cd | ||
|
|
d5fd985f0d | ||
|
|
eab7839195 | ||
|
|
18717dd6f5 | ||
|
|
d249f411f8 | ||
|
|
b85e2545d6 | ||
|
|
79280b195e | ||
|
|
4a18728e19 | ||
|
|
b7498416fa | ||
|
|
49b201db0f | ||
|
|
be4d6761b1 | ||
|
|
c01ba1a3cb | ||
|
|
af59ff3209 | ||
|
|
b0a37c6ac5 | ||
|
|
8b3fd9d1e9 | ||
|
|
95b16690e0 | ||
|
|
f6b865a052 | ||
|
|
d1c756306a | ||
|
|
ad5af8e123 | ||
|
|
ba89285c74 | ||
|
|
43c0c2ec2a | ||
|
|
a277104ad5 | ||
|
|
84afffc761 | ||
|
|
5e5680fd13 | ||
|
|
727da38fb6 | ||
|
|
79096cfdce | ||
|
|
a848f82b8f | ||
|
|
71bdd4608b | ||
|
|
f04a948152 | ||
|
|
15be3e52ae | ||
|
|
b1003e954e | ||
|
|
f2b9a7ff0c | ||
|
|
19ad9ab224 | ||
|
|
8eae8a4fb5 | ||
|
|
85fbe38e71 | ||
|
|
e896fd1fd6 | ||
|
|
916150de01 | ||
|
|
732204f11b | ||
|
|
1df50ff855 | ||
|
|
11042858b8 | ||
|
|
89ca2319f5 | ||
|
|
2f4fd310bd | ||
|
|
6d7919ad85 | ||
|
|
59467c906d | ||
|
|
def871ac89 | ||
|
|
6fe5a93a73 | ||
|
|
7796c9269c | ||
|
|
ec150d4a4c | ||
|
|
49abff1609 | ||
|
|
be59c16aad | ||
|
|
f1144f3a7e | ||
|
|
9ebff816dc | ||
|
|
4c3eacd745 | ||
|
|
325e402d0f | ||
|
|
251587cb86 | ||
|
|
9fb1f8acf8 | ||
|
|
cffbc76da1 | ||
|
|
be51025048 | ||
|
|
ae6f9fc87c | ||
|
|
e61a7bff65 | ||
|
|
bb14881b63 | ||
|
|
a7f1bfa7c9 | ||
|
|
7b3384a6be | ||
|
|
efa8717fc5 | ||
|
|
9e42cee87c | ||
|
|
9fe30b905b | ||
|
|
2fc9afa4f4 | ||
|
|
732c8b1f7f | ||
|
|
19be3bc55c | ||
|
|
8a7e2577aa | ||
|
|
e32494879c | ||
|
|
ac4803961a | ||
|
|
de8d6d3c8c | ||
|
|
392b80fe14 | ||
|
|
9fa75a8b45 | ||
|
|
b19097ab8f | ||
|
|
31624b32e9 | ||
|
|
b8b6558f53 | ||
|
|
a53e75aeaa | ||
|
|
7798004568 | ||
|
|
63873575a5 | ||
|
|
9845df4d1b | ||
|
|
462d5f5d05 | ||
|
|
1d860923d0 | ||
|
|
c9a3fac654 | ||
|
|
a1c9685b49 | ||
|
|
c16c4aac44 | ||
|
|
e80ff9c551 | ||
|
|
3176ccc6e3 | ||
|
|
b24196be36 | ||
|
|
52365a9755 | ||
|
|
41bea9f50c | ||
|
|
3416c7bb3c | ||
|
|
ce126b11fb | ||
|
|
99db8fc3fe | ||
|
|
780cec2596 | ||
|
|
d3b4cb71c0 | ||
|
|
1758c3e3f2 | ||
|
|
995fa7d6fd | ||
|
|
87abe426d8 | ||
|
|
bec0b46a2c | ||
|
|
a88ddc2a4d | ||
|
|
1f60578a63 | ||
|
|
2f70489e22 | ||
|
|
3b75734672 | ||
|
|
ff4b35d6f1 | ||
|
|
e5b26fdad0 | ||
|
|
bcbcf40eae | ||
|
|
661fdfb43e | ||
|
|
31f08c49e7 | ||
|
|
2999d61ac9 | ||
|
|
ca72a4b0fc | ||
|
|
164977972e | ||
|
|
b6fbfcc814 | ||
|
|
418700ce3f | ||
|
|
1d52557562 | ||
|
|
45e24c54ce | ||
|
|
abd909d23b | ||
|
|
f39932ece7 | ||
|
|
03fb649274 | ||
|
|
54e9e95076 | ||
|
|
201fb4d73e | ||
|
|
e0cc35ba66 | ||
|
|
d3818e888e | ||
|
|
a2af4a3e91 | ||
|
|
02a02fa64c | ||
|
|
9fae0d2505 | ||
|
|
e23198bbcc | ||
|
|
0a8c43901d | ||
|
|
e9054301d1 | ||
|
|
caaede7e84 | ||
|
|
3ed9e1dd51 | ||
|
|
207eccc505 | ||
|
|
45d5524df7 | ||
|
|
1f08e407d1 | ||
|
|
2c215afe33 | ||
|
|
d1d2b03dfd | ||
|
|
c1a41c6605 | ||
|
|
d1a17b39ea | ||
|
|
bf365bedfd | ||
|
|
6a1ab47a08 | ||
|
|
5fdaa6b0ee | ||
|
|
a6b0c2638a | ||
|
|
a671d08f0b | ||
|
|
5e869a5e5c | ||
|
|
0e6109ff2b | ||
|
|
0bff6ee504 | ||
|
|
7cbe429be9 | ||
|
|
09b578522f | ||
|
|
40897d0be6 | ||
|
|
f49bc088fc | ||
|
|
7795a9ead2 | ||
|
|
2c238f49e0 | ||
|
|
599789634a | ||
|
|
77359f7b83 | ||
|
|
7cff55a160 | ||
|
|
8d26eb4e07 | ||
|
|
ad5e3ebce3 | ||
|
|
2deb0e1708 | ||
|
|
b2f383f095 | ||
|
|
22ababd87a | ||
|
|
167c1fa348 | ||
|
|
3b1bf67436 | ||
|
|
d2eb73df96 | ||
|
|
4d075efcd3 | ||
|
|
8a53c56a46 | ||
|
|
73d4152d1d | ||
|
|
c0a90bd677 | ||
|
|
106157a951 | ||
|
|
ab9cf6d036 | ||
|
|
54ba6efc93 | ||
|
|
85ac4aac94 | ||
|
|
691b6611d0 | ||
|
|
1b33b4425b | ||
|
|
41defbcf9c | ||
|
|
928594fc7c | ||
|
|
cc1f668308 | ||
|
|
f2b8813fb9 | ||
|
|
5ed7c31278 | ||
|
|
13b456bffd | ||
|
|
938dee481b | ||
|
|
a69140faa9 | ||
|
|
6a5ebdb1ef | ||
|
|
ece4d083a5 | ||
|
|
96688a8ffe | ||
|
|
e9b0aa537f | ||
|
|
4052c3e817 | ||
|
|
4a6e838b18 | ||
|
|
3773f6b44f | ||
|
|
a19e836d63 | ||
|
|
aa5e5f9cc0 | ||
|
|
6647e75c77 | ||
|
|
f85a514ee3 | ||
|
|
619dd84d81 | ||
|
|
f9fdfab19e | ||
|
|
ca46d0f8e1 | ||
|
|
bb8f75b4be | ||
|
|
0db599a478 | ||
|
|
902e60fab2 | ||
|
|
87f48e2cc9 | ||
|
|
cc55073107 | ||
|
|
96c43b4607 | ||
|
|
f1b4367168 | ||
|
|
4416f8530d | ||
|
|
4e48ab2363 | ||
|
|
b5a26696f8 | ||
|
|
4307229ae0 | ||
|
|
b681f01be9 | ||
|
|
c262027728 | ||
|
|
6a08fedf18 | ||
|
|
e471b4edf5 | ||
|
|
dd86812822 | ||
|
|
ac311ab75d | ||
|
|
c9387313e2 | ||
|
|
97641dbcda | ||
|
|
54fdbcd947 | ||
|
|
7636e09284 | ||
|
|
7666ed3010 | ||
|
|
e82a9ec37a | ||
|
|
770d9e5b7c | ||
|
|
5f0e0c993e | ||
|
|
7be69b0b54 | ||
|
|
251beb7f9b | ||
|
|
1c27cbd90a | ||
|
|
4b4b26651a | ||
|
|
1a6ba8c230 | ||
|
|
06904506d4 | ||
|
|
62a28825f8 | ||
|
|
c6c693acd2 | ||
|
|
8d04454457 | ||
|
|
aeb831eeff | ||
|
|
67db78ad66 | ||
|
|
06809ab5fc | ||
|
|
08ba911738 | ||
|
|
59f4b6788a | ||
|
|
a317a4d689 | ||
|
|
6e164e61aa | ||
|
|
2098bf84a1 | ||
|
|
860a83ba90 | ||
|
|
abce5fd120 | ||
|
|
0243e9c5be | ||
|
|
8a4a0154f6 | ||
|
|
469a5221ed | ||
|
|
f251b9c6c5 | ||
|
|
c4228be86c | ||
|
|
94e565aa00 | ||
|
|
cc6e028b1d | ||
|
|
33a69abece | ||
|
|
6a4947533f | ||
|
|
879a31f51e | ||
|
|
49fc87e295 | ||
|
|
fe89f1f096 | ||
|
|
346681ba27 | ||
|
|
13e13cd5a8 | ||
|
|
0f8aad52b2 | ||
|
|
b6a5cbf956 | ||
|
|
a482d4db5f | ||
|
|
df15dceaef | ||
|
|
9f2e192993 | ||
|
|
d62f36c6a0 | ||
|
|
2427724868 | ||
|
|
9b35d8f8e1 | ||
|
|
a859f4524c | ||
|
|
8be896aebb | ||
|
|
a008cf971d | ||
|
|
316077fffb | ||
|
|
4373037071 | ||
|
|
24e81c873c | ||
|
|
9e4a3905a0 | ||
|
|
b54b4a6580 | ||
|
|
f33a9c3941 | ||
|
|
d792798963 | ||
|
|
e5af4f6299 | ||
|
|
ef5bd9dc61 | ||
|
|
8834feac65 | ||
|
|
2f70dd732d |
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*.js, *.css, *.tpl]
|
||||
indent_style = tab
|
||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,15 +1,21 @@
|
||||
#################
|
||||
## npm
|
||||
#################
|
||||
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
sftp-config.json
|
||||
config.json
|
||||
public/src/nodebb.min.js
|
||||
public/config.json
|
||||
public/css/*.css
|
||||
public/themes/*
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
plugins/*
|
||||
.project
|
||||
.project
|
||||
.idea
|
||||
*.swp
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
provision.sh
|
||||
*.komodoproject
|
||||
|
||||
feeds/recent.rss
|
||||
|
||||
# winston?
|
||||
error.log
|
||||
|
||||
17
.jsbeautifyrc
Normal file
17
.jsbeautifyrc
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"indent_size": 4,
|
||||
"indent_char": " ",
|
||||
"indent_level": 0,
|
||||
"indent_with_tabs": true,
|
||||
"preserve_newlines": true,
|
||||
"max_preserve_newlines": 10,
|
||||
"jslint_happy": true,
|
||||
"brace_style": "collapse",
|
||||
"keep_array_indentation": false,
|
||||
"keep_function_indentation": false,
|
||||
"space_before_conditional": true,
|
||||
"break_chained_methods": false,
|
||||
"eval_code": false,
|
||||
"unescape_strings": false,
|
||||
"wrap_line_length": 0
|
||||
}
|
||||
86
.jshintrc
Normal file
86
.jshintrc
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
// JSHint Default Configuration File (as on JSHint website)
|
||||
// See http://jshint.com/docs/ for more details
|
||||
|
||||
"maxerr" : 50, // {int} Maximum error before stopping
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"indent" : 4, // {int} Number of spaces to use for indentation
|
||||
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : false, // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : false, // true: Require all defined variables be used TODO: Set this to true, update codebase.
|
||||
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||
"trailing" : false, // true: Prohibit trailing whitespaces
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : false, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||
// (ex: `for each`, multiple try/catch, function expression…)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
// Environments
|
||||
"browser" : true, // Web Browser (window, document, etc)
|
||||
"couch" : false, // CouchDB
|
||||
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||
"dojo" : false, // Dojo Toolkit
|
||||
"jquery" : true, // jQuery
|
||||
"mootools" : false, // MooTools
|
||||
"node" : true, // Node.js
|
||||
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||
"prototypejs" : false, // Prototype and Scriptaculous
|
||||
"rhino" : false, // Rhino
|
||||
"worker" : false, // Web Workers
|
||||
"wsh" : false, // Windows Scripting Host
|
||||
"yui" : false, // Yahoo User Interface
|
||||
|
||||
// Legacy
|
||||
"nomen" : false, // true: Prohibit dangling `_` in variables
|
||||
"onevar" : false, // true: Allow only one `var` statement per function
|
||||
"passfail" : false, // true: Stop on first error
|
||||
"white" : false, // true: Check against strict whitespace and indentation rules
|
||||
|
||||
// Custom Globals
|
||||
"globals" : {} // additional predefined global variables
|
||||
}
|
||||
26
README.md
26
README.md
@@ -1,12 +1,16 @@
|
||||
Please support NodeBB development! Check out our IndieGoGo campaign and like, share, and follow us :)
|
||||
[NodeBB Homepage](http://www.nodebb.org/ "NodeBB") # [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter") # [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
|
||||
# NodeBB
|
||||
**NodeBB** is a robust Node.js driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8.
|
||||
|
||||

|
||||
* [NodeBB Homepage](http://www.nodebb.org/ "NodeBB")
|
||||
* [Demo & Meta Discussion](http://try.nodebb.org)
|
||||
* [Wiki Guides](https://github.com/designcreateplay/NodeBB/wiki) - includes setup for other platforms
|
||||
* [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/nodebb) - #nodebb on Freenode
|
||||
* [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?
|
||||
|
||||
@@ -16,7 +20,11 @@ Please support NodeBB development! Check out our IndieGoGo campaign and like, sh
|
||||
|
||||
## Requirements
|
||||
|
||||
NodeBB requires a version of Node.js at least 0.8 or greater, and a Redis version 2.6 or greater.
|
||||
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 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
|
||||
|
||||
@@ -24,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
|
||||
@@ -54,3 +64,7 @@ NodeBB can also be started with helper programs, such as `supervisor` and `forev
|
||||
*(Optional)* Some server configurations may install the node binary as `nodejs` instead of `node`. You can re-map it (so as to not break compatibility with `node-supervisor`) by running the following command:
|
||||
|
||||
# update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
|
||||
|
||||
## Upgrading NodeBB
|
||||
|
||||
Detailed upgrade instructions are listed in [Upgrading NodeBB](https://github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB)
|
||||
|
||||
257
app.js
257
app.js
@@ -16,145 +16,170 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Configuration setup
|
||||
nconf = require('nconf');
|
||||
nconf.argv().file({ file: __dirname + '/config.json'});
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var fs = require('fs'),
|
||||
winston = require('winston'),
|
||||
pkg = require('./package.json'),
|
||||
url = require('url'),
|
||||
meta = require('./src/meta.js');
|
||||
// Configuration setup
|
||||
var nconf = require('nconf');
|
||||
nconf.argv().env();
|
||||
|
||||
// Runtime environment
|
||||
global.env = process.env.NODE_ENV || 'production',
|
||||
var fs = require('fs'),
|
||||
async = require('async'),
|
||||
semver = require('semver'),
|
||||
winston = require('winston'),
|
||||
pkg = require('./package.json'),
|
||||
path = require('path'),
|
||||
meta;
|
||||
|
||||
// Runtime environment
|
||||
global.env = process.env.NODE_ENV || 'production';
|
||||
|
||||
|
||||
winston.remove(winston.transports.Console);
|
||||
winston.add(winston.transports.Console, {
|
||||
colorize:true
|
||||
});
|
||||
|
||||
winston.add(winston.transports.File, {
|
||||
filename:'error.log',
|
||||
level:'error'
|
||||
})
|
||||
|
||||
// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed
|
||||
winston.err = function(err) {
|
||||
winston.error(err.stack);
|
||||
};
|
||||
|
||||
// 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.');
|
||||
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
winston.info('===');
|
||||
|
||||
|
||||
|
||||
if(nconf.get('upgrade')) {
|
||||
meta.configs.init(function() {
|
||||
require('./src/upgrade').upgrade();
|
||||
winston.remove(winston.transports.Console);
|
||||
winston.add(winston.transports.Console, {
|
||||
colorize: true
|
||||
});
|
||||
} else if (!nconf.get('setup') && nconf.get('base_url')) {
|
||||
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/');
|
||||
|
||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
winston.info('Base Configuration OK.');
|
||||
winston.add(winston.transports.File, {
|
||||
filename: 'error.log',
|
||||
level: 'error'
|
||||
});
|
||||
|
||||
meta.configs.init(function() {
|
||||
// Initial setup for Redis & Reds
|
||||
var reds = require('reds');
|
||||
RDB = require('./src/redis.js');
|
||||
reds.createClient = function() {
|
||||
return reds.client || (reds.client = RDB);
|
||||
// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed
|
||||
winston.err = function (err) {
|
||||
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.');
|
||||
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
winston.info('');
|
||||
|
||||
|
||||
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');
|
||||
|
||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||
nconf.set('base_dir', __dirname);
|
||||
|
||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
winston.info('NodeBB instance bound to: ' + ((nconf.get('bind_address') === "0.0.0.0" || !nconf.get('bind_address')) ? 'Any address (0.0.0.0)' : nconf.get('bind_address')));
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
winston.info('Base Configuration OK.');
|
||||
}
|
||||
|
||||
var categories = require('./src/categories.js'),
|
||||
templates = require('./public/src/templates.js'),
|
||||
webserver = require('./src/webserver.js'),
|
||||
websockets = require('./src/websockets.js'),
|
||||
plugins = require('./src/plugins'),
|
||||
admin = {
|
||||
'categories': require('./src/admin/categories.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.')
|
||||
}
|
||||
|
||||
DEVELOPMENT = true;
|
||||
require('./src/database').init(function(err) {
|
||||
meta.configs.init(function () {
|
||||
|
||||
global.configuration = {};
|
||||
global.templates = {};
|
||||
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');
|
||||
|
||||
(function(config) {
|
||||
config['ROOT_DIRECTORY'] = __dirname;
|
||||
upgrade.check(function(schema_ok) {
|
||||
if (schema_ok || nconf.get('check-schema') === false) {
|
||||
websockets.init(SocketIO);
|
||||
|
||||
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',
|
||||
plugins.init();
|
||||
global.templates = {};
|
||||
global.translator = translator;
|
||||
|
||||
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
||||
]);
|
||||
translator.loadServer();
|
||||
|
||||
templates.ready(webserver.init);
|
||||
var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false;
|
||||
|
||||
//setup scripts to be moved outside of the app in future.
|
||||
function setup_categories() {
|
||||
winston.info('Checking categories...');
|
||||
categories.getAllCategories(function(data) {
|
||||
if (data.categories.length === 0) {
|
||||
winston.info('Setting up default categories...');
|
||||
// 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',
|
||||
|
||||
fs.readFile(config.ROOT_DIRECTORY + '/install/data/categories.json', function(err, default_categories) {
|
||||
default_categories = JSON.parse(default_categories);
|
||||
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
||||
], customTemplates);
|
||||
|
||||
for (var category in default_categories) {
|
||||
admin.categories.create(default_categories[category]);
|
||||
}
|
||||
|
||||
plugins.ready(function() {
|
||||
templates.ready(webserver.init);
|
||||
});
|
||||
|
||||
|
||||
winston.info('Hardcoding uid 1 as an admin');
|
||||
var user = require('./src/user.js');
|
||||
user.makeAdministrator(1);
|
||||
|
||||
|
||||
notifications.init();
|
||||
} else {
|
||||
winston.info('Categories OK. Found ' + data.categories.length + ' categories.');
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup_categories();
|
||||
}(global.configuration));
|
||||
});
|
||||
|
||||
} else {
|
||||
// New install, ask setup questions
|
||||
if (nconf.get('setup')) winston.info('NodeBB Setup Triggered via Command Line');
|
||||
else winston.info('Configuration not found, starting NodeBB setup');
|
||||
|
||||
var install = require('./src/install');
|
||||
|
||||
process.stdout.write(
|
||||
"\nWelcome to NodeBB!\nThis looks like a new installation, so you'll have to answer a " +
|
||||
"few questions about your environment before we can proceed.\n\n" +
|
||||
"Press enter to accept the default setting (shown in brackets).\n\n\n"
|
||||
);
|
||||
|
||||
install.setup(function(err) {
|
||||
if (err) {
|
||||
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||
});
|
||||
});
|
||||
} 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');
|
||||
} else {
|
||||
if (!nconf.get('setup')) {
|
||||
process.stdout.write(
|
||||
"Please start NodeBB again and register a new user. This user will automatically become an administrator.\n\n"
|
||||
);
|
||||
}
|
||||
winston.warn('Configuration not found, starting NodeBB setup');
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
});
|
||||
|
||||
var install = require('./src/install');
|
||||
|
||||
winston.info('Welcome to NodeBB!');
|
||||
winston.info('This looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.');
|
||||
winston.info('Press enter to accept the default setting (shown in brackets).');
|
||||
|
||||
install.setup(function (err) {
|
||||
if (err) {
|
||||
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||
} else {
|
||||
winston.info('NodeBB Setup Completed. Run \'node app\' to manually start your NodeBB server.');
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
|
||||
} else if (nconf.get('upgrade')) {
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
});
|
||||
require('./src/database').init(function(err) {
|
||||
meta = require('./src/meta.js');
|
||||
|
||||
meta.configs.init(function () {
|
||||
require('./src/upgrade').upgrade();
|
||||
});
|
||||
});
|
||||
} else/* if (nconf.get('help') */{
|
||||
winston.info('Usage: node app [options] [arguments]');
|
||||
winston.info(' [NODE_ENV=development | NODE_ENV=production] node app [--start] [arguments]');
|
||||
winston.info('');
|
||||
winston.info('Options:');
|
||||
winston.info(' --help displays this usage information');
|
||||
winston.info(' --setup configure your environment and setup NodeBB');
|
||||
winston.info(' --upgrade upgrade NodeBB, first read: github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB');
|
||||
winston.info(' --start manually start NodeBB (default when no options are given)');
|
||||
};
|
||||
}());
|
||||
|
||||
2
feeds/categories/.gitignore
vendored
2
feeds/categories/.gitignore
vendored
@@ -1 +1 @@
|
||||
*.rss
|
||||
*.rss
|
||||
2
feeds/topics/.gitignore
vendored
2
feeds/topics/.gitignore
vendored
@@ -1 +1 @@
|
||||
*.rss
|
||||
*.rss
|
||||
@@ -1,74 +1,98 @@
|
||||
[
|
||||
{
|
||||
"name": "Announcements",
|
||||
"description": "A place to talk about whateeeever you want",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-bullhorn"
|
||||
"description": "Announcements regarding our community",
|
||||
"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": "Bugs? Dont worry, we dont read this thread, so post them here.",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-github"
|
||||
"description": "NodeBB development news and announcements",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-github",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"name": "Blogs",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-pencil"
|
||||
"description": "Blog posts from individual members",
|
||||
"bgColor": "#0059B2",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-pencil",
|
||||
"order": 4
|
||||
},
|
||||
{
|
||||
"name": "Feature Requests",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-lightbulb"
|
||||
"description": "Got a feature request you'd like to see? Give us a shout here.",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-lightbulb-o",
|
||||
"order": 5
|
||||
},
|
||||
{
|
||||
"name": "Bug Reports",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-cogs"
|
||||
"description": "Having trouble with NodeBB? Let us know...",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-cogs",
|
||||
"order": 6
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Addons",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-plus-sign"
|
||||
"name": "NodeBB Plugins",
|
||||
"description": "Enhance your NodeBB with plugins!",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-plus-square",
|
||||
"order": 7
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Link Exchange",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-exchange"
|
||||
"description": "Link exchange",
|
||||
"bgColor": "#ab1290",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-exchange",
|
||||
"order": 8
|
||||
},
|
||||
{
|
||||
"name": "News",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-globe"
|
||||
"description": "News from around the world",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-globe",
|
||||
"order": 9
|
||||
},
|
||||
{
|
||||
"name": "Movies",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-film"
|
||||
"description": "Discuss the latest movies here",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-film",
|
||||
"order": 10
|
||||
},
|
||||
{
|
||||
"name": "Games",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-screenshot"
|
||||
"description": "Discuss the latest games here",
|
||||
"bgColor": "#004C66",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-crosshairs",
|
||||
"order": 11
|
||||
},
|
||||
{
|
||||
"name": "Random",
|
||||
"description": "In future an example of how a hidden category should look like.",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-beer"
|
||||
"description": "Anything and (almost) everything welcome!",
|
||||
"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));
|
||||
58
nodebb
58
nodebb
@@ -1,6 +1,54 @@
|
||||
#!/bin/bash
|
||||
clear
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1
|
||||
|
||||
# $0 script path
|
||||
# $1 action
|
||||
# $2 subaction
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
node app
|
||||
;;
|
||||
|
||||
dev)
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development node app
|
||||
;;
|
||||
|
||||
watch)
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||
NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- app $1
|
||||
;;
|
||||
|
||||
language)
|
||||
case "$2" in
|
||||
check)
|
||||
node app --language="check"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Language Settings"
|
||||
echo $"Usage: $0 language {check}"
|
||||
echo ''
|
||||
column -s ' ' -t <<< '
|
||||
check Compare language files against the /en directory
|
||||
'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Welcome to NodeBB"
|
||||
echo $"Usage: $0 {start|dev|watch|language}"
|
||||
echo ''
|
||||
column -s ' ' -t <<< '
|
||||
start Start NodeBB in production mode
|
||||
dev Start NodeBB in development mode
|
||||
watch Start NodeBB in development mode and watch for changes
|
||||
language Language settings
|
||||
'
|
||||
exit 1
|
||||
esac
|
||||
|
||||
53
package.json
53
package.json
@@ -2,21 +2,22 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.6",
|
||||
"version": "0.2.0",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/designcreateplay/NodeBB/"
|
||||
},
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"test": "mocha ./tests"
|
||||
},
|
||||
"dependencies": {
|
||||
"socket.io": "0.9.14",
|
||||
"redis": "0.8.3",
|
||||
"socket.io": "~0.9.16",
|
||||
"express": "3.2.0",
|
||||
"express-namespace": "0.1.1",
|
||||
"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",
|
||||
@@ -25,17 +26,34 @@
|
||||
"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",
|
||||
"node-rss": "1.0.1",
|
||||
"gravatar": "1.0.6",
|
||||
"nconf": "~0.6.7",
|
||||
"sitemap": "~0.6.0",
|
||||
"cheerio": "~0.12.0",
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2",
|
||||
"nodebb-plugin-mentions": "~0.1.0"
|
||||
"rss": "~0.2.0",
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0",
|
||||
"validator": "~1.5.1",
|
||||
"nodebb-plugin-mentions": "~0.1.16",
|
||||
"nodebb-plugin-markdown": "~0.2.1",
|
||||
"nodebb-theme-vanilla": "~0.0.10",
|
||||
"nodebb-theme-cerulean": "0.0.10",
|
||||
"cron": "~1.0.1",
|
||||
"semver": "~2.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"redis": "0.8.3",
|
||||
"mongodb": "~1.3.19",
|
||||
"connect-redis": "1.4.5",
|
||||
"connect-mongo": "0.4.0",
|
||||
"hiredis": "~0.1.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.13.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
@@ -46,15 +64,22 @@
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Andrew Rodrigues",
|
||||
"email": "andrew@designcreateplay.com"
|
||||
"email": "andrew@designcreateplay.com",
|
||||
"url": "https://github.com/psychobunny"
|
||||
},
|
||||
{
|
||||
"name": "Julian Lam",
|
||||
"email": "julian@designcreateplay.com"
|
||||
"email": "julian@designcreateplay.com",
|
||||
"url": "https://github.com/julianlam"
|
||||
},
|
||||
{
|
||||
"name": "Barış Soner Uşaklı",
|
||||
"email": "baris@designcreateplay.com"
|
||||
"email": "baris@designcreateplay.com",
|
||||
"url": "https://github.com/barisusakli"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Darqui",
|
||||
"url": "https://github.com/adarqui"
|
||||
},
|
||||
{
|
||||
"name": "Damian Bushong",
|
||||
@@ -63,6 +88,10 @@
|
||||
{
|
||||
"name": "Matt Smith",
|
||||
"url": "https://github.com/soimafreak"
|
||||
},
|
||||
{
|
||||
"name": "Quinton Marchi",
|
||||
"url": "https://github.com/iamcardinal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
0
plugins/.gitignore
vendored
0
plugins/.gitignore
vendored
@@ -1,157 +0,0 @@
|
||||
@import "mixins";
|
||||
|
||||
.admin {
|
||||
.entry-row {
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
input.description {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.admin-categories {
|
||||
form {
|
||||
margin: 0 0 0px;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 20px;
|
||||
padding: 5px;
|
||||
margin-left: 10px;
|
||||
width: 150px;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.category_description {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
select {
|
||||
border: 0;
|
||||
margin-left: 10px;
|
||||
padding: 5px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
.icon{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
line-height: 35px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.themes {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
padding: 10px 16px;
|
||||
margin: 0.25em 1em;
|
||||
list-style-type: none;
|
||||
.pointer;
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
-webkit-transition: background-color 250ms linear;
|
||||
-moz-transition: background-color 250ms linear;
|
||||
-ms-transition: background-color 250ms linear;
|
||||
-o-transition: background-color 250ms linear;
|
||||
transition: background-color 250ms linear;
|
||||
|
||||
img {
|
||||
max-width: 150px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
h4, p {
|
||||
margin-left: 170px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(128, 128, 128, 0.2);
|
||||
}
|
||||
|
||||
&.no-themes {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.motd textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.topics {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
.zebra;
|
||||
list-style-type: none;
|
||||
padding: 1em;
|
||||
margin-bottom: 1em;
|
||||
|
||||
ul {
|
||||
margin: 0.5em 0;
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
.row {
|
||||
margin: 0;
|
||||
.span3 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 1px;
|
||||
cursor: pointer;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
|
||||
&:hover, &.selected {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plugins {
|
||||
li {
|
||||
list-style-type: none;
|
||||
background: rgba(64, 64, 64, 0.05);
|
||||
padding: 1em;
|
||||
border-left: 5px solid #08c;
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
|
||||
.category {
|
||||
.span9 {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
a {
|
||||
li {
|
||||
list-style: none;
|
||||
//border-bottom: 1px solid #eee;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
&.deleted {
|
||||
-moz-opacity: 0.30;
|
||||
opacity: 0.30;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child li {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.thread-rating {
|
||||
color: #444;
|
||||
text-align: center;
|
||||
margin-top: 7px;
|
||||
|
||||
span {
|
||||
display: inline-block; margin-left: 5px;
|
||||
i {
|
||||
padding-left: 2.4px;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1200px)
|
||||
{
|
||||
margin-left: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.topic-row {
|
||||
border-radius: 5px;
|
||||
padding-left: 20px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
|
||||
small {
|
||||
vertical-align: 2px;
|
||||
strong {
|
||||
color: #666;
|
||||
}
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 4px;
|
||||
color: rgb(0, 136, 204);
|
||||
line-height: 25px;
|
||||
|
||||
.topic-title {
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
white-space: nowrap;
|
||||
text-overflow:ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
.badge {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
@media (max-width: 979px)
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 979px)
|
||||
{
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.latest-post {
|
||||
float: right;
|
||||
padding-top: 2px;
|
||||
margin-right: 0px;
|
||||
width: 40%;
|
||||
|
||||
.pull-right {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 16px;
|
||||
margin-left: 1px;
|
||||
padding: 5px;
|
||||
border-left: 1px solid #bbb;
|
||||
padding-left: 20px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
p {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 70%;
|
||||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
height: 32px;
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 70%;
|
||||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
height: 16px;
|
||||
margin-top: -10px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recent-replies {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
ul {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 16px;
|
||||
margin-left: 1px;
|
||||
padding: 5px 5px 5px 0px;
|
||||
list-style-type: none;
|
||||
|
||||
li {
|
||||
clear: both;
|
||||
line-height: 16px;
|
||||
margin-bottom: 1em;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
p {
|
||||
display: block;
|
||||
padding-left:5px;
|
||||
padding-top: 2px;
|
||||
overflow: hidden;
|
||||
height: 32px;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
span {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
height: 16px;
|
||||
padding-left:5px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.sidebar-block {
|
||||
.block-header {
|
||||
padding: 8px;
|
||||
padding-left: 13px;
|
||||
display: block;
|
||||
background: rgb(245,245,245);
|
||||
color: #676;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
}
|
||||
.block-content {
|
||||
padding: 10px;
|
||||
.img-polaroid {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
max-width: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
border-radius: 5px;
|
||||
padding: 0;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.img-polaroid {
|
||||
margin-top: 2px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
.no-select {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
*cursor: hand;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.zebra {
|
||||
&:nth-child(even) {
|
||||
background: rgba(191,191,191,0.2);
|
||||
}
|
||||
|
||||
&:nth-child(odd) {
|
||||
background: rgba(223,223,223,0.2);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@import "style";
|
||||
|
||||
@import "topic";
|
||||
@import "category";
|
||||
@import "noscript";
|
||||
@@ -1,57 +0,0 @@
|
||||
@import "mixins";
|
||||
|
||||
noscript {
|
||||
.default {
|
||||
list-style-type: none;
|
||||
padding: 1em;
|
||||
margin-bottom: 1em;
|
||||
.zebra;
|
||||
}
|
||||
|
||||
.categories {
|
||||
li {
|
||||
.default;
|
||||
|
||||
.icon {
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.topics {
|
||||
li {
|
||||
.default;
|
||||
}
|
||||
|
||||
.teaser {
|
||||
margin-left: 16px;
|
||||
margin-top: 8px;
|
||||
|
||||
img {
|
||||
float: left;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
margin-left: 64px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.posts {
|
||||
li {
|
||||
.default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,885 +0,0 @@
|
||||
@import "mixins";
|
||||
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
body {
|
||||
/*background: #fdfdfd;*/ // port to default theme when it is implemented.
|
||||
-webkit-transition: margin-bottom 250ms ease;
|
||||
-moz-transition: margin-bottom 250ms ease;
|
||||
-ms-transition: margin-bottom 250ms ease;
|
||||
-o-transition: margin-bottom 250ms ease;
|
||||
transition: margin-bottom 250ms ease;
|
||||
|
||||
&.composing {
|
||||
margin-bottom: 350px;
|
||||
}
|
||||
|
||||
@media (min-width: 979px)
|
||||
{
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
@media (max-width: 979px)
|
||||
{
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
button, a {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.none {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.block, .show {
|
||||
display: block;
|
||||
}
|
||||
.badge {
|
||||
vertical-align: 17%;
|
||||
}
|
||||
.nav .badge {
|
||||
vertical-align: 2%;
|
||||
}
|
||||
|
||||
#alert_window {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
top: 60px;
|
||||
width: 300px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.toaster-alert {
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
footer.footer {
|
||||
color: #555;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
|
||||
#post_window {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
height: 350px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
background: white;
|
||||
z-index: 1500;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
background: #222;
|
||||
height: 220px;
|
||||
resize: none;
|
||||
border-radius: 0;
|
||||
border: 1px solid #111;
|
||||
font-size: 16px;
|
||||
color: #bebebe;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
border:none !important;
|
||||
box-shadow:none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.post-title-container {
|
||||
opacity: 0.8;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.post-content-container {
|
||||
opacity: 0.8;
|
||||
background: #000;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#user_label { //belongs in header.less
|
||||
img {
|
||||
border: 1px solid #454;
|
||||
margin-right: 8px;
|
||||
margin-top: -2px;
|
||||
float: left;
|
||||
width:24px;
|
||||
height:24px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ded;
|
||||
}
|
||||
}
|
||||
|
||||
#reply_title {
|
||||
font-size: 17px;
|
||||
padding-top: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.alt-logins {
|
||||
margin: 0 0 0 1em;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
vertical-align: top;
|
||||
background: transparent;
|
||||
display: none;
|
||||
margin: 0.25em;
|
||||
.pointer;
|
||||
|
||||
&.active {
|
||||
.inline-block;
|
||||
}
|
||||
|
||||
i {
|
||||
-webkit-transition: color 100ms linear;
|
||||
-moz-transition: color 100ms linear;
|
||||
-ms-transition: color 100ms linear;
|
||||
-o-transition: color 100ms linear;
|
||||
transition: color 100ms linear;
|
||||
|
||||
&.icon-twitter-sign:hover {
|
||||
color: #4099FF;
|
||||
}
|
||||
|
||||
&.icon-facebook-sign:hover {
|
||||
color: #3b5999;
|
||||
}
|
||||
|
||||
&.icon-google-plus-sign:hover {
|
||||
color: #d34836;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#thread_active_users {
|
||||
float: right;
|
||||
color: rgb(153,153,153);
|
||||
|
||||
strong {
|
||||
color: rgb(100,100,100);
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.account-username-box{
|
||||
border-bottom:1px solid #e3e3e3;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.account-sub-links a{
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
.account-username{
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.account-block {
|
||||
div {
|
||||
padding-bottom:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.account-picture-block{
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
}
|
||||
|
||||
.account-online-status {
|
||||
.icon-circle-blank {
|
||||
color:red;
|
||||
}
|
||||
.icon-circle {
|
||||
color:green;
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile-picture {
|
||||
width:128px;
|
||||
}
|
||||
|
||||
.user-picture-label {
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
.account-bio-block{
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
}
|
||||
|
||||
.account-bio-label{
|
||||
display:inline-block;
|
||||
width:100px;
|
||||
}
|
||||
|
||||
.user-recent-posts {
|
||||
div {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
cursor: pointer;
|
||||
overflow:hidden;
|
||||
p {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
span {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.category-icon {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
text-align: center;
|
||||
border-radius: 0px;
|
||||
margin: 0;
|
||||
padding-top:25px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 5px;
|
||||
overflow:hidden;
|
||||
}
|
||||
.category-row h4 {
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
/*color: #555;*/ // NOTE: color for cat/topic header links should be grey in the default theme when we get around to it.
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.category-row a {
|
||||
text-decoration: none;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.category-purple {
|
||||
@color: #ab1290;
|
||||
background: @color;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: lighten(@color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.category-darkblue {
|
||||
@color: #004C66;
|
||||
background: @color;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: lighten(@color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.category-blue {
|
||||
@color: #0059B2;
|
||||
background: @color;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: lighten(@color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.category-darkgreen {
|
||||
@color: #004000;
|
||||
background: @color;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: lighten(@color, 10%);
|
||||
}
|
||||
}
|
||||
.category-orange {
|
||||
@color: #FF7A4D;
|
||||
color: white;
|
||||
background: @color;
|
||||
|
||||
&:hover {
|
||||
background: lighten(@color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.category-list {
|
||||
li {
|
||||
.inline-block;
|
||||
.pointer;
|
||||
padding: 0.5em 0;
|
||||
text-align: center;
|
||||
margin: 0.5em;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
padding: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-unit {
|
||||
background: #56BCDA;
|
||||
color: white;
|
||||
padding: 30px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.users-box{
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
max-width: 104px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width:80px;
|
||||
height:80px;
|
||||
}
|
||||
|
||||
a {
|
||||
margin:5px;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover, .btn-link:hover, .btn-link:active, .btn-link:focus {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.formatting-bar {
|
||||
.no-select;
|
||||
|
||||
span:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.breadcrumb {
|
||||
li {
|
||||
max-width: 35%;
|
||||
white-space: nowrap;
|
||||
text-overflow:ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
body .navbar .nodebb-inline-block {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
#right-menu{
|
||||
float:right;
|
||||
}
|
||||
|
||||
#admin-redis-info {
|
||||
span {
|
||||
display:inline-block;
|
||||
width:220px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-signature {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid #ddd;
|
||||
display: inline-block;
|
||||
|
||||
img {
|
||||
max-width:200px;
|
||||
max-height:60px;
|
||||
}
|
||||
}
|
||||
|
||||
.username-field {
|
||||
.icon-circle {
|
||||
font-size: 12px;
|
||||
color: green;
|
||||
margin-right:3px;
|
||||
}
|
||||
.icon-circle-blank {
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
margin-right:3px;
|
||||
}
|
||||
}
|
||||
|
||||
#chat-content {
|
||||
width:95%;
|
||||
height:200px;
|
||||
resize:none;
|
||||
}
|
||||
|
||||
#chat-message-input {
|
||||
width:95%;
|
||||
}
|
||||
|
||||
#content{
|
||||
padding-bottom:20px;
|
||||
}
|
||||
|
||||
|
||||
.dropdown-toggle {
|
||||
i {
|
||||
font-size: 12px;
|
||||
|
||||
@-webkit-keyframes glow
|
||||
{
|
||||
from {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
50% {text-shadow: 0 0 10px #aaf, 0 0 10px #aaf, 0 0 10px #aaf;}
|
||||
to {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
}
|
||||
@keyframes glow
|
||||
{
|
||||
from {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
50% {text-shadow: 0 0 10px #aaf, 0 0 10px #aaf, 0 0 10px #aaf;}
|
||||
to {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
}
|
||||
|
||||
|
||||
&.active {
|
||||
color: #558;
|
||||
|
||||
text-shadow: 0 0 1em #aaf, 0 0 1em #aaf, 0 0 1em #aaf;
|
||||
-webkit-animation:glow 1.5s infinite linear;
|
||||
animation:glow 1.5s infinite linear;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#notif-list {
|
||||
li {
|
||||
font-size: 12px;
|
||||
width: 300px;
|
||||
text-align: left;
|
||||
|
||||
a {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
&.unread {
|
||||
background: #eceff5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.taskbar {
|
||||
display: none;
|
||||
-moz-opacity: 0.5;
|
||||
opacity: 0.5;
|
||||
margin-top: 0;
|
||||
-webkit-transition: opacity 250ms ease-in;
|
||||
-moz-transition: opacity 250ms ease-in;
|
||||
-ms-transition: opacity 250ms ease-in;
|
||||
-o-transition: opacity 250ms ease-in;
|
||||
transition: opacity 250ms ease-in;
|
||||
|
||||
&[data-active="1"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
-moz-opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
li {
|
||||
a > span {
|
||||
.inline-block;
|
||||
max-width: 200px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
&.pulse {
|
||||
-webkit-animation: pulsate 2500ms linear;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulsate {
|
||||
0% { background: none; }
|
||||
50% { background: #e5e5e5; }
|
||||
100% { background: none; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.post-window {
|
||||
position: fixed;
|
||||
display: none;
|
||||
height: 350px;
|
||||
visibility: hidden;
|
||||
|
||||
> div {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
background: rgba(64, 64, 64, 0.6);
|
||||
visibility: visible;
|
||||
|
||||
.btn-toolbar {
|
||||
&.formatting-bar {
|
||||
width: 90%;
|
||||
margin: 0 auto 8px auto;
|
||||
|
||||
span {
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.action-bar {
|
||||
width: 90%;
|
||||
margin: 8px auto 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
width: 98%;
|
||||
text-align: center;
|
||||
border: none;
|
||||
padding: 0.5em 0;
|
||||
-webkit-border-radius: 0px;
|
||||
-moz-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
margin: 5px auto 10px auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background: rgba(64, 64, 64, 0.95);
|
||||
border: none;
|
||||
padding: 0.5em;
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0em auto;
|
||||
resize: none;
|
||||
color: white;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.imagedrop {
|
||||
text-align: center;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 214px;
|
||||
line-height: 214px;
|
||||
font-size: 20px;
|
||||
vertical-align: middle;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.imagelist {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
left: 5%;
|
||||
|
||||
div {
|
||||
margin-right:5px;
|
||||
}
|
||||
|
||||
span {
|
||||
line-height:20px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
button {
|
||||
padding-left:5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 979px) {
|
||||
.post-window {
|
||||
position: relative;
|
||||
bottom: 0px !important;
|
||||
|
||||
> div {
|
||||
position: static;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#mobile-menu {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
height: 50px;
|
||||
background: #333;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
#mobile-menu, #mobile-menu-overlay {
|
||||
z-index: 999;
|
||||
|
||||
@media (min-width: 979px)
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn-none,
|
||||
.btn-none:active,
|
||||
.btn-none[disabled] {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-none {
|
||||
cursor: pointer;
|
||||
border-color: transparent;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.btn-none:hover,
|
||||
.btn-none:focus {
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.btn-none[disabled]:hover,
|
||||
.btn-none[disabled]:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-none {
|
||||
.icon-white {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
#mobile-menu {
|
||||
button {
|
||||
color: #eee;
|
||||
padding: 10px;
|
||||
text-shadow: none;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
#mobile-menu-overlay {
|
||||
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
//margin-top: 50px;
|
||||
padding-top: 20px;
|
||||
opacity: 0;
|
||||
|
||||
-webkit-transition: opacity 150ms ease;
|
||||
-moz-transition: opacity 150ms ease;
|
||||
-ms-transition: opacity 150ms ease;
|
||||
-o-transition: opacity 150ms ease;
|
||||
transition: opacity 150ms ease;
|
||||
z-index: -1;
|
||||
&.menu-visible {
|
||||
z-index: 99;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.mobile-menu-icon {
|
||||
color: white;
|
||||
width: 20%;
|
||||
min-width: 85px;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
|
||||
-webkit-transition: margin-top 250ms ease;
|
||||
-moz-transition: margin-top 250ms ease;
|
||||
-ms-transition: margin-top 250ms ease;
|
||||
-o-transition: margin-top 250ms ease;
|
||||
transition: margin-top 250ms ease;
|
||||
|
||||
margin-top: 20%;
|
||||
|
||||
|
||||
&.menu-visible {
|
||||
margin-top: 0%;
|
||||
}
|
||||
|
||||
i {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#mobile-sidebar {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 0px;
|
||||
overflow: hidden;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.category-box {
|
||||
height:90px;
|
||||
|
||||
.post-preview {
|
||||
padding-left:10px;
|
||||
padding-right:10px;
|
||||
text-align:left;
|
||||
img {
|
||||
width:60px;
|
||||
height:60px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
p {
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
height:60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#mark-allread-btn {
|
||||
margin-bottom:15px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes scroll-2 /* Safari and Chrome */
|
||||
{
|
||||
0% {top: 0px;}
|
||||
25% {top: -90px;}
|
||||
50% {top: -180px;}
|
||||
75% {top: -270px;}
|
||||
100% {top: -360px;}
|
||||
}
|
||||
|
||||
@keyframes scroll-2
|
||||
{
|
||||
0% {top: 0px;}
|
||||
25% {top: -90px;}
|
||||
50% {top: -180px;}
|
||||
75% {top: -270px;}
|
||||
100% {top: -360px;}
|
||||
}
|
||||
|
||||
@-webkit-keyframes scroll-1 /* Safari and Chrome */
|
||||
{
|
||||
0% {top: 0px;}
|
||||
33% {top: -90px;}
|
||||
66% {top: -180px;}
|
||||
100% {top: -270px;}
|
||||
}
|
||||
|
||||
@keyframes scroll-1
|
||||
{
|
||||
0% {top: 0px;}
|
||||
33% {top: -90px;}
|
||||
66% {top: -180px;}
|
||||
100% {top: -270px;}
|
||||
}
|
||||
|
||||
@-webkit-keyframes scroll-0 /* Safari and Chrome */
|
||||
{
|
||||
0% {top: 0px;}
|
||||
50% {top: -90px;}
|
||||
100% {top: -180px;}
|
||||
}
|
||||
|
||||
@keyframes scroll-0
|
||||
{
|
||||
0% {top: 0px;}
|
||||
50% {top: -90px;}
|
||||
100% {top: -180px;}
|
||||
}
|
||||
|
||||
.category-slider-2:hover {
|
||||
position:relative;
|
||||
|
||||
-webkit-animation: scroll-2 10s ease 0.5s infinite normal;
|
||||
animation: scroll-2 10s ease 0.5s infinite normal;/* Safari and Chrome: */
|
||||
}
|
||||
|
||||
.category-slider-1:hover {
|
||||
position:relative;
|
||||
|
||||
-webkit-animation: scroll-1 8s ease 0.5s infinite normal;
|
||||
animation: scroll-1 8s ease 0.5s infinite normal;/* Safari and Chrome: */
|
||||
}
|
||||
|
||||
.category-slider-0:hover {
|
||||
position:relative;
|
||||
|
||||
-webkit-animation: scroll-0 6s ease 0.5s infinite normal;
|
||||
animation: scroll-0 6s ease 0.5s infinite normal;/* Safari and Chrome: */
|
||||
}
|
||||
|
||||
.form-search {
|
||||
float: left;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.search-result-post {
|
||||
width: 100%;
|
||||
line-height: 16px;
|
||||
padding: 5px;
|
||||
overflow:hidden;
|
||||
img {
|
||||
display: block;
|
||||
float: left;
|
||||
width:48px;
|
||||
height:48px;
|
||||
padding-right:10px;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
|
||||
.post-container {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
clear: both;
|
||||
|
||||
.profile-image-block {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
|
||||
.stats {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
padding-bottom: 15px;
|
||||
|
||||
&.deleted {
|
||||
-moz-opacity: 0.30;
|
||||
opacity: 0.30;
|
||||
height:30px;
|
||||
overflow-y:hidden;
|
||||
}
|
||||
|
||||
&.deleted-expanded {
|
||||
height:100%;
|
||||
overflow-y:default;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-block, .post-block {
|
||||
position:relative;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
|
||||
p {
|
||||
line-height: 1.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-block {
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
margin-right: -11px;
|
||||
margin-left: -11px;
|
||||
margin-bottom: -11px;
|
||||
margin-top: 15px;
|
||||
border-radius: 0 0 5px 5px;
|
||||
font-size: 10px;
|
||||
line-height: 18px;
|
||||
padding: 5px;
|
||||
padding-left: 10px;
|
||||
|
||||
img.hidden-desktop {
|
||||
max-width: 10px;
|
||||
max-height: 10px;
|
||||
padding-top: 5px;
|
||||
margin-right: 5px;
|
||||
|
||||
}
|
||||
}
|
||||
.post-content {
|
||||
min-height: 50px;
|
||||
padding: 2px 5px 0 5px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.post-images{
|
||||
padding: 2px 5px 0 5px;
|
||||
}
|
||||
|
||||
.post-block {
|
||||
.post-buttons {
|
||||
font-size: 12px;
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
|
||||
button, a {
|
||||
display: inline-block;
|
||||
padding: 0px 15px;
|
||||
border: none;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.06);
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
font-size: 12px;
|
||||
height: 20px;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-star {
|
||||
//theme this to make it yellow eventually
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
&.deleted {
|
||||
-moz-opacity: 0.30;
|
||||
opacity: 0.30;
|
||||
}
|
||||
/*http://stackoverflow.com/questions/11037517/bootstrap-making-responsive-changes-to-layout*/
|
||||
@media (max-width: 979px) {
|
||||
|
||||
|
||||
.span12-tablet {
|
||||
width: 100% !important;
|
||||
margin-left:0px;
|
||||
*width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 979px) {
|
||||
.speech-bubble:after
|
||||
{
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
left: -7px;
|
||||
border-style: solid;
|
||||
border-width: 7px 7px 7px 0;
|
||||
border-color: transparent #FFFFFF;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.speech-bubble:before
|
||||
{
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
left: -8px;
|
||||
border-style: solid;
|
||||
border-width: 7px 7px 7px 0;
|
||||
border-color: transparent rgba(0, 0, 0, 0.125);
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.main-post {
|
||||
h3 {
|
||||
margin: 0;
|
||||
|
||||
.topic-title {
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-top: 5px;
|
||||
margin-bottom: -5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.main-avatar {
|
||||
color: white;
|
||||
position: relative;
|
||||
float: left;
|
||||
margin-right: 25px;
|
||||
margin-bottom: 0px;
|
||||
padding-bottom: 0px;
|
||||
text-align: center;
|
||||
width:80px;
|
||||
|
||||
@media (max-width: 767px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.main-avatar:hover .hover-overlay {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.hover-overlay {
|
||||
margin: 5px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
height: 35px;
|
||||
padding-top: 2px;
|
||||
width: 80px;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
background: #000;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
min-height: 80px;
|
||||
}
|
||||
hr {
|
||||
margin-top: 0;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.post-block {
|
||||
.post-buttons {
|
||||
div {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.favourite {
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.topic-buttons {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
public/language/TODO
Normal file
3
public/language/TODO
Normal file
@@ -0,0 +1,3 @@
|
||||
NPM INSTALL
|
||||
For now, language packs will be stored here. Eventually, will be moved to server side to allow for npm install-ability.
|
||||
When that happens, server code will generate compressed JSON language files in this folder.
|
||||
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"
|
||||
}
|
||||
14
public/language/en/category.json
Normal file
14
public/language/en/category.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"new_topic_button": "New Topic",
|
||||
"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",
|
||||
"posts": "posts",
|
||||
"views": "views",
|
||||
"posted": "posted",
|
||||
"browsing": "browsing",
|
||||
"no_replies": "No one has replied",
|
||||
"replied": "replied",
|
||||
"last_edited_by": "last edited by"
|
||||
}
|
||||
10
public/language/en/footer.json
Normal file
10
public/language/en/footer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"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",
|
||||
"success": "success"
|
||||
}
|
||||
31
public/language/en/global.json
Normal file
31
public/language/en/global.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"home": "Home",
|
||||
"search": "Search",
|
||||
"buttons.close": "Close",
|
||||
"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>.",
|
||||
"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",
|
||||
"header.profile": "Profile",
|
||||
|
||||
"notifications.loading": "Loading Notifications",
|
||||
"chats.loading": "Loading Chats"
|
||||
}
|
||||
10
public/language/en/login.json
Normal file
10
public/language/en/login.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"login": "Login",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"remember_me": "Remember Me?",
|
||||
"forgot_password": "Forgot Password?",
|
||||
"alternative_logins": "Alternative Logins",
|
||||
"failed_login_attempt": "Failed login attempt, please try again.",
|
||||
"login_successful": "You have successfully logged in!"
|
||||
}
|
||||
9
public/language/en/notifications.json
Normal file
9
public/language/en/notifications.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"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 "
|
||||
}
|
||||
5
public/language/en/recent.json
Normal file
5
public/language/en/recent.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"day": "Day",
|
||||
"week": "Week",
|
||||
"month": "Month"
|
||||
}
|
||||
16
public/language/en/register.json
Normal file
16
public/language/en/register.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"register": "Register",
|
||||
"help.email": "By default, your email will be hidden from the public.",
|
||||
"help.username_restrictions": "A unique username between %1 and %2 characters. Others can mention you with @<span id='yourUsername'>username</span>.",
|
||||
"help.minimum_password_length": "Your password's length must be at least %1 characters.",
|
||||
"email_address": "Email Address",
|
||||
"email_address_placeholder": "Enter Email Address",
|
||||
"username": "Username",
|
||||
"username_placeholder": "Enter Username",
|
||||
"password": "Password",
|
||||
"password_placeholder": "Enter Password",
|
||||
"confirm_password": "Confirm Password",
|
||||
"confirm_password_placeholder": "Confirm Password",
|
||||
"register_now_button": "Register Now",
|
||||
"alternative_registration": "Alternative Registration"
|
||||
}
|
||||
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!"
|
||||
}
|
||||
42
public/language/en/topic.json
Normal file
42
public/language/en/topic.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"topic": "Topic",
|
||||
"topics": "Topics",
|
||||
|
||||
"no_topics_found": "No topics found!",
|
||||
|
||||
"profile": "Profile",
|
||||
"posted_by": "Posted by",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Be notified of new replies in this topic",
|
||||
"quote": "Quote",
|
||||
"reply": "Reply",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"banned": "banned",
|
||||
"link": "Link",
|
||||
|
||||
"thread_tools.title": "Thread Tools",
|
||||
"thread_tools.pin": "Pin Thread",
|
||||
"thread_tools.lock": "Lock Thread",
|
||||
"thread_tools.move": "Move Thread",
|
||||
"thread_tools.delete": "Delete Thread",
|
||||
|
||||
"load_categories": "Loading Categories",
|
||||
"disabled_categories_note": "Disabled Categories are greyed out",
|
||||
"confirm_move": "Move",
|
||||
|
||||
"favourite": "Favourite",
|
||||
"favourites": "Favorites",
|
||||
"favourites.not_logged_in.title": "Not Logged In",
|
||||
"favourites.not_logged_in.message": "Please log in in order to favourite this post",
|
||||
"favourites.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"
|
||||
}
|
||||
5
public/language/en/unread.json
Normal file
5
public/language/en/unread.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"no_unread_topics": "There are no unread topics.",
|
||||
"mark_all_read": "Mark all as Read",
|
||||
"load_more": "Load More"
|
||||
}
|
||||
39
public/language/en/user.json
Normal file
39
public/language/en/user.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"banned": "Banned",
|
||||
"offline": "Offline",
|
||||
"email": "Email",
|
||||
"fullname": "Full Name",
|
||||
"website": "Website",
|
||||
"location": "Location",
|
||||
"age": "Age",
|
||||
"joined": "Joined",
|
||||
"profile_views": "Profile views",
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts",
|
||||
"followers": "Followers",
|
||||
"following": "Following",
|
||||
"signature": "Signature",
|
||||
"gravatar": "Gravatar",
|
||||
"birthday": "Birthday",
|
||||
|
||||
"change_picture": "Change Picture",
|
||||
"edit": "Edit",
|
||||
"uploaded_picture": "Uploaded Picture",
|
||||
"upload_new_picture": "Upload New Picture",
|
||||
"change_password": "Change Password",
|
||||
"confirm_password": "Confirm Password",
|
||||
"password": "Password",
|
||||
|
||||
"upload_picture": "Upload picture",
|
||||
"upload_a_picture": "Upload a picture",
|
||||
"image_spec": "You may only upload PNG, JPG, or GIF files under 256kb.",
|
||||
|
||||
"settings": "settings",
|
||||
"show_email": "Show My Email",
|
||||
|
||||
"has_no_follower": "This user doesn't have any followers :(",
|
||||
"follows_no_one": "This user isn't following anyone :(",
|
||||
|
||||
"email_hidden": "Email Hidden",
|
||||
"hidden": "hidden"
|
||||
}
|
||||
9
public/language/en/users.json
Normal file
9
public/language/en/users.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"latest_users": "Latest Users",
|
||||
"top_posters": "Top Posters",
|
||||
"most_reputation": "Most Reputation",
|
||||
"online": "Online",
|
||||
"search": "Search",
|
||||
"enter_username": "Enter a username to search",
|
||||
"load_more": "Load More"
|
||||
}
|
||||
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 |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
2
public/socket.io/socket.io.min.js
vendored
2
public/socket.io/socket.io.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
var ajaxify = {};
|
||||
|
||||
|
||||
(function($) {
|
||||
(function ($) {
|
||||
/*global app, templates, utils*/
|
||||
|
||||
var location = document.location || window.location,
|
||||
rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : ''),
|
||||
@@ -11,8 +13,8 @@ var ajaxify = {};
|
||||
var executed = {};
|
||||
|
||||
var events = [];
|
||||
ajaxify.register_events = function(new_page_events) {
|
||||
for (var i = 0, ii = events.length; i<ii; i++) {
|
||||
ajaxify.register_events = function (new_page_events) {
|
||||
for (var i = 0, ii = events.length; i < ii; i++) {
|
||||
socket.removeAllListeners(events[i]); // optimize this to user removeListener(event, listener) instead.
|
||||
}
|
||||
|
||||
@@ -20,28 +22,45 @@ var ajaxify = {};
|
||||
};
|
||||
|
||||
|
||||
window.onpopstate = function(event) {
|
||||
window.onpopstate = function (event) {
|
||||
// "quiet": If set to true, will not call pushState
|
||||
if (event !== null && event.state && event.state.url !== undefined) ajaxify.go(event.state.url, null, null, true);
|
||||
if (event !== null && event.state && event.state.url !== undefined) {
|
||||
ajaxify.go(event.state.url, null, true);
|
||||
}
|
||||
};
|
||||
|
||||
ajaxify.go = function(url, callback, template, quiet) {
|
||||
$(window).off('scroll');
|
||||
// leave room and join global
|
||||
app.enter_room('global');
|
||||
var pagination, paginator_bar;
|
||||
|
||||
var url = url.replace(/\/$/, "");
|
||||
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;
|
||||
// end
|
||||
|
||||
// Remove trailing slash
|
||||
url = url.replace(/\/$/, "");
|
||||
|
||||
var hash = window.location.hash;
|
||||
|
||||
if(url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
|
||||
if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
|
||||
url = url.slice(RELATIVE_PATH.length);
|
||||
}
|
||||
|
||||
var tpl_url = templates.get_custom_map(url.split('?')[0]);
|
||||
|
||||
if (tpl_url == false && !templates[url]) {
|
||||
if(url === '' || url === '/') {
|
||||
if (url === '' || url === '/') {
|
||||
tpl_url = 'home';
|
||||
} else {
|
||||
tpl_url = url.split('/')[0].split('?')[0];
|
||||
@@ -52,86 +71,136 @@ var ajaxify = {};
|
||||
}
|
||||
|
||||
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
|
||||
if (quiet !== true) {
|
||||
window.history.pushState({
|
||||
"url": url
|
||||
}, url, RELATIVE_PATH + "/" + url);
|
||||
ajaxify.currentPage = tpl_url;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jQuery('#footer, #content').fadeOut(100);
|
||||
translator.load(tpl_url);
|
||||
|
||||
jQuery('#footer, #content').removeClass('hide').addClass('ajaxifying');
|
||||
|
||||
templates.flush();
|
||||
templates.load_template(function() {
|
||||
templates.load_template(function () {
|
||||
exec_body_scripts(content);
|
||||
require(['forum/' + tpl_url], function(script) {
|
||||
if (script && script.init) {
|
||||
script.init();
|
||||
}
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
app.process_page();
|
||||
app.processPage();
|
||||
|
||||
jQuery('#content, #footer').stop(true, true).fadeIn(200, function() {
|
||||
if(window.location.hash)
|
||||
hash = window.location.hash;
|
||||
if(hash)
|
||||
app.scrollToPost(hash.substr(1));
|
||||
});
|
||||
jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying');
|
||||
|
||||
utils.refreshTitle(url);
|
||||
if (window.location.hash) {
|
||||
hash = window.location.hash;
|
||||
}
|
||||
|
||||
}, url, template);
|
||||
if (hash) {
|
||||
require(['forum/topic'], function(topic) {
|
||||
topic.scrollToPost(hash.substr(1));
|
||||
});
|
||||
}
|
||||
|
||||
app.refreshTitle(url);
|
||||
|
||||
}, url);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
$('document').ready(function() {
|
||||
if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers
|
||||
ajaxify.refresh = function() {
|
||||
ajaxify.go(ajaxify.currentPage);
|
||||
};
|
||||
|
||||
$('document').ready(function () {
|
||||
if (!window.history || !window.history.pushState) {
|
||||
return; // no ajaxification for old browsers
|
||||
}
|
||||
|
||||
content = content || document.getElementById('content');
|
||||
|
||||
// Enhancing all anchors to ajaxify...
|
||||
$(document.body).on('click', 'a', function(e) {
|
||||
|
||||
$(document.body).on('click', 'a', function (e) {
|
||||
function hrefEmpty(href) {
|
||||
return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#";
|
||||
return href === 'javascript:;' || href === window.location.href + "#" || href.slice(-1) === "#";
|
||||
}
|
||||
|
||||
if(hrefEmpty(this.href)) return;
|
||||
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') {
|
||||
return;
|
||||
}
|
||||
|
||||
var url = this.href.replace(rootUrl +'/', '');
|
||||
if(!window.location.pathname.match(/\/(403|404)$/g)) {
|
||||
app.previousUrl = window.location.href;
|
||||
}
|
||||
|
||||
if (this.target !== '') return;
|
||||
if (this.getAttribute('data-ajaxify') === 'false') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && e.which === 1) {
|
||||
if (ajaxify.go(url)) {
|
||||
e.preventDefault();
|
||||
if ((!e.ctrlKey && !e.shiftKey) && e.which === 1) {
|
||||
if (this.host === window.location.host) {
|
||||
// Internal link
|
||||
var url = this.href.replace(rootUrl + '/', '');
|
||||
|
||||
if (ajaxify.go(url)) {
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (window.location.pathname !== '/outgoing') {
|
||||
// External Link
|
||||
|
||||
if (config.useOutgoingLinksPage == true) {
|
||||
ajaxify.go('outgoing?url=' + encodeURIComponent(this.href));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function exec_body_scripts(body_el) {
|
||||
// modified from http://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
||||
|
||||
function nodeName(elem, name) {
|
||||
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
|
||||
};
|
||||
}
|
||||
|
||||
function evalScript(elem) {
|
||||
var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
|
||||
head = document.getElementsByTagName("head")[0] ||
|
||||
document.documentElement,
|
||||
var data = (elem.text || elem.textContent || elem.innerHTML || ""),
|
||||
head = document.getElementsByTagName("head")[0] ||
|
||||
document.documentElement,
|
||||
script = document.createElement("script");
|
||||
|
||||
script.type = "text/javascript";
|
||||
try {
|
||||
script.appendChild(document.createTextNode(data));
|
||||
} catch(e) {
|
||||
script.text = data;
|
||||
script.appendChild(document.createTextNode(data));
|
||||
} catch (e) {
|
||||
script.text = data;
|
||||
}
|
||||
|
||||
if (elem.src) {
|
||||
@@ -141,18 +210,18 @@ var ajaxify = {};
|
||||
head.insertBefore(script, head.firstChild);
|
||||
//TODO: remove from head before inserting?, doing this breaks scripts in safari so commented out for now
|
||||
//head.removeChild(script);
|
||||
};
|
||||
}
|
||||
|
||||
var scripts = [],
|
||||
script,
|
||||
children_nodes = body_el.childNodes,
|
||||
children_nodes = $(body_el).find('script'),
|
||||
child,
|
||||
i;
|
||||
|
||||
for (i = 0; children_nodes[i]; i++) {
|
||||
child = children_nodes[i];
|
||||
if (nodeName(child, "script" ) &&
|
||||
(!child.type || child.type.toLowerCase() === "text/javascript")) {
|
||||
if (nodeName(child, "script") &&
|
||||
(!child.type || child.type.toLowerCase() === "text/javascript")) {
|
||||
scripts.push(child);
|
||||
}
|
||||
}
|
||||
@@ -164,6 +233,6 @@ var ajaxify = {};
|
||||
}
|
||||
evalScript(scripts[i]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}(jQuery));
|
||||
}(jQuery));
|
||||
|
||||
@@ -1,125 +1,193 @@
|
||||
var socket,
|
||||
config,
|
||||
app = {},
|
||||
API_URL = null;
|
||||
app = {
|
||||
"username": null,
|
||||
"uid": null,
|
||||
"isFocused": true,
|
||||
"currentRoom": null
|
||||
};
|
||||
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
var showWelcomeMessage = false;
|
||||
|
||||
function loadConfig() {
|
||||
|
||||
app.loadConfig = function() {
|
||||
$.ajax({
|
||||
url: RELATIVE_PATH + '/api/config',
|
||||
success: function(data) {
|
||||
API_URL = data.api_url;
|
||||
|
||||
success: function (data) {
|
||||
config = data;
|
||||
socket = io.connect(config.socket.address + (config.socket.port ? ':' + config.socket.port : ''));
|
||||
|
||||
var reconnecting = false;
|
||||
var reconnectTries = 0;
|
||||
|
||||
socket.on('event:connect', function(data) {
|
||||
console.log('connected to nodebb socket: ', data);
|
||||
app.username = data.username;
|
||||
app.showLoginMessage();
|
||||
});
|
||||
|
||||
socket.on('event:alert', function(data) {
|
||||
app.alert(data);
|
||||
});
|
||||
|
||||
socket.on('connect', function(data){
|
||||
if(reconnecting) {
|
||||
setTimeout(function(){
|
||||
app.alert({
|
||||
alert_id: 'connection_alert',
|
||||
title: 'Connected',
|
||||
message: 'Connection successful.',
|
||||
type: 'success',
|
||||
timeout: 5000
|
||||
});
|
||||
}, 1000);
|
||||
reconnecting = false;
|
||||
reconnectTries = 0;
|
||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('reconnecting', function(data) {
|
||||
function showDisconnectModal() {
|
||||
$('#disconnect-modal').modal({
|
||||
backdrop:'static',
|
||||
show:true
|
||||
});
|
||||
|
||||
$('#reload-button').on('click',function(){
|
||||
$('#disconnect-modal').modal('hide');
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
reconnecting = true;
|
||||
reconnectTries++;
|
||||
|
||||
if(reconnectTries > 4) {
|
||||
showDisconnectModal();
|
||||
return;
|
||||
}
|
||||
|
||||
app.alert({
|
||||
alert_id: 'connection_alert',
|
||||
title: 'Reconnecting',
|
||||
message: 'You have disconnected from NodeBB, we will try to reconnect you. <br/><i class="icon-refresh icon-spin"></i>',
|
||||
type: 'notify',
|
||||
timeout: 5000
|
||||
if(socket) {
|
||||
socket.disconnect();
|
||||
setTimeout(function() {
|
||||
socket.socket.connect();
|
||||
}, 200);
|
||||
} else {
|
||||
var max_reconnection_attemps = 5;
|
||||
var reconnection_delay = 200;
|
||||
socket = io.connect(RELATIVE_PATH, {
|
||||
'max reconnection attempts': max_reconnection_attemps,
|
||||
'reconnection delay': reconnection_delay
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:user.get_online_users', function(users) {
|
||||
jQuery('.username-field').each(function() {
|
||||
if (this.processed === true)
|
||||
return;
|
||||
var reconnecting = false,
|
||||
reconnectEl, reconnectTimer;
|
||||
|
||||
var el = jQuery(this),
|
||||
uid = el.parents('li').attr('data-uid');
|
||||
socket.on('event:connect', function (data) {
|
||||
app.username = data.username;
|
||||
app.uid = data.uid;
|
||||
|
||||
if (uid && jQuery.inArray(uid, users) !== -1) {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="icon-circle"></i>');
|
||||
} else {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="icon-circle-blank"></i>');
|
||||
app.showLoginMessage();
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('event:alert', function (data) {
|
||||
app.alert(data);
|
||||
});
|
||||
|
||||
socket.on('connect', function (data) {
|
||||
if (reconnecting) {
|
||||
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').addClass("hide");
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
el.processed = true;
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.enter_room('global');
|
||||
socket.on('event:disconnect', function() {
|
||||
socket.socket.connect();
|
||||
});
|
||||
|
||||
socket.on('reconnecting', function (data, attempt) {
|
||||
if(attempt == max_reconnection_attemps) {
|
||||
socket.socket.reconnectionAttempts = 0;
|
||||
socket.socket.reconnectionDelay = reconnection_delay;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reconnectEl) reconnectEl = $('#reconnect');
|
||||
reconnecting = true;
|
||||
|
||||
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) {
|
||||
jQuery('a.username-field').each(function () {
|
||||
if (this.processed === true)
|
||||
return;
|
||||
|
||||
var el = jQuery(this),
|
||||
uid = el.parents('li').attr('data-uid');
|
||||
|
||||
if (uid && jQuery.inArray(uid, users) !== -1) {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="fa fa-circle"></i>');
|
||||
} else {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="fa fa-circle-o"></i>');
|
||||
}
|
||||
|
||||
el.processed = true;
|
||||
});
|
||||
jQuery('button .username-field').each(function () {
|
||||
//DRY FAIL
|
||||
if (this.processed === true)
|
||||
return;
|
||||
|
||||
var el = jQuery(this),
|
||||
uid = el.parents('li').attr('data-uid');
|
||||
|
||||
if (uid && jQuery.inArray(uid, users) !== -1) {
|
||||
el.parent().addClass('btn-success');
|
||||
} else {
|
||||
el.parent().addClass('btn-danger');
|
||||
}
|
||||
|
||||
el.processed = true;
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('event:banned', function() {
|
||||
app.alert({
|
||||
title: 'Banned',
|
||||
message: 'You are banned you will be logged out!',
|
||||
type: 'warning',
|
||||
timeout: 1000
|
||||
});
|
||||
|
||||
setTimeout(app.logout, 1000);
|
||||
});
|
||||
|
||||
app.enterRoom('global');
|
||||
}
|
||||
},
|
||||
async: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.logout = function() {
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: $('#csrf_token').val()
|
||||
}, function() {
|
||||
window.location.href = RELATIVE_PATH + '/';
|
||||
});
|
||||
};
|
||||
|
||||
// takes a string like 1000 and returns 1,000
|
||||
app.addCommas = function(text) {
|
||||
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) {
|
||||
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,
|
||||
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
|
||||
@@ -127,14 +195,15 @@ var socket,
|
||||
// message = alert message content
|
||||
// timeout default = permanent
|
||||
// location : alert_window (default) or content
|
||||
app.alert = function(params) {
|
||||
app.alert = function (params) {
|
||||
var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime());
|
||||
|
||||
var alert = $('#'+alert_id);
|
||||
var alert = $('#' + alert_id);
|
||||
var title = params.title || '';
|
||||
|
||||
function startTimeout(div, timeout) {
|
||||
var timeoutId = setTimeout(function() {
|
||||
$(div).fadeOut(1000, function() {
|
||||
var timeoutId = setTimeout(function () {
|
||||
$(div).fadeOut(1000, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
}, timeout);
|
||||
@@ -142,58 +211,49 @@ var socket,
|
||||
$(div).attr('timeoutId', timeoutId);
|
||||
}
|
||||
|
||||
if(alert.length > 0) {
|
||||
alert.find('strong').html(params.title);
|
||||
if (alert.length > 0) {
|
||||
alert.find('strong').html(title);
|
||||
alert.find('p').html(params.message);
|
||||
alert.attr('class', "alert toaster-alert " + ((params.type=='warning') ? '' : "alert-" + params.type));
|
||||
alert.attr('class', "alert toaster-alert " + "alert-" + params.type);
|
||||
|
||||
clearTimeout(alert.attr('timeoutId'));
|
||||
startTimeout(alert, params.timeout);
|
||||
}
|
||||
else {
|
||||
var div = document.createElement('div'),
|
||||
button = document.createElement('button'),
|
||||
strong = document.createElement('strong'),
|
||||
p = document.createElement('p');
|
||||
} else {
|
||||
var div = $('<div id="' + alert_id + '" class="alert toaster-alert alert-' + params.type +'"></div>'),
|
||||
button = $('<button class="close">×</button>'),
|
||||
strong = $('<strong>' + title + '</strong>'),
|
||||
p = $('<p>' + params.message + '</p>');
|
||||
|
||||
p.innerHTML = params.message;
|
||||
strong.innerHTML = params.title;
|
||||
div.append(button)
|
||||
.append(strong)
|
||||
.append(p);
|
||||
|
||||
div.className = "alert toaster-alert " + ((params.type=='warning') ? '' : "alert-" + params.type);
|
||||
|
||||
div.setAttribute('id', alert_id);
|
||||
div.appendChild(button);
|
||||
div.appendChild(strong);
|
||||
div.appendChild(p);
|
||||
|
||||
button.className = 'close';
|
||||
button.innerHTML = '×';
|
||||
button.onclick = function(ev) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
button.on('click', function () {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
if (params.location == null)
|
||||
params.location = 'alert_window';
|
||||
|
||||
jQuery('#'+params.location).prepend(jQuery(div).fadeIn('100'));
|
||||
$('#' + params.location).prepend(div.fadeIn('100'));
|
||||
|
||||
if (params.timeout) {
|
||||
startTimeout(div, params.timeout);
|
||||
}
|
||||
|
||||
if (params.clickfn) {
|
||||
div.onclick = function() {
|
||||
div.on('click', function () {
|
||||
params.clickfn();
|
||||
jQuery(div).fadeOut(500, function() {
|
||||
this.remove();
|
||||
div.fadeOut(500, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.alertSuccess = function(message, timeout) {
|
||||
if(!timeout)
|
||||
app.alertSuccess = function (message, timeout) {
|
||||
if (!timeout)
|
||||
timeout = 2000;
|
||||
|
||||
app.alert({
|
||||
@@ -202,63 +262,55 @@ var socket,
|
||||
type: 'success',
|
||||
timeout: timeout
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.alertError = function(message, timeout) {
|
||||
if(!timeout)
|
||||
app.alertError = function (message, timeout) {
|
||||
if (!timeout)
|
||||
timeout = 2000;
|
||||
|
||||
app.alert({
|
||||
title: 'Error',
|
||||
message: message,
|
||||
type: 'error',
|
||||
type: 'danger',
|
||||
timeout: timeout
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.current_room = null;
|
||||
app.enter_room = function(room) {
|
||||
if(socket) {
|
||||
if (app.current_room === room)
|
||||
app.enterRoom = function (room, force) {
|
||||
if (socket) {
|
||||
if (app.currentRoom === room && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('event:enter_room', {
|
||||
'enter': room,
|
||||
'leave': app.current_room
|
||||
'leave': app.currentRoom
|
||||
});
|
||||
|
||||
app.current_room = room;
|
||||
app.currentRoom = room;
|
||||
}
|
||||
};
|
||||
|
||||
app.populate_online_users = function() {
|
||||
app.populateOnlineUsers = function () {
|
||||
var uids = [];
|
||||
|
||||
jQuery('.post-row').each(function() {
|
||||
jQuery('.post-row').each(function () {
|
||||
uids.push(this.getAttribute('data-uid'));
|
||||
});
|
||||
|
||||
socket.emit('api:user.get_online_users', uids);
|
||||
}
|
||||
};
|
||||
|
||||
app.process_page = function() {
|
||||
|
||||
// here is where all modules' onNavigate should be called, I think.
|
||||
require(['mobileMenu'], function(mobileMenu) {
|
||||
mobileMenu.onNavigate();
|
||||
});
|
||||
|
||||
app.populate_online_users();
|
||||
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length-1];
|
||||
function highlightNavigationLink() {
|
||||
var path = window.location.pathname,
|
||||
parts = path.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
|
||||
jQuery('#main-nav li').removeClass('active');
|
||||
if(active) {
|
||||
jQuery('#main-nav li a').each(function() {
|
||||
if (active) {
|
||||
jQuery('#main-nav li a').each(function () {
|
||||
var href = this.getAttribute('href');
|
||||
if(active.match(/^users/))
|
||||
if (active == "sort-posts" || active == "sort-reputation" || active == "search" || active == "latest" || active == "online")
|
||||
active = 'users';
|
||||
if (href && href.match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
@@ -266,13 +318,41 @@ var socket,
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
app.createUserTooltips = function() {
|
||||
$('img[title].teaser-pic,img[title].user-img').each(function() {
|
||||
$(this).tooltip({
|
||||
placement: 'top',
|
||||
title: $(this).attr('title')
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
app.makeNumbersHumanReadable = function(elements) {
|
||||
elements.each(function() {
|
||||
$(this).html(utils.makeNumberHumanReadable($(this).attr('title')));
|
||||
});
|
||||
};
|
||||
|
||||
app.processPage = function () {
|
||||
app.populateOnlineUsers();
|
||||
|
||||
highlightNavigationLink();
|
||||
|
||||
$('span.timeago').timeago();
|
||||
$('.post-content img').addClass('img-responsive');
|
||||
|
||||
app.makeNumbersHumanReadable($('.human-readable-number'));
|
||||
|
||||
app.createUserTooltips();
|
||||
|
||||
setTimeout(function () {
|
||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
app.showLoginMessage = function() {
|
||||
app.showLoginMessage = function () {
|
||||
function showAlert() {
|
||||
app.alert({
|
||||
type: 'success',
|
||||
@@ -282,165 +362,127 @@ var socket,
|
||||
});
|
||||
}
|
||||
|
||||
if(showWelcomeMessage) {
|
||||
if (showWelcomeMessage) {
|
||||
showWelcomeMessage = false;
|
||||
if(document.readyState !== 'complete') {
|
||||
if (document.readyState !== 'complete') {
|
||||
$(document).ready(showAlert);
|
||||
} else {
|
||||
showAlert();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.addCommasToNumbers = function() {
|
||||
$('.formatted-number').each(function(index, element) {
|
||||
app.addCommasToNumbers = function () {
|
||||
$('.formatted-number').each(function (index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
app.createNewPosts = function(data) {
|
||||
data.posts[0].display_moderator_tools = 'none';
|
||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data),
|
||||
uniqueid = new Date().getTime(),
|
||||
tempContainer = jQuery('<div id="' + uniqueid + '"></div>')
|
||||
.appendTo("#post-container")
|
||||
.hide()
|
||||
.append(html)
|
||||
.fadeIn('slow');
|
||||
|
||||
for(var x=0,numPosts=data.posts.length;x<numPosts;x++) {
|
||||
socket.emit('api:post.privileges', data.posts[x].pid);
|
||||
}
|
||||
|
||||
tempContainer.replaceWith(tempContainer.contents());
|
||||
infiniteLoaderActive = false;
|
||||
|
||||
app.populate_online_users();
|
||||
app.addCommasToNumbers();
|
||||
}
|
||||
|
||||
app.infiniteLoaderActive = false;
|
||||
|
||||
app.loadMorePosts = function(tid, callback) {
|
||||
if(app.infiniteLoaderActive)
|
||||
return;
|
||||
app.infiniteLoaderActive = true;
|
||||
socket.emit('api:topic.loadMore', {
|
||||
tid: tid,
|
||||
after: document.querySelectorAll('#post-container li[data-pid]').length
|
||||
}, function(data) {
|
||||
app.infiniteLoaderActive = false;
|
||||
if(data.posts.length) {
|
||||
app.createNewPosts(data);
|
||||
}
|
||||
|
||||
if(callback)
|
||||
callback(data.posts);
|
||||
});
|
||||
}
|
||||
|
||||
app.scrollToPost = function(pid) {
|
||||
|
||||
if(!pid)
|
||||
return;
|
||||
|
||||
var container = $(document.body),
|
||||
scrollTo = $('#post_anchor_' + pid),
|
||||
tid = $('#post-container').attr('data-tid');
|
||||
|
||||
function animateScroll() {
|
||||
$('body,html').animate({
|
||||
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
||||
app.openChat = function (username, touid) {
|
||||
if (username === app.username) {
|
||||
app.alert({
|
||||
type: 'warning',
|
||||
title: 'Invalid Chat',
|
||||
message: "You can't chat with yourself!",
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!scrollTo.length && tid) {
|
||||
if (!app.username) {
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
title: 'Not Logged In',
|
||||
message: 'Please log in to chat with <strong>' + username + '</strong>',
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
var intervalID = setInterval(function() {
|
||||
app.loadMorePosts(tid, function(posts) {
|
||||
scrollTo = $('#post_anchor_' + pid);
|
||||
|
||||
if(tid && scrollTo.length) {
|
||||
animateScroll();
|
||||
}
|
||||
|
||||
if(!posts.length || scrollTo.length)
|
||||
clearInterval(intervalID);
|
||||
});
|
||||
}, 100);
|
||||
|
||||
} else if(tid) {
|
||||
animateScroll();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
require(['chat'], function (chat) {
|
||||
var chatModal;
|
||||
if (!chat.modalExists(touid)) {
|
||||
chatModal = chat.createModal(username, touid);
|
||||
} else {
|
||||
chatModal = chat.getModal(touid);
|
||||
}
|
||||
chat.load(chatModal.attr('UUID'));
|
||||
chat.center(chatModal);
|
||||
});
|
||||
};
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
addTouchEvents();
|
||||
app.scrollToTop = function () {
|
||||
$('body,html').animate({
|
||||
scrollTop: 0
|
||||
});
|
||||
};
|
||||
|
||||
$('#search-form').on('submit', function() {
|
||||
app.scrollToBottom = function () {
|
||||
$('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;
|
||||
|
||||
loadConfig();
|
||||
|
||||
|
||||
function addTouchEvents() {
|
||||
return; // later.
|
||||
|
||||
|
||||
// click simulation just for testing/sanity purposes.
|
||||
|
||||
var el = jQuery("#content"),
|
||||
sidebar = jQuery('#mobile-sidebar'),
|
||||
width = el.width();
|
||||
|
||||
function onTouchMove(ev) {
|
||||
var coordinates = window.event ? window.event.touches[0] : ev.touches[0];
|
||||
|
||||
el.css({
|
||||
marginLeft: -parseInt(width - coordinates.pageX) + 'px',
|
||||
paddingRight: parseInt(width - coordinates.pageX) + 'px'});
|
||||
|
||||
sidebar.css({
|
||||
marginLeft: -parseInt(width - coordinates.pageX) + 'px',
|
||||
width: parseInt(width - coordinates.pageX) + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
function onMouseMove(ev) {
|
||||
ev.touches = [{pageX: ev.pageX, pageY: ev.pageY}];
|
||||
onTouchMove(ev);
|
||||
}
|
||||
|
||||
function onTouchEnd() {
|
||||
el.css({
|
||||
marginLeft: '0px',
|
||||
paddingRight: '0px'
|
||||
});
|
||||
|
||||
sidebar.css({
|
||||
marginLeft: '0px',
|
||||
width: '0px'
|
||||
});
|
||||
}
|
||||
|
||||
el.on('touchmove', onTouchMove);
|
||||
el.on('mousedown', function() {
|
||||
el.on('mousemove', onMouseMove);
|
||||
});
|
||||
|
||||
el.on('touchend', onTouchEnd);
|
||||
el.on('mouseup', function() {
|
||||
el.off('mousemove');
|
||||
onTouchEnd();
|
||||
});
|
||||
|
||||
}
|
||||
}());
|
||||
app.loadConfig();
|
||||
app.alternatingTitle('');
|
||||
}());
|
||||
@@ -1,71 +1,101 @@
|
||||
(function() {
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
isFollowing = templates.get('isFollowing');
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var Account = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
Account.init = function() {
|
||||
header.init();
|
||||
|
||||
app.addCommasToNumbers();
|
||||
|
||||
var followBtn = $('#follow-btn');
|
||||
var unfollowBtn = $('#unfollow-btn');
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
isFollowing = templates.get('isFollowing');
|
||||
|
||||
if(yourid !== theirid) {
|
||||
if(isFollowing) {
|
||||
followBtn.hide();
|
||||
unfollowBtn.show();
|
||||
$(document).ready(function() {
|
||||
var username = $('.account-username a').html();
|
||||
app.enterRoom('user/' + theirid);
|
||||
|
||||
app.addCommasToNumbers();
|
||||
$('.user-recent-posts img').addClass('img-responsive');
|
||||
|
||||
var followBtn = $('#follow-btn');
|
||||
var unfollowBtn = $('#unfollow-btn');
|
||||
var chatBtn = $('#chat-btn');
|
||||
|
||||
if (yourid !== theirid && yourid !== "0") {
|
||||
if (isFollowing) {
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.removeClass('hide');
|
||||
} else {
|
||||
followBtn.removeClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
}
|
||||
chatBtn.removeClass('hide');
|
||||
} else {
|
||||
followBtn.show();
|
||||
unfollowBtn.hide();
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
chatBtn.addClass('hide');
|
||||
}
|
||||
}
|
||||
|
||||
followBtn.on('click', function() {
|
||||
socket.emit('api:user.follow', {uid: theirid}, function(success) {
|
||||
var username = $('.account-username a').html();
|
||||
if(success) {
|
||||
followBtn.hide();
|
||||
unfollowBtn.show();
|
||||
app.alertSuccess('You are now following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error following' + username + '!');
|
||||
}
|
||||
followBtn.on('click', function() {
|
||||
socket.emit('api:user.follow', {
|
||||
uid: theirid
|
||||
}, function(success) {
|
||||
if (success) {
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.removeClass('hide');
|
||||
app.alertSuccess('You are now following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error following' + username + '!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
unfollowBtn.on('click', function() {
|
||||
socket.emit('api:user.unfollow', {uid: theirid}, function(success) {
|
||||
var username = $('.account-username a').html();
|
||||
if(success) {
|
||||
followBtn.show();
|
||||
unfollowBtn.hide();
|
||||
app.alertSuccess('You are no longer following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error unfollowing ' + username + '!');
|
||||
}
|
||||
unfollowBtn.on('click', function() {
|
||||
socket.emit('api:user.unfollow', {
|
||||
uid: theirid
|
||||
}, function(success) {
|
||||
if (success) {
|
||||
followBtn.removeClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
app.alertSuccess('You are no longer following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error unfollowing ' + username + '!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
chatBtn.on('click', function() {
|
||||
app.openChat(username, theirid);
|
||||
});
|
||||
|
||||
$('.user-recent-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
|
||||
socket.on('api:user.isOnline', Account.handleUserOnline);
|
||||
|
||||
socket.emit('api:user.isOnline', theirid, Account.handleUserOnline);
|
||||
|
||||
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();
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.user-recent-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Account.handleUserOnline = function(data) {
|
||||
var onlineStatus = $('.account-online-status');
|
||||
|
||||
socket.on('api:user.isOnline', function(online) {
|
||||
if(online) {
|
||||
onlineStatus.find('span span').text('online');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||
} else {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||
}
|
||||
});
|
||||
|
||||
socket.emit('api:user.isOnline', theirid);
|
||||
|
||||
});
|
||||
if (data.online) {
|
||||
onlineStatus.find('span span').text('online');
|
||||
onlineStatus.find('i').attr('class', 'fa fa-circle');
|
||||
} else {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'fa fa-circle-o');
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
return Account;
|
||||
});
|
||||
|
||||
@@ -1,277 +1,243 @@
|
||||
define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
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');
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
var selectedImageType = '';
|
||||
|
||||
$('#submitBtn').on('click', function() {
|
||||
|
||||
$('#uploadForm').submit(function() {
|
||||
status('uploading the file ...');
|
||||
|
||||
$('#upload-progress-bar').css('width', '0%');
|
||||
$('#upload-progress-box').show();
|
||||
|
||||
if(!$('#userPhotoInput').val()) {
|
||||
error('select an image to upload!');
|
||||
return false;
|
||||
}
|
||||
|
||||
$(this).find('#imageUploadCsrf').val($('#csrf_token').val());
|
||||
|
||||
var userData = {
|
||||
uid: $('#inputUID').val(),
|
||||
email: $('#inputEmail').val(),
|
||||
fullname: $('#inputFullname').val(),
|
||||
website: $('#inputWebsite').val(),
|
||||
birthday: $('#inputBirthday').val(),
|
||||
location: $('#inputLocation').val(),
|
||||
signature: $('#inputSignature').val()
|
||||
};
|
||||
|
||||
$(this).ajaxSubmit({
|
||||
|
||||
error: function(xhr) {
|
||||
error('Error: ' + xhr.status);
|
||||
},
|
||||
|
||||
uploadProgress : function(event, position, total, percent) {
|
||||
$('#upload-progress-bar').css('width', percent+'%');
|
||||
},
|
||||
|
||||
|
||||
success: function(response) {
|
||||
if(response.error) {
|
||||
error(response.error);
|
||||
return;
|
||||
socket.emit('api:user.updateProfile', userData, function(err, data) {
|
||||
if (data.success) {
|
||||
app.alertSuccess('Your profile has been updated successfully!');
|
||||
if (data.picture) {
|
||||
$('#user-current-picture').attr('src', data.picture);
|
||||
$('#user_label img').attr('src', data.picture);
|
||||
}
|
||||
if (data.gravatarpicture) {
|
||||
$('#user-gravatar-picture').attr('src', data.gravatarpicture);
|
||||
gravatarPicture = data.gravatarpicture;
|
||||
}
|
||||
} else {
|
||||
app.alertError('There was an error updating your profile! ' + err.error);
|
||||
}
|
||||
|
||||
var imageUrlOnServer = response.path;
|
||||
|
||||
$('#user-current-picture').attr('src', imageUrlOnServer);
|
||||
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
|
||||
|
||||
uploadedPicture = imageUrlOnServer;
|
||||
|
||||
setTimeout(function() {
|
||||
hideAlerts();
|
||||
$('#upload-picture-modal').modal('hide');
|
||||
}, 750);
|
||||
|
||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
||||
success('File uploaded successfully!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
function hideAlerts() {
|
||||
$('#alert-status').hide();
|
||||
$('#alert-success').hide();
|
||||
$('#alert-error').hide();
|
||||
$('#upload-progress-box').hide();
|
||||
}
|
||||
|
||||
function status(message) {
|
||||
hideAlerts();
|
||||
$('#alert-status').text(message).show();
|
||||
}
|
||||
|
||||
function success(message) {
|
||||
hideAlerts();
|
||||
$('#alert-success').text(message).show();
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
hideAlerts();
|
||||
$('#alert-error').text(message).show();
|
||||
}
|
||||
|
||||
function changeUserPicture(type) {
|
||||
|
||||
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();
|
||||
|
||||
$('#change-picture-modal').modal('show');
|
||||
$('#change-picture-modal').removeClass('hide');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#gravatar-box').on('click', function() {
|
||||
$('#gravatar-box .fa-check').show();
|
||||
$('#uploaded-box .fa-check').hide();
|
||||
selectedImageType = 'gravatar';
|
||||
});
|
||||
|
||||
$('#uploaded-box').on('click', function() {
|
||||
$('#gravatar-box .fa-check').hide();
|
||||
$('#uploaded-box .fa-check').show();
|
||||
selectedImageType = 'uploaded';
|
||||
});
|
||||
|
||||
$('#savePictureChangesBtn').on('click', function() {
|
||||
$('#change-picture-modal').modal('hide');
|
||||
|
||||
if (selectedImageType) {
|
||||
AccountEdit.changeUserPicture(selectedImageType);
|
||||
|
||||
if (selectedImageType == 'gravatar')
|
||||
$('#user-current-picture').attr('src', gravatarPicture);
|
||||
else if (selectedImageType == 'uploaded')
|
||||
$('#user-current-picture').attr('src', uploadedPicture);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$('#upload-picture-modal').on('hide', function() {
|
||||
$('#userPhotoInput').val('');
|
||||
});
|
||||
|
||||
$('#uploadPictureBtn').on('click', function() {
|
||||
|
||||
$('#change-picture-modal').modal('hide');
|
||||
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);
|
||||
|
||||
uploadedPicture = imageUrlOnServer;
|
||||
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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');
|
||||
var password_notify = $('#password-notify');
|
||||
var password_confirm_notify = $('#password-confirm-notify');
|
||||
var password = $('#inputNewPassword');
|
||||
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) {
|
||||
showError(password_notify, 'Password too short!');
|
||||
} else if (!passwordvalid) {
|
||||
showError(password_notify, 'Invalid password!');
|
||||
} else {
|
||||
showSuccess(password_notify, successIcon);
|
||||
}
|
||||
}
|
||||
|
||||
function onPasswordConfirmChanged() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
password.on('blur', onPasswordChanged);
|
||||
password_confirm.on('blur', onPasswordConfirmChanged);
|
||||
|
||||
$('#changePasswordBtn').on('click', function() {
|
||||
|
||||
if (passwordvalid && passwordsmatch && currentPassword.val()) {
|
||||
socket.emit('api:user.changePassword', {
|
||||
'currentPassword': currentPassword.val(),
|
||||
'newPassword': password.val()
|
||||
}, function(err) {
|
||||
|
||||
currentPassword.val('');
|
||||
password.val('');
|
||||
password_confirm.val('');
|
||||
passwordsmatch = false;
|
||||
passwordvalid = false;
|
||||
|
||||
if (err) {
|
||||
app.alertError(err.error);
|
||||
return;
|
||||
}
|
||||
|
||||
app.alertSuccess('Your password is updated!');
|
||||
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}());
|
||||
};
|
||||
|
||||
|
||||
AccountEdit.changeUserPicture = function(type) {
|
||||
var userData = {
|
||||
type: type
|
||||
};
|
||||
|
||||
|
||||
socket.emit('api:user.changePicture', userData, function(success) {
|
||||
if(!success) {
|
||||
if (!success) {
|
||||
app.alertError('There was an error changing picture!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var selectedImageType = '';
|
||||
|
||||
$('#submitBtn').on('click',function(){
|
||||
|
||||
var userData = {
|
||||
uid:$('#inputUID').val(),
|
||||
email:$('#inputEmail').val(),
|
||||
fullname:$('#inputFullname').val(),
|
||||
website:$('#inputWebsite').val(),
|
||||
birthday:$('#inputBirthday').val(),
|
||||
location:$('#inputLocation').val(),
|
||||
signature:$('#inputSignature').val()
|
||||
};
|
||||
|
||||
socket.emit('api:user.updateProfile', userData, function(data) {
|
||||
if(data.success) {
|
||||
app.alertSuccess('Your profile has been updated successfully!');
|
||||
if(data.picture) {
|
||||
$('#user-current-picture').attr('src', data.picture);
|
||||
$('#user_label img').attr('src', data.picture);
|
||||
}
|
||||
if(data.gravatarpicture) {
|
||||
$('#user-gravatar-picture').attr('src', data.gravatarpicture);
|
||||
gravatarPicture = data.gravatarpicture;
|
||||
}
|
||||
} else {
|
||||
app.alertError('There was an error updating your profile!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
function updateImages() {
|
||||
AccountEdit.updateImages = function() {
|
||||
var currentPicture = $('#user-current-picture').attr('src');
|
||||
|
||||
if(gravatarPicture) {
|
||||
if (gravatarPicture) {
|
||||
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
||||
$('#gravatar-box').show();
|
||||
}
|
||||
else
|
||||
} else {
|
||||
$('#gravatar-box').hide();
|
||||
}
|
||||
|
||||
if(uploadedPicture) {
|
||||
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 == uploadedPicture)
|
||||
$('#uploaded-box .icon-ok').show();
|
||||
else
|
||||
$('#uploaded-box .icon-ok').hide();
|
||||
}
|
||||
|
||||
|
||||
if (currentPicture == gravatarPicture) {
|
||||
$('#gravatar-box .fa-check').show();
|
||||
} else {
|
||||
$('#gravatar-box .fa-check').hide();
|
||||
}
|
||||
|
||||
if (currentPicture == uploadedPicture) {
|
||||
$('#uploaded-box .fa-check').show();
|
||||
} else {
|
||||
$('#uploaded-box .fa-check').hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('#changePictureBtn').on('click', function() {
|
||||
selectedImageType = '';
|
||||
updateImages();
|
||||
|
||||
$('#change-picture-modal').modal('show');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#gravatar-box').on('click', function(){
|
||||
$('#gravatar-box .icon-ok').show();
|
||||
$('#uploaded-box .icon-ok').hide();
|
||||
selectedImageType = 'gravatar';
|
||||
});
|
||||
|
||||
$('#uploaded-box').on('click', function(){
|
||||
$('#gravatar-box .icon-ok').hide();
|
||||
$('#uploaded-box .icon-ok').show();
|
||||
selectedImageType = 'uploaded';
|
||||
});
|
||||
|
||||
$('#savePictureChangesBtn').on('click', function() {
|
||||
$('#change-picture-modal').modal('hide');
|
||||
|
||||
if(selectedImageType) {
|
||||
changeUserPicture(selectedImageType);
|
||||
|
||||
if(selectedImageType == 'gravatar')
|
||||
$('#user-current-picture').attr('src', gravatarPicture);
|
||||
else if(selectedImageType == 'uploaded')
|
||||
$('#user-current-picture').attr('src', uploadedPicture);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$('#upload-picture-modal').on('hide', function() {
|
||||
$('#userPhotoInput').val('');
|
||||
});
|
||||
|
||||
$('#uploadPictureBtn').on('click', function(){
|
||||
|
||||
$('#change-picture-modal').modal('hide');
|
||||
$('#upload-picture-modal').modal('show');
|
||||
|
||||
hideAlerts();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#pictureUploadSubmitBtn').on('click', function() {
|
||||
$('#uploadForm').submit();
|
||||
});
|
||||
|
||||
(function handlePasswordChange() {
|
||||
var currentPassword = $('#inputCurrentPassword');
|
||||
var password_notify = $('#password-notify');
|
||||
var password_confirm_notify = $('#password-confirm-notify');
|
||||
var password = $('#inputNewPassword');
|
||||
var password_confirm = $('#inputNewPasswordAgain');
|
||||
var passwordvalid = false;
|
||||
var passwordsmatch = false;
|
||||
|
||||
|
||||
function onPasswordChanged() {
|
||||
passwordvalid = utils.isPasswordValid(password.val());
|
||||
if (password.val().length < 6) {
|
||||
password_notify.html('Password too short');
|
||||
password_notify.attr('class', 'label label-important');
|
||||
} else if(!passwordvalid) {
|
||||
password_notify.html('Invalid password');
|
||||
password_notify.attr('class', 'label label-important');
|
||||
} else {
|
||||
password_notify.html('OK!');
|
||||
password_notify.attr('class', 'label label-success');
|
||||
}
|
||||
|
||||
onPasswordConfirmChanged();
|
||||
}
|
||||
|
||||
function onPasswordConfirmChanged() {
|
||||
if(password.val() !== password_confirm.val()) {
|
||||
password_confirm_notify.html('Passwords must match!');
|
||||
password_confirm_notify.attr('class', 'label label-important');
|
||||
passwordsmatch = false;
|
||||
} else {
|
||||
password_confirm_notify.html('OK!');
|
||||
password_confirm_notify.attr('class', 'label label-success');
|
||||
passwordsmatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
password.on('keyup', onPasswordChanged);
|
||||
password_confirm.on('keyup', onPasswordConfirmChanged);
|
||||
|
||||
$('#changePasswordBtn').on('click', function() {
|
||||
|
||||
if(passwordvalid && passwordsmatch && currentPassword.val()) {
|
||||
socket.emit('api:user.changePassword', {'currentPassword': currentPassword.val(),'newPassword': password.val() }, function(data) {
|
||||
|
||||
currentPassword.val('');
|
||||
password.val('');
|
||||
password_confirm.val('');
|
||||
password_notify.html('');
|
||||
password_confirm_notify.html('');
|
||||
passwordsmatch = false;
|
||||
passwordvalid = false;
|
||||
|
||||
if(data.err) {
|
||||
app.alertError(data.err);
|
||||
return;
|
||||
}
|
||||
|
||||
app.alertSuccess('Your password is updated!');
|
||||
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}());
|
||||
return AccountEdit;
|
||||
});
|
||||
@@ -1,36 +1,43 @@
|
||||
(function() {
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid');
|
||||
define(function() {
|
||||
var AccountHeader = {};
|
||||
|
||||
AccountHeader.init = function() {
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid');
|
||||
|
||||
function createMenu() {
|
||||
var userslug = $('.account-username-box').attr('data-userslug');
|
||||
var links = $('<div class="account-sub-links inline-block pull-right">\
|
||||
<span id="settingsLink" class="pull-right"><a href="/users/' + userslug + '/settings">settings</a></span>\
|
||||
<span id="favouritesLink" class="pull-right"><a href="/users/' + userslug + '/favourites">favourites</a></span>\
|
||||
<span class="pull-right"><a href="/users/' + userslug + '/followers">followers</a></span>\
|
||||
<span class="pull-right"><a href="/users/' + userslug + '/following">following</a></span>\
|
||||
<span id="editLink" class="pull-right"><a href="/users/' + userslug + '/edit">edit</a></span>\
|
||||
</div>');
|
||||
|
||||
$('.account-username-box').append(links);
|
||||
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
createMenu();
|
||||
AccountHeader.createMenu();
|
||||
|
||||
var editLink = $('#editLink');
|
||||
var settingsLink = $('#settingsLink');
|
||||
var favouritesLink = $('#favouritesLink');
|
||||
|
||||
if(yourid === "0" || yourid !== theirid) {
|
||||
|
||||
if (yourid === "0" || yourid !== theirid) {
|
||||
editLink.hide();
|
||||
settingsLink.hide();
|
||||
favouritesLink.hide();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}());
|
||||
jQuery('.account-sub-links span a').removeClass('bold').each(function() {
|
||||
var href = this.getAttribute('href');
|
||||
if (window.location.href.indexOf(href) !== -1) {
|
||||
jQuery(this).addClass('bold');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AccountHeader.createMenu = function() {
|
||||
var userslug = $('.account-username-box').attr('data-userslug');
|
||||
var links = $('<div class="account-sub-links inline-block pull-right">\
|
||||
<span id="settingsLink" class="pull-right"><a href="/user/' + userslug + '/settings">settings</a></span>\
|
||||
<span id="favouritesLink" class="pull-right"><a href="/user/' + userslug + '/favourites">favourites</a></span>\
|
||||
<span class="pull-right"><a href="/user/' + userslug + '/followers">followers</a></span>\
|
||||
<span class="pull-right"><a href="/user/' + userslug + '/following">following</a></span>\
|
||||
<span id="editLink" class="pull-right"><a href="/user/' + userslug + '/edit">edit</a></span>\
|
||||
</div>');
|
||||
|
||||
$('.account-username-box').append(links);
|
||||
}
|
||||
|
||||
return AccountHeader;
|
||||
});
|
||||
@@ -1,22 +1,25 @@
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var AccountSettings = {};
|
||||
|
||||
AccountSettings.init = function() {
|
||||
header.init();
|
||||
|
||||
$('#submitBtn').on('click', function() {
|
||||
|
||||
$(document).ready(function() {
|
||||
var settings = {
|
||||
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
|
||||
};
|
||||
|
||||
$('#submitBtn').on('click', function() {
|
||||
|
||||
var settings = {
|
||||
showemail: $('#showemailCheckBox').is(':checked')?1:0
|
||||
};
|
||||
|
||||
socket.emit('api:user.saveSettings', settings, function(success) {
|
||||
if(success) {
|
||||
app.alertSuccess('Settings saved!');
|
||||
} else {
|
||||
app.alertError('There was an error saving settings!');
|
||||
}
|
||||
socket.emit('api:user.saveSettings', settings, function(err) {
|
||||
if (!err) {
|
||||
app.alertSuccess('Settings saved!');
|
||||
} else {
|
||||
app.alertError('There was an error saving settings!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
return AccountSettings;
|
||||
});
|
||||
|
||||
@@ -1,103 +1,350 @@
|
||||
define(['uploader'], function(uploader) {
|
||||
var Categories = {};
|
||||
|
||||
var modified_categories = {};
|
||||
Categories.init = function() {
|
||||
var modified_categories = {};
|
||||
|
||||
function modified(el) {
|
||||
var cid = $(el).parents('li').attr('data-cid');
|
||||
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid][el.getAttribute('data-name')] = el.value;
|
||||
}
|
||||
|
||||
function save() {
|
||||
socket.emit('api:admin.categories.update', modified_categories);
|
||||
modified_categories = {};
|
||||
}
|
||||
|
||||
function select_icon(el) {
|
||||
var selected = el.className.replace(' icon-2x', '');
|
||||
jQuery('#icons .selected').removeClass('selected');
|
||||
jQuery('#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.className = iconClass + ' icon icon-2x';
|
||||
el.value = iconClass;
|
||||
|
||||
modified(el);
|
||||
function modified(el) {
|
||||
var cid = $(el).parents('li').attr('data-cid');
|
||||
if(cid) {
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('.bootbox .span3').on('click', function() {
|
||||
jQuery('.bootbox .selected').removeClass('selected');
|
||||
jQuery(this).addClass('selected');
|
||||
});
|
||||
}
|
||||
function save() {
|
||||
socket.emit('api:admin.categories.update', modified_categories);
|
||||
modified_categories = {};
|
||||
}
|
||||
|
||||
function select_icon(el) {
|
||||
var selected = el.attr('class').replace(' fa-2x', '');
|
||||
$('#icons .selected').removeClass('selected');
|
||||
if (selected)
|
||||
$('#icons .' + selected).parent().addClass('selected');
|
||||
|
||||
|
||||
function update_blockclass(el) {
|
||||
el.parentNode.parentNode.className = 'entry-row ' + el.value;
|
||||
}
|
||||
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
|
||||
if (confirm) {
|
||||
var iconClass = $('.bootbox .selected').children(':first').attr('class');
|
||||
|
||||
jQuery('#entry-container').sortable();
|
||||
jQuery('.blockclass').each(function() {
|
||||
jQuery(this).val(this.getAttribute('data-value'));
|
||||
});
|
||||
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
|
||||
$('.bootbox .col-md-3').on('click', function() {
|
||||
$('.bootbox .selected').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
//DRY Failure. this needs to go into an ajaxify onready style fn. Currently is copy pasted into every single function so after ACP is off the ground fix asap
|
||||
(function() {
|
||||
jQuery('document').ready(function() {
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length-1];
|
||||
function update_blockclass(el) {
|
||||
el.parentNode.parentNode.className = 'entry-row ' + el.value;
|
||||
}
|
||||
|
||||
jQuery('.nav-pills li').removeClass('active');
|
||||
jQuery('.nav-pills li a').each(function() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
return false;
|
||||
function updateCategoryOrders() {
|
||||
var categories = $('.admin-categories #entry-container').children();
|
||||
for(var i=0; i<categories.length; ++i) {
|
||||
var input = $(categories[i]).find('input[data-name="order"]');
|
||||
|
||||
input.val(i+1).attr('data-value', i+1);
|
||||
modified(input);
|
||||
}
|
||||
}
|
||||
|
||||
$('#entry-container').sortable({
|
||||
stop: function( event, ui ) {
|
||||
updateCategoryOrders();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#save').on('click', save);
|
||||
|
||||
jQuery('.icon').on('click', function(ev) {
|
||||
select_icon(ev.target);
|
||||
$('.blockclass').each(function() {
|
||||
$(this).val(this.getAttribute('data-value'));
|
||||
});
|
||||
|
||||
jQuery('.blockclass').on('change', function(ev) {
|
||||
update_blockclass(ev.target);
|
||||
|
||||
function showCreateCategoryModal() {
|
||||
$('#new-category-modal').modal();
|
||||
}
|
||||
|
||||
function createNewCategory() {
|
||||
var category = {
|
||||
name: $('#inputName').val(),
|
||||
description: $('#inputDescription').val(),
|
||||
icon: $('#new-category-modal i').val(),
|
||||
bgColor: '#0059b2',
|
||||
color: '#fff',
|
||||
order: $('.admin-categories #entry-container').children().length + 1
|
||||
};
|
||||
|
||||
socket.emit('api:admin.categories.create', category, function(err, data) {
|
||||
if (!err) {
|
||||
app.alert({
|
||||
alert_id: 'category_created',
|
||||
title: 'Created',
|
||||
message: 'Category successfully created!',
|
||||
type: 'success',
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
|
||||
categories: [data]
|
||||
});
|
||||
$('#entry-container').append(html);
|
||||
|
||||
$('#new-category-modal').modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('document').ready(function() {
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
|
||||
$('.nav-pills li').removeClass('active');
|
||||
$('.nav-pills li a').each(function() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
$(this.parentNode).addClass('active');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$('#save').on('click', save);
|
||||
$('#addNew').on('click', showCreateCategoryModal);
|
||||
$('#create-category-btn').on('click', createNewCategory);
|
||||
|
||||
$('#entry-container').on('click', '.icon', function(ev) {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
$('#new-category-modal').on('click', '.icon', function(ev) {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
$('.admin-categories form input').on('change', function(ev) {
|
||||
modified(ev.target);
|
||||
});
|
||||
|
||||
$('.dropdown li[data-disabled]').each(function(index, element) {
|
||||
var disabled = $(element).attr('data-disabled');
|
||||
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>');
|
||||
}
|
||||
});
|
||||
|
||||
$('.dropdown').on('click', '[data-disabled]', function(ev) {
|
||||
var btn = $(this);
|
||||
var categoryRow = btn.parents('li');
|
||||
var cid = categoryRow.attr('data-cid');
|
||||
|
||||
var disabled = this.getAttribute('data-disabled') === '0' ? '1' : '0';
|
||||
categoryRow.remove();
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid]['disabled'] = disabled;
|
||||
|
||||
save();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Colour Picker
|
||||
$('[data-name="bgColor"], [data-name="color"]').each(function(idx, inputEl) {
|
||||
var jinputEl = $(this),
|
||||
previewEl = jinputEl.parents('[data-cid]').find('.preview-box');
|
||||
|
||||
jinputEl.ColorPicker({
|
||||
color: this.value || '#000',
|
||||
onChange: function(hsb, hex) {
|
||||
jinputEl.val('#' + hex);
|
||||
if (inputEl.getAttribute('data-name') === 'bgColor') previewEl.css('background', '#' + hex);
|
||||
else if (inputEl.getAttribute('data-name') === 'color') previewEl.css('color', '#' + hex);
|
||||
modified(inputEl);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Permissions modal
|
||||
$('.permissions').on('click', function() {
|
||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||
Categories.launchPermissionsModal(cid);
|
||||
});
|
||||
|
||||
|
||||
$('.upload-button').on('click', function() {
|
||||
var inputEl = this;
|
||||
|
||||
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', function(imageUrlOnServer) {
|
||||
inputEl.value = imageUrlOnServer;
|
||||
$(inputEl).parents('li[data-cid]').find('.preview-box').css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
|
||||
modified(inputEl);
|
||||
});
|
||||
});
|
||||
|
||||
$('.admin-categories').delegate('.delete-image', 'click', function() {
|
||||
var parent = $(this).parents('li[data-cid]'),
|
||||
inputEl = parent.find('.upload-button'),
|
||||
preview = parent.find('.preview-box'),
|
||||
bgColor = parent.find('.category_bgColor').val();
|
||||
|
||||
inputEl.value = '';
|
||||
modified(inputEl);
|
||||
|
||||
preview.css('background', bgColor);
|
||||
|
||||
$(this).hide();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Categories.launchPermissionsModal = function(cid) {
|
||||
var modal = $('#category-permissions-modal'),
|
||||
searchEl = modal.find('#permission-search'),
|
||||
resultsEl = modal.find('.search-results'),
|
||||
groupsResultsEl = modal.find('.groups-results'),
|
||||
searchDelay;
|
||||
|
||||
searchEl.off().on('keyup', function() {
|
||||
var searchEl = this,
|
||||
resultsFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
clearTimeout(searchDelay);
|
||||
|
||||
searchDelay = setTimeout(function() {
|
||||
socket.emit('api:admin.categories.search', searchEl.value, cid, function(err, results) {
|
||||
var numResults = results.length,
|
||||
resultObj;
|
||||
for(var x=0;x<numResults;x++) {
|
||||
resultObj = results[x];
|
||||
|
||||
liEl.setAttribute('data-uid', resultObj.uid);
|
||||
liEl.innerHTML = '<div class="pull-right">' +
|
||||
'<div class="btn-group">' +
|
||||
'<button type="button" data-priv="+r" class="btn btn-default' + (resultObj.privileges['+r'] ? ' active' : '') + '">Read</button>' +
|
||||
'<button type="button" data-priv="+w" class="btn btn-default' + (resultObj.privileges['+w'] ? ' active' : '') + '">Write</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<img src="' + resultObj.picture + '" /> ' + resultObj.username;
|
||||
|
||||
resultsFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
resultsEl.html(resultsFrag);
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
jQuery('.category_name, .category_description, .blockclass').on('change', function(ev) {
|
||||
modified(ev.target);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
jQuery('.entry-row button').each(function(index, element) {
|
||||
var disabled = $(element).attr('data-disabled');
|
||||
if(disabled == "0" || disabled == "")
|
||||
$(element).html('Disable');
|
||||
else
|
||||
$(element).html('Enable');
|
||||
|
||||
modal.off().on('click', '.members li > img', function() {
|
||||
searchEl.val(this.getAttribute('title'));
|
||||
searchEl.keyup();
|
||||
});
|
||||
|
||||
jQuery('.entry-row button').on('click', function(ev) {
|
||||
var btn = jQuery(this);
|
||||
var categoryRow = btn.parents('li');
|
||||
var cid = categoryRow.attr('data-cid');
|
||||
|
||||
var disabled = btn.html() == "Disable" ? "1":"0";
|
||||
categoryRow.remove();
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid]['disabled'] = disabled;
|
||||
|
||||
save();
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
// 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,122 +1,42 @@
|
||||
jQuery('document').ready(function() {
|
||||
// On menu click, change "active" state
|
||||
var menuEl = document.querySelector('.sidebar-nav'),
|
||||
liEls = menuEl.querySelectorAll('li')
|
||||
parentEl = null;
|
||||
|
||||
|
||||
|
||||
var nodebb_admin = (function(nodebb_admin) {
|
||||
|
||||
nodebb_admin.config = undefined;
|
||||
|
||||
nodebb_admin.prepare = function() {
|
||||
// Come back in 500ms if the config isn't ready yet
|
||||
if (nodebb_admin.config === undefined) {
|
||||
setTimeout(function() {
|
||||
nodebb_admin.prepare();
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate the fields on the page from the config
|
||||
var fields = document.querySelectorAll('#content [data-field]'),
|
||||
numFields = fields.length,
|
||||
saveBtn = document.getElementById('save'),
|
||||
x, key, inputType;
|
||||
for(x=0;x<numFields;x++) {
|
||||
key = fields[x].getAttribute('data-field');
|
||||
inputType = fields[x].getAttribute('type');
|
||||
if (fields[x].nodeName === 'INPUT') {
|
||||
if (nodebb_admin.config[key]) {
|
||||
switch(inputType) {
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
case 'number':
|
||||
fields[x].value = nodebb_admin.config[key];
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
fields[x].checked = nodebb_admin.config[key] === '1' ? true : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (fields[x].nodeName === 'TEXTAREA') {
|
||||
if (nodebb_admin.config[key]) fields[x].value = nodebb_admin.config[key];
|
||||
menuEl.addEventListener('click', function(e) {
|
||||
parentEl = e.target.parentNode;
|
||||
if (parentEl.nodeName === 'LI') {
|
||||
for (var x = 0, numLis = liEls.length; x < numLis; x++) {
|
||||
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
|
||||
else jQuery(parentEl).addClass('active');
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
saveBtn.addEventListener('click', function(e) {
|
||||
var key, value;
|
||||
e.preventDefault();
|
||||
socket.once('api:config.get', function(config) {
|
||||
app.config = config;
|
||||
});
|
||||
|
||||
for(x=0;x<numFields;x++) {
|
||||
key = fields[x].getAttribute('data-field');
|
||||
if (fields[x].nodeName === 'INPUT') {
|
||||
inputType = fields[x].getAttribute('type');
|
||||
switch(inputType) {
|
||||
case 'text':
|
||||
case 'number':
|
||||
value = fields[x].value;
|
||||
break;
|
||||
socket.emit('api:config.get');
|
||||
|
||||
case 'checkbox':
|
||||
value = fields[x].checked ? '1' : '0';
|
||||
break;
|
||||
}
|
||||
} else if (fields[x].nodeName === 'TEXTAREA') {
|
||||
value = fields[x].value;
|
||||
}
|
||||
|
||||
socket.emit('api:config.set', { key: key, value: value });
|
||||
}
|
||||
socket.on('api:config.set', function(data) {
|
||||
if (data.status === 'ok') {
|
||||
app.alert({
|
||||
alert_id: 'config_status',
|
||||
timeout: 2500,
|
||||
title: 'Changes Saved',
|
||||
message: 'Your changes to the NodeBB configuration have been saved.',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
app.alert({
|
||||
alert_id: 'config_status',
|
||||
timeout: 2500,
|
||||
title: 'Changes Not Saved',
|
||||
message: 'NodeBB encountered a problem saving your changes',
|
||||
type: 'danger'
|
||||
});
|
||||
}
|
||||
|
||||
nodebb_admin.remove = function(key) {
|
||||
socket.emit('api:config.remove', key);
|
||||
}
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
// On menu click, change "active" state
|
||||
var menuEl = document.querySelector('.sidebar-nav'),
|
||||
liEls = menuEl.querySelectorAll('li')
|
||||
parentEl = null;
|
||||
|
||||
menuEl.addEventListener('click', function(e) {
|
||||
parentEl = e.target.parentNode;
|
||||
if (parentEl.nodeName === 'LI') {
|
||||
for(var x=0,numLis=liEls.length;x<numLis;x++) {
|
||||
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
|
||||
else jQuery(parentEl).addClass('active');
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
socket.once('api:config.get', function(config) {
|
||||
nodebb_admin.config = config;
|
||||
});
|
||||
|
||||
socket.emit('api:config.get');
|
||||
|
||||
socket.on('api:config.set', function(data) {
|
||||
if (data.status === 'ok') {
|
||||
app.alert({
|
||||
alert_id: 'config_status',
|
||||
timeout: 2500,
|
||||
title: 'Changes Saved',
|
||||
message: 'Your changes to the NodeBB configuration have been saved. You may have to restart NodeBB to see the changes.',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
app.alert({
|
||||
alert_id: 'config_status',
|
||||
timeout: 2500,
|
||||
title: 'Changes Not Saved',
|
||||
message: 'NodeBB encountered a problem saving your changes',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return nodebb_admin;
|
||||
|
||||
}(nodebb_admin || {}));
|
||||
|
||||
});
|
||||
204
public/src/forum/admin/groups.js
Normal file
204
public/src/forum/admin/groups.js
Normal file
@@ -0,0 +1,204 @@
|
||||
define(function() {
|
||||
var Groups = {};
|
||||
|
||||
Groups.init = function() {
|
||||
var createEl = document.getElementById('create'),
|
||||
createModal = $('#create-modal'),
|
||||
createSubmitBtn = document.getElementById('create-modal-go'),
|
||||
createNameEl = $('#create-group-name'),
|
||||
detailsModal = $('#group-details-modal'),
|
||||
detailsSearch = detailsModal.find('#group-details-search'),
|
||||
searchResults = detailsModal.find('#group-details-search-results'),
|
||||
groupMembersEl = detailsModal.find('ul.current_members'),
|
||||
detailsModalSave = detailsModal.find('.btn-primary'),
|
||||
searchDelay = undefined,
|
||||
listEl = $('#groups-list');
|
||||
|
||||
createEl.addEventListener('click', function() {
|
||||
createModal.modal('show');
|
||||
setTimeout(function() {
|
||||
createNameEl.focus();
|
||||
}, 250);
|
||||
}, false);
|
||||
|
||||
createSubmitBtn.addEventListener('click', function() {
|
||||
var submitObj = {
|
||||
name: createNameEl.val(),
|
||||
description: $('#create-group-desc').val()
|
||||
},
|
||||
errorEl = $('#create-modal-error'),
|
||||
errorText;
|
||||
|
||||
socket.emit('api:groups.create', submitObj, function(err, data) {
|
||||
if (err) {
|
||||
switch (err) {
|
||||
case 'group-exists':
|
||||
errorText = '<strong>Please choose another name</strong><p>There seems to be a group with this name already.</p>';
|
||||
break;
|
||||
case 'name-too-short':
|
||||
errorText = '<strong>Please specify a grou name</strong><p>A group name is required for administrative purposes.</p>';
|
||||
break;
|
||||
default:
|
||||
errorText = '<strong>Uh-Oh</strong><p>There was a problem creating your group. Please try again later!</p>';
|
||||
break;
|
||||
}
|
||||
|
||||
errorEl.html(errorText).removeClass('hide');
|
||||
} else {
|
||||
errorEl.addClass('hide');
|
||||
createNameEl.val('');
|
||||
createModal.on('hidden.bs.modal', function() {
|
||||
ajaxify.go('admin/groups');
|
||||
});
|
||||
createModal.modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
listEl.on('click', 'button[data-action]', function() {
|
||||
var action = this.getAttribute('data-action'),
|
||||
gid = $(this).parents('li[data-gid]').attr('data-gid');
|
||||
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:groups.delete', gid, function(err, data) {
|
||||
if (data === 'OK') ajaxify.go('admin/groups');
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'members':
|
||||
socket.emit('api:groups.get', gid, function(err, groupObj) {
|
||||
var formEl = detailsModal.find('form'),
|
||||
nameEl = formEl.find('#change-group-name'),
|
||||
descEl = formEl.find('#change-group-desc'),
|
||||
memberIcon = document.createElement('li'),
|
||||
numMembers = groupObj.members.length,
|
||||
membersFrag = document.createDocumentFragment(),
|
||||
memberIconImg, x;
|
||||
|
||||
|
||||
nameEl.val(groupObj.name);
|
||||
descEl.val(groupObj.description);
|
||||
|
||||
// Member list
|
||||
memberIcon.innerHTML = '<img /><span></span>';
|
||||
memberIconImg = memberIcon.querySelector('img');
|
||||
memberIconLabel = memberIcon.querySelector('span');
|
||||
if (numMembers > 0) {
|
||||
for (x = 0; x < numMembers; x++) {
|
||||
memberIconImg.src = groupObj.members[x].picture;
|
||||
memberIconLabel.innerHTML = groupObj.members[x].username;
|
||||
memberIcon.setAttribute('data-uid', groupObj.members[x].uid);
|
||||
membersFrag.appendChild(memberIcon.cloneNode(true));
|
||||
}
|
||||
groupMembersEl.html('');
|
||||
groupMembersEl[0].appendChild(membersFrag);
|
||||
}
|
||||
|
||||
detailsModal.attr('data-gid', groupObj.gid);
|
||||
detailsModal.modal('show');
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
detailsSearch.on('keyup', function() {
|
||||
var searchEl = this;
|
||||
|
||||
if (searchDelay) clearTimeout(searchDelay);
|
||||
|
||||
searchDelay = setTimeout(function() {
|
||||
var searchText = searchEl.value,
|
||||
resultsEl = document.getElementById('group-details-search-results'),
|
||||
foundUser = document.createElement('li'),
|
||||
foundUserImg, foundUserLabel;
|
||||
|
||||
foundUser.innerHTML = '<img /><span></span>';
|
||||
foundUserImg = foundUser.getElementsByTagName('img')[0];
|
||||
foundUserLabel = foundUser.getElementsByTagName('span')[0];
|
||||
|
||||
socket.emit('api:admin.user.search', searchText, function(err, results) {
|
||||
if (!err && results && results.length > 0) {
|
||||
var numResults = results.length,
|
||||
resultsSlug = document.createDocumentFragment(),
|
||||
x;
|
||||
if (numResults > 4) numResults = 4;
|
||||
for (x = 0; x < numResults; x++) {
|
||||
foundUserImg.src = results[x].picture;
|
||||
foundUserLabel.innerHTML = results[x].username;
|
||||
foundUser.setAttribute('title', results[x].username);
|
||||
foundUser.setAttribute('data-uid', results[x].uid);
|
||||
resultsSlug.appendChild(foundUser.cloneNode(true));
|
||||
}
|
||||
|
||||
resultsEl.innerHTML = '';
|
||||
resultsEl.appendChild(resultsSlug);
|
||||
} else resultsEl.innerHTML = '<li>No Users Found</li>';
|
||||
});
|
||||
}, 200);
|
||||
});
|
||||
|
||||
searchResults.on('click', 'li[data-uid]', function() {
|
||||
var userLabel = this,
|
||||
uid = parseInt(this.getAttribute('data-uid')),
|
||||
gid = detailsModal.attr('data-gid'),
|
||||
members = [];
|
||||
|
||||
groupMembersEl.find('li[data-uid]').each(function() {
|
||||
members.push(parseInt(this.getAttribute('data-uid')));
|
||||
});
|
||||
|
||||
if (members.indexOf(uid) === -1) {
|
||||
socket.emit('api:groups.join', {
|
||||
gid: gid,
|
||||
uid: uid
|
||||
}, function(err, data) {
|
||||
if (!err) {
|
||||
groupMembersEl.append(userLabel.cloneNode(true));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
groupMembersEl.on('click', 'li[data-uid]', function() {
|
||||
var uid = this.getAttribute('data-uid'),
|
||||
gid = detailsModal.attr('data-gid');
|
||||
|
||||
socket.emit('api:groups.leave', {
|
||||
gid: gid,
|
||||
uid: uid
|
||||
}, function(err, data) {
|
||||
if (!err) {
|
||||
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
detailsModalSave.on('click', function() {
|
||||
var formEl = detailsModal.find('form'),
|
||||
nameEl = formEl.find('#change-group-name'),
|
||||
descEl = formEl.find('#change-group-desc'),
|
||||
gid = detailsModal.attr('data-gid');
|
||||
|
||||
socket.emit('api:groups.update', {
|
||||
gid: gid,
|
||||
values: {
|
||||
name: nameEl.val(),
|
||||
description: descEl.val()
|
||||
}
|
||||
}, function(err) {
|
||||
if (!err) {
|
||||
detailsModal.on('hidden.bs.modal', function() {
|
||||
ajaxify.go('admin/groups');
|
||||
});
|
||||
detailsModal.modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return Groups;
|
||||
});
|
||||
@@ -1,25 +1,36 @@
|
||||
define(function() {
|
||||
var Admin = {};
|
||||
|
||||
(function() {
|
||||
|
||||
ajaxify.register_events(['api:get_all_rooms']);
|
||||
socket.on('api:get_all_rooms', function(data) {
|
||||
Admin.init = function() {
|
||||
ajaxify.register_events(['api:get_all_rooms']);
|
||||
socket.on('api:get_all_rooms', function(data) {
|
||||
|
||||
var active_users = document.getElementById('active_users'),
|
||||
total = 0;
|
||||
active_users.innerHTML = '';
|
||||
|
||||
for(var room in data) {
|
||||
if (room !== '') {
|
||||
var count = data[room].length;
|
||||
total += count;
|
||||
active_users.innerHTML = active_users.innerHTML + "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
|
||||
var active_users = document.getElementById('active_users'),
|
||||
total = 0;
|
||||
active_users.innerHTML = '';
|
||||
|
||||
for (var room in data) {
|
||||
if (room !== '') {
|
||||
var count = data[room].length;
|
||||
total += count;
|
||||
active_users.innerHTML = active_users.innerHTML + "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('connections').innerHTML = total;
|
||||
});
|
||||
document.getElementById('connections').innerHTML = total;
|
||||
});
|
||||
|
||||
app.enter_room('admin');
|
||||
socket.emit('api:get_all_rooms');
|
||||
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;
|
||||
});
|
||||
|
||||
@@ -1,38 +1,33 @@
|
||||
var nodebb_admin = nodebb_admin || {};
|
||||
define(function() {
|
||||
var Plugins = {
|
||||
init: function() {
|
||||
var pluginsList = $('.plugins'),
|
||||
numPlugins = pluginsList[0].querySelectorAll('li').length,
|
||||
pluginID, pluginTgl;
|
||||
|
||||
(function() {
|
||||
var plugins = {
|
||||
init: function() {
|
||||
var pluginsList = $('.plugins'),
|
||||
numPlugins = pluginsList[0].querySelectorAll('li').length,
|
||||
pluginID, pluginTgl;
|
||||
if (numPlugins > 0) {
|
||||
pluginsList.on('click', 'button[data-action="toggleActive"]', function() {
|
||||
pluginID = $(this).parents('li').attr('data-plugin-id');
|
||||
socket.emit('api:admin.plugins.toggle', pluginID);
|
||||
});
|
||||
|
||||
if (numPlugins > 0) {
|
||||
pluginsList.on('click', 'button[data-action="toggleActive"]', function() {
|
||||
pluginID = $(this).parents('li').attr('data-plugin-id');
|
||||
socket.emit('api:admin.plugins.toggle', pluginID);
|
||||
});
|
||||
socket.on('api:admin.plugins.toggle', function(status) {
|
||||
pluginTgl = document.querySelector('.plugins li[data-plugin-id="' + status.id + '"] button');
|
||||
pluginTgl.innerHTML = '<i class="fa fa-power-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';
|
||||
|
||||
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';
|
||||
|
||||
app.alert({
|
||||
alert_id: 'plugin_toggled_' + status.id,
|
||||
title: 'Plugin Enabled',
|
||||
message: 'You may need to restart NodeBB in order for these changes to be reflected.',
|
||||
type: 'notify',
|
||||
timeout: 5000
|
||||
})
|
||||
});
|
||||
} else {
|
||||
pluginsList.append('<li><p><i>No plugins found.</i></p></li>');
|
||||
}
|
||||
app.alert({
|
||||
alert_id: 'plugin_toggled_' + status.id,
|
||||
title: 'Plugin Enabled',
|
||||
message: 'You may need to restart NodeBB in order for these changes to be reflected.',
|
||||
type: 'warning',
|
||||
timeout: 5000
|
||||
})
|
||||
});
|
||||
} else {
|
||||
pluginsList.append('<li><p><i>No plugins found.</i></p></li>');
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
nodebb_admin.plugins = plugins;
|
||||
nodebb_admin.plugins.init();
|
||||
});
|
||||
})();
|
||||
return Plugins;
|
||||
});
|
||||
99
public/src/forum/admin/settings.js
Normal file
99
public/src/forum/admin/settings.js
Normal file
@@ -0,0 +1,99 @@
|
||||
define(['uploader'], function(uploader) {
|
||||
var Settings = {};
|
||||
|
||||
Settings.init = function() {
|
||||
Settings.prepare();
|
||||
};
|
||||
|
||||
Settings.prepare = function() {
|
||||
// Come back in 125ms if the config isn't ready yet
|
||||
if (!app.config) {
|
||||
setTimeout(function() {
|
||||
Settings.prepare();
|
||||
}, 125);
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate the fields on the page from the config
|
||||
var fields = document.querySelectorAll('#content [data-field]'),
|
||||
numFields = fields.length,
|
||||
saveBtn = document.getElementById('save'),
|
||||
x, key, inputType;
|
||||
for (x = 0; x < numFields; x++) {
|
||||
key = fields[x].getAttribute('data-field');
|
||||
inputType = fields[x].getAttribute('type');
|
||||
if (fields[x].nodeName === 'INPUT') {
|
||||
if (app.config[key]) {
|
||||
switch (inputType) {
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
case 'number':
|
||||
fields[x].value = app.config[key];
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
saveBtn.addEventListener('click', function(e) {
|
||||
var key, value;
|
||||
e.preventDefault();
|
||||
|
||||
for (x = 0; x < numFields; x++) {
|
||||
key = fields[x].getAttribute('data-field');
|
||||
if (fields[x].nodeName === 'INPUT') {
|
||||
inputType = fields[x].getAttribute('type');
|
||||
switch (inputType) {
|
||||
case 'text':
|
||||
case 'number':
|
||||
value = fields[x].value;
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
value = fields[x].checked ? '1' : '0';
|
||||
break;
|
||||
}
|
||||
} 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', {
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#uploadLogoBtn').on('click', function() {
|
||||
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) {
|
||||
socket.emit('api:config.remove', key);
|
||||
};
|
||||
|
||||
return Settings;
|
||||
});
|
||||
@@ -1,118 +1,132 @@
|
||||
define(function() {
|
||||
var Themes = {};
|
||||
|
||||
Themes.init = function() {
|
||||
var scriptEl = document.createElement('script');
|
||||
scriptEl.src = 'http://api.bootswatch.com/3/?callback=bootswatchListener';
|
||||
document.body.appendChild(scriptEl);
|
||||
|
||||
var nodebb_admin = (function(nodebb_admin) {
|
||||
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
||||
installedThemeContainer = document.querySelector('#installed_themes'),
|
||||
themeEvent = function(e) {
|
||||
if (e.target.hasAttribute('data-action')) {
|
||||
switch (e.target.getAttribute('data-action')) {
|
||||
case 'preview':
|
||||
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
||||
cssEl = document.getElementById('base-theme');
|
||||
|
||||
var themes = {};
|
||||
cssEl.href = cssSrc;
|
||||
break;
|
||||
case 'use':
|
||||
var parentEl = $(e.target).parents('li'),
|
||||
themeType = parentEl.attr('data-type'),
|
||||
cssSrc = parentEl.attr('data-css'),
|
||||
themeId = parentEl.attr('data-theme');
|
||||
|
||||
themes.render = function(bootswatch) {
|
||||
socket.emit('api:admin.theme.set', {
|
||||
type: themeType,
|
||||
id: themeId,
|
||||
src: cssSrc
|
||||
}, function(err) {
|
||||
app.alert({
|
||||
alert_id: 'admin:theme',
|
||||
type: 'success',
|
||||
title: 'Theme Changed',
|
||||
message: 'You have successfully changed your NodeBB\'s theme. Please restart to see the changes.',
|
||||
timeout: 2500
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
bootstrapThemeContainer.addEventListener('click', themeEvent);
|
||||
installedThemeContainer.addEventListener('click', themeEvent);
|
||||
|
||||
var revertEl = document.getElementById('revert_theme');
|
||||
revertEl.addEventListener('click', function() {
|
||||
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:admin.theme.set', {
|
||||
type: 'local',
|
||||
id: 'nodebb-theme-cerulean'
|
||||
}, function(err) {
|
||||
app.alert({
|
||||
alert_id: 'admin:theme',
|
||||
type: 'success',
|
||||
title: 'Theme Changed',
|
||||
message: 'You have successfully reverted your NodeBB back to it\'s default theme. Please restart to see the changes.',
|
||||
timeout: 3500
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}, false);
|
||||
|
||||
// Installed Themes
|
||||
socket.emit('api:admin.themes.getInstalled', function(themes) {
|
||||
var instListEl = document.getElementById('installed_themes'),
|
||||
themeFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
liEl.setAttribute('data-type', 'local');
|
||||
|
||||
if (themes.length > 0) {
|
||||
for (var x = 0, numThemes = themes.length; x < numThemes; x++) {
|
||||
liEl.setAttribute('data-theme', themes[x].id);
|
||||
liEl.innerHTML = '<img src="' + (themes[x].screenshot ? '/css/previews/' + themes[x].id : RELATIVE_PATH + '/images/themes/default.png') + '" />' +
|
||||
'<div>' +
|
||||
'<div class="pull-right">' +
|
||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||
'<button class="btn btn-default" data-action="preview">Preview</button>' +
|
||||
'</div>' +
|
||||
'<h4>' + themes[x].name + '</h4>' +
|
||||
'<p>' +
|
||||
themes[x].description +
|
||||
(themes[x].url ? ' (<a href="' + themes[x].url + '">Homepage</a>)' : '') +
|
||||
'</p>' +
|
||||
'</div>' +
|
||||
'<div class="clear">';
|
||||
themeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
// No themes found
|
||||
liEl.className = 'no-themes';
|
||||
liEl.innerHTML = 'No installed themes found';
|
||||
themeFrag.appendChild(liEl);
|
||||
}
|
||||
|
||||
instListEl.innerHTML = '';
|
||||
instListEl.appendChild(themeFrag);
|
||||
});
|
||||
}
|
||||
|
||||
Themes.render = function(bootswatch) {
|
||||
var themeFrag = document.createDocumentFragment(),
|
||||
themeEl = document.createElement('li'),
|
||||
themeContainer = document.querySelector('#bootstrap_themes'),
|
||||
numThemes = bootswatch.themes.length;
|
||||
|
||||
for(var x=0;x<numThemes;x++) {
|
||||
themeEl.setAttribute('data-type', 'bootswatch');
|
||||
|
||||
for (var x = 0; x < numThemes; x++) {
|
||||
var theme = bootswatch.themes[x];
|
||||
themeEl.setAttribute('data-css', theme.cssMin);
|
||||
themeEl.setAttribute('data-theme', theme.name);
|
||||
themeEl.innerHTML = '<img src="' + theme.thumbnail + '" />' +
|
||||
'<div>' +
|
||||
'<div class="pull-right">' +
|
||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||
'<button class="btn" data-action="preview">Preview</button>' +
|
||||
'</div>' +
|
||||
'<h4>' + theme.name + '</h4>' +
|
||||
'<p>' + theme.description + '</p>' +
|
||||
'</div>' +
|
||||
'<div class="clear">';
|
||||
themeEl.innerHTML = '<img src="' + theme.thumbnail + '" />' +
|
||||
'<div>' +
|
||||
'<div class="pull-right">' +
|
||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||
'<button class="btn btn-default" data-action="preview">Preview</button>' +
|
||||
'</div>' +
|
||||
'<h4>' + theme.name + '</h4>' +
|
||||
'<p>' + theme.description + '</p>' +
|
||||
'</div>' +
|
||||
'<div class="clear">';
|
||||
themeFrag.appendChild(themeEl.cloneNode(true));
|
||||
}
|
||||
themeContainer.innerHTML = '';
|
||||
themeContainer.appendChild(themeFrag);
|
||||
}
|
||||
|
||||
nodebb_admin.themes = themes;
|
||||
|
||||
return nodebb_admin;
|
||||
|
||||
}(nodebb_admin || {}));
|
||||
|
||||
|
||||
(function() {
|
||||
var scriptEl = document.createElement('script');
|
||||
scriptEl.src = 'http://api.bootswatch.com/2/?callback=nodebb_admin.themes.render';
|
||||
document.body.appendChild(scriptEl);
|
||||
|
||||
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
||||
installedThemeContainer = document.querySelector('#installed_themes'),
|
||||
themeEvent = function(e) {
|
||||
if (e.target.hasAttribute('data-action')) {
|
||||
switch(e.target.getAttribute('data-action')) {
|
||||
case 'preview':
|
||||
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
||||
cssEl = document.getElementById('base-theme');
|
||||
|
||||
cssEl.href = cssSrc;
|
||||
break;
|
||||
case 'use':
|
||||
var parentEl = $(e.target).parents('li'),
|
||||
cssSrc = parentEl.attr('data-css'),
|
||||
cssName = parentEl.attr('data-theme');
|
||||
socket.emit('api:config.set', {
|
||||
key: 'theme:id', value: 'bootswatch:' + cssName
|
||||
});
|
||||
socket.emit('api:config.set', {
|
||||
key: 'theme:src', value: cssSrc
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
bootstrapThemeContainer.addEventListener('click', themeEvent);
|
||||
installedThemeContainer.addEventListener('click', themeEvent);
|
||||
|
||||
var revertEl = document.getElementById('revert_theme');
|
||||
revertEl.addEventListener('click', function() {
|
||||
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
|
||||
if (confirm) {
|
||||
nodebb_admin.remove('theme:id');
|
||||
nodebb_admin.remove('theme:src');
|
||||
}
|
||||
});
|
||||
}, false);
|
||||
|
||||
// Installed Themes
|
||||
socket.emit('api:admin.themes.getInstalled', function(themes) {
|
||||
var instListEl = document.getElementById('installed_themes'),
|
||||
themeFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
|
||||
if (themes.length > 0) {
|
||||
for(var x=0,numThemes=themes.length;x<numThemes;x++) {
|
||||
liEl.setAttribute('data-theme', themes[x].id);
|
||||
liEl.setAttribute('data-css', themes[x].src);
|
||||
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
|
||||
'<div>' +
|
||||
'<div class="pull-right">' +
|
||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||
'<button class="btn" data-action="preview">Preview</button>' +
|
||||
'</div>' +
|
||||
'<h4>' + themes[x].name + '</h4>' +
|
||||
'<p>' +
|
||||
themes[x].description +
|
||||
(themes[x].url ? ' (<a href="' + themes[x].url + '">Homepage</a>)' : '') +
|
||||
'</p>' +
|
||||
'</div>' +
|
||||
'<div class="clear">';
|
||||
themeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
// No themes found
|
||||
liEl.className = 'no-themes';
|
||||
liEl.innerHTML = 'No installed themes found';
|
||||
themeFrag.appendChild(liEl);
|
||||
}
|
||||
|
||||
instListEl.innerHTML = '';
|
||||
instListEl.appendChild(themeFrag);
|
||||
});
|
||||
})();
|
||||
return Themes;
|
||||
});
|
||||
@@ -1,115 +1,158 @@
|
||||
$(document).ready(function() {
|
||||
var topicsListEl = document.querySelector('.topics'),
|
||||
loadMoreEl = document.getElementById('topics_loadmore');
|
||||
define(function() {
|
||||
var Topics = {};
|
||||
|
||||
$(topicsListEl).on('click', '[data-action]', function() {
|
||||
var $this = $(this),
|
||||
action = this.getAttribute('data-action'),
|
||||
tid = $this.parents('[data-tid]').attr('data-tid');
|
||||
Topics.init = function() {
|
||||
var topicsListEl = document.querySelector('.topics'),
|
||||
loadMoreEl = document.getElementById('topics_loadmore');
|
||||
|
||||
switch(action) {
|
||||
case 'pin':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.pin', { tid: tid });
|
||||
else socket.emit('api:topic.unpin', { tid: tid });
|
||||
break;
|
||||
case 'lock':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.lock', { tid: tid });
|
||||
else socket.emit('api:topic.unlock', { tid: tid });
|
||||
break;
|
||||
case 'delete':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.delete', { tid: tid });
|
||||
else socket.emit('api:topic.restore', { tid: tid });
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.resolveButtonStates();
|
||||
|
||||
loadMoreEl.addEventListener('click', function() {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
var topics = document.querySelectorAll('.topics li[data-tid]'),
|
||||
lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
|
||||
$(topicsListEl).on('click', '[data-action]', function() {
|
||||
var $this = $(this),
|
||||
action = this.getAttribute('data-action'),
|
||||
tid = $this.parents('[data-tid]').attr('data-tid');
|
||||
|
||||
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
|
||||
socket.emit('api:admin.topics.getMore', {
|
||||
limit: 10,
|
||||
after: lastTid
|
||||
}, function(topics) {
|
||||
var btnEl = document.getElementById('topics_loadmore');
|
||||
switch (action) {
|
||||
case 'pin':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.pin', {
|
||||
tid: tid
|
||||
});
|
||||
else socket.emit('api:topic.unpin', {
|
||||
tid: tid
|
||||
});
|
||||
break;
|
||||
case 'lock':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.lock', {
|
||||
tid: tid
|
||||
});
|
||||
else socket.emit('api:topic.unlock', {
|
||||
tid: tid
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
if (!$this.hasClass('active')) socket.emit('api:topic.delete', {
|
||||
tid: tid
|
||||
});
|
||||
else socket.emit('api:topic.restore', {
|
||||
tid: tid
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
topics = JSON.parse(topics);
|
||||
if (topics.length > 0) {
|
||||
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
topicsListEl = document.querySelector('.topics');
|
||||
loadMoreEl.addEventListener('click', function() {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
var topics = document.querySelectorAll('.topics li[data-tid]');
|
||||
|
||||
topicsListEl.innerHTML += html;
|
||||
btnEl.innerHTML = 'Load More Topics';
|
||||
} else {
|
||||
// Exhausted all topics
|
||||
btnEl.className += ' disabled';
|
||||
btnEl.innerHTML = 'No more topics';
|
||||
if(!topics.length) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
var lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
|
||||
|
||||
this.innerHTML = '<i class="fa fa-refresh fa-spin"></i> Retrieving topics';
|
||||
socket.emit('api:admin.topics.getMore', {
|
||||
limit: 10,
|
||||
after: lastTid
|
||||
}, function(topics) {
|
||||
var btnEl = document.getElementById('topics_loadmore');
|
||||
|
||||
topics = JSON.parse(topics);
|
||||
if (topics.length > 0) {
|
||||
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
topicsListEl = document.querySelector('.topics');
|
||||
|
||||
// Fix relative paths
|
||||
html = html.replace(/\{relative_path\}/g, RELATIVE_PATH);
|
||||
|
||||
topicsListEl.innerHTML += html;
|
||||
|
||||
Topics.resolveButtonStates();
|
||||
|
||||
btnEl.innerHTML = 'Load More Topics';
|
||||
$('span.timeago').timeago();
|
||||
} else {
|
||||
// Exhausted all topics
|
||||
btnEl.className += ' disabled';
|
||||
btnEl.innerHTML = 'No more topics';
|
||||
}
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
|
||||
socket.on('api:topic.pin', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.unpin', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.lock', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.unlock', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.delete', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
$(btnEl).siblings('[data-action="lock"]').addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.restore', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
$(btnEl).siblings('[data-action="lock"]').removeClass('active');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Topics.resolveButtonStates = function() {
|
||||
// Resolve proper button state for all topics
|
||||
var topicsListEl = document.querySelector('.topics'),
|
||||
topicEls = topicsListEl.querySelectorAll('li'),
|
||||
numTopics = topicEls.length;
|
||||
for (var x = 0; x < numTopics; x++) {
|
||||
if (topicEls[x].getAttribute('data-pinned') === '1') {
|
||||
topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
||||
topicEls[x].removeAttribute('data-pinned');
|
||||
}
|
||||
if (topicEls[x].getAttribute('data-locked') === '1') {
|
||||
topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
||||
topicEls[x].removeAttribute('data-locked');
|
||||
}
|
||||
if (topicEls[x].getAttribute('data-deleted') === '1') {
|
||||
topicEls[x].querySelector('[data-action="delete"]').className += ' active';
|
||||
topicEls[x].removeAttribute('data-deleted');
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
// Resolve proper button state for all topics
|
||||
var topicEls = topicsListEl.querySelectorAll('li'),
|
||||
numTopics = topicEls.length;
|
||||
for(var x=0;x<numTopics;x++) {
|
||||
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
|
||||
topicEls[x].removeAttribute('data-pinned');
|
||||
topicEls[x].removeAttribute('data-locked');
|
||||
topicEls[x].removeAttribute('data-deleted');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.pin', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.unpin', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.lock', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.unlock', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.delete', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.restore', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
|
||||
|
||||
$(btnEl).removeClass('active');
|
||||
}
|
||||
return Topics;
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
define(function() {
|
||||
var Users = {};
|
||||
|
||||
(function() {
|
||||
|
||||
function initUsers() {
|
||||
Users.init = function() {
|
||||
var yourid = templates.get('yourid');
|
||||
|
||||
function isUserAdmin(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
@@ -10,217 +11,200 @@
|
||||
|
||||
function isUserBanned(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
|
||||
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
|
||||
}
|
||||
|
||||
function getUID(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return parent.attr('data-uid');
|
||||
return parent.attr('data-uid');
|
||||
}
|
||||
|
||||
jQuery('.admin-btn').each(function(index, element) {
|
||||
var adminBtn = $(element);
|
||||
var isAdmin = isUserAdmin(adminBtn);
|
||||
|
||||
if(isAdmin)
|
||||
adminBtn.addClass('btn-success');
|
||||
else
|
||||
adminBtn.removeClass('btn-success');
|
||||
|
||||
});
|
||||
|
||||
jQuery('.delete-btn').each(function(index, element) {
|
||||
var deleteBtn = $(element);
|
||||
var isAdmin = isUserAdmin(deleteBtn);
|
||||
|
||||
if(isAdmin)
|
||||
deleteBtn.addClass('disabled');
|
||||
else
|
||||
deleteBtn.show();
|
||||
});
|
||||
|
||||
jQuery('.ban-btn').each(function(index, element) {
|
||||
var banBtn = $(element);
|
||||
var isAdmin = isUserAdmin(banBtn);
|
||||
var isBanned = isUserBanned(banBtn);
|
||||
|
||||
if(isAdmin)
|
||||
banBtn.addClass('disabled');
|
||||
else if(isBanned)
|
||||
banBtn.addClass('btn-warning');
|
||||
else
|
||||
banBtn.removeClass('btn-warning');
|
||||
|
||||
});
|
||||
|
||||
jQuery('.admin-btn').on('click', function() {
|
||||
var adminBtn = $(this);
|
||||
var isAdmin = isUserAdmin(adminBtn);
|
||||
var parent = adminBtn.parents('.users-box');
|
||||
var uid = getUID(adminBtn);
|
||||
|
||||
if(isAdmin) {
|
||||
socket.emit('api:admin.user.removeAdmin', uid);
|
||||
adminBtn.removeClass('btn-success');
|
||||
parent.find('.delete-btn').removeClass('disabled');
|
||||
parent.attr('data-admin', 0);
|
||||
}
|
||||
else {
|
||||
bootbox.confirm('Do you really want to make "' + parent.attr('data-username') +'" an admin?', function(confirm) {
|
||||
if(confirm) {
|
||||
socket.emit('api:admin.user.makeAdmin', uid);
|
||||
adminBtn.addClass('btn-success');
|
||||
parent.find('.delete-btn').addClass('disabled');
|
||||
parent.attr('data-admin', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('.delete-btn').on('click', function() {
|
||||
var deleteBtn = $(this);
|
||||
var isAdmin = isUserAdmin(deleteBtn);
|
||||
var parent = deleteBtn.parents('.users-box');
|
||||
var uid = getUID(deleteBtn);
|
||||
|
||||
if(!isAdmin) {
|
||||
bootbox.confirm('Do you really want to delete "' + parent.attr('data-username') +'"?', function(confirm) {
|
||||
socket.emit('api:admin.user.deleteUser', uid);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('.ban-btn').on('click', function() {
|
||||
var banBtn = $(this);
|
||||
var isAdmin = isUserAdmin(banBtn);
|
||||
var isBanned = isUserBanned(banBtn);
|
||||
var parent = banBtn.parents('.users-box');
|
||||
var uid = getUID(banBtn);
|
||||
|
||||
if(!isAdmin) {
|
||||
if(isBanned) {
|
||||
socket.emit('api:admin.user.unbanUser', uid);
|
||||
function updateUserButtons() {
|
||||
jQuery('.ban-btn').each(function(index, element) {
|
||||
var banBtn = $(element);
|
||||
var uid = getUID(banBtn);
|
||||
if (isUserAdmin(banBtn) || uid === yourid)
|
||||
banBtn.addClass('disabled');
|
||||
else if (isUserBanned(banBtn))
|
||||
banBtn.addClass('btn-warning');
|
||||
else
|
||||
banBtn.removeClass('btn-warning');
|
||||
parent.attr('data-banned', 0);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function initUsers() {
|
||||
|
||||
updateUserButtons();
|
||||
|
||||
$('#users-container').on('click', '.ban-btn', function() {
|
||||
var banBtn = $(this);
|
||||
var isAdmin = isUserAdmin(banBtn);
|
||||
var isBanned = isUserBanned(banBtn);
|
||||
var parent = banBtn.parents('.users-box');
|
||||
var uid = getUID(banBtn);
|
||||
|
||||
if (!isAdmin) {
|
||||
if (isBanned) {
|
||||
socket.emit('api:admin.user.unbanUser', uid);
|
||||
banBtn.removeClass('btn-warning');
|
||||
parent.attr('data-banned', 0);
|
||||
} 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
|
||||
var timeoutId = 0,
|
||||
loadingMoreUsers = false;
|
||||
|
||||
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() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#search-user').on('keyup', function() {
|
||||
if (timeoutId !== 0) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = 0;
|
||||
}
|
||||
|
||||
timeoutId = setTimeout(function() {
|
||||
var username = $('#search-user').val();
|
||||
|
||||
jQuery('.fa-spinner').removeClass('none');
|
||||
socket.emit('api:admin.user.search', username);
|
||||
|
||||
}, 250);
|
||||
});
|
||||
|
||||
initUsers();
|
||||
|
||||
handleUserCreate();
|
||||
|
||||
socket.removeAllListeners('api:admin.user.search');
|
||||
|
||||
socket.on('api:admin.user.search', function(data) {
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||
users: data
|
||||
}),
|
||||
userListEl = document.querySelector('.users');
|
||||
|
||||
userListEl.innerHTML = html;
|
||||
jQuery('.fa-spinner').addClass('none');
|
||||
|
||||
if (data && data.length === 0) {
|
||||
$('#user-notfound-notify').html('User not found!')
|
||||
.show()
|
||||
.addClass('label-danger')
|
||||
.removeClass('label-success');
|
||||
} else {
|
||||
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') +'"?', function(confirm) {
|
||||
socket.emit('api:admin.user.banUser', uid);
|
||||
banBtn.addClass('btn-warning');
|
||||
parent.attr('data-banned', 1);
|
||||
$('#user-notfound-notify').html(data.length + ' user' + (data.length > 1 ? 's' : '') + ' found!')
|
||||
.show()
|
||||
.addClass('label-success')
|
||||
.removeClass('label-danger');
|
||||
}
|
||||
|
||||
initUsers();
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||
users: users
|
||||
});
|
||||
$('#users-container').append(html);
|
||||
updateUserButtons();
|
||||
}
|
||||
|
||||
function loadMoreUsers() {
|
||||
var set = '';
|
||||
if (active === 'latest') {
|
||||
set = 'users:joindate';
|
||||
} else if (active === 'sort-posts') {
|
||||
set = 'users:postcount';
|
||||
} else if (active === 'sort-reputation') {
|
||||
set = 'users:reputation';
|
||||
}
|
||||
|
||||
if (set) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: $('#users-container').children().length
|
||||
}, function(data) {
|
||||
if (data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
|
||||
loadMoreUsers();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
timeoutId = 0,
|
||||
loadingMoreUsers = false;
|
||||
|
||||
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() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#search-user').on('keyup', function () {
|
||||
if(timeoutId !== 0) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = 0;
|
||||
}
|
||||
|
||||
timeoutId = setTimeout(function() {
|
||||
var username = $('#search-user').val();
|
||||
|
||||
jQuery('.icon-spinner').removeClass('none');
|
||||
socket.emit('api:admin.user.search', username);
|
||||
|
||||
}, 250);
|
||||
});
|
||||
|
||||
initUsers();
|
||||
|
||||
socket.removeAllListeners('api:admin.user.search');
|
||||
|
||||
socket.on('api:admin.user.search', function(data) {
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||
users: data
|
||||
}),
|
||||
userListEl = document.querySelector('.users');
|
||||
|
||||
userListEl.innerHTML = html;
|
||||
jQuery('.icon-spinner').addClass('none');
|
||||
|
||||
if(data && data.length === 0) {
|
||||
$('#user-notfound-notify').html('User not found!')
|
||||
.show()
|
||||
.addClass('label-important')
|
||||
.removeClass('label-success');
|
||||
}
|
||||
else {
|
||||
$('#user-notfound-notify').html(data.length + ' user'+(data.length>1?'s':'') + ' found!')
|
||||
.show()
|
||||
.addClass('label-success')
|
||||
.removeClass('label-important');
|
||||
}
|
||||
|
||||
initUsers();
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ users: users });
|
||||
$('#users-container').append(html);
|
||||
}
|
||||
|
||||
function loadMoreUsers() {
|
||||
var set = '';
|
||||
if(active === 'latest') {
|
||||
set = 'users:joindate';
|
||||
} else if(active === 'sort-posts') {
|
||||
set = 'users:postcount';
|
||||
} else if(active === 'sort-reputation') {
|
||||
set = 'users:reputation';
|
||||
}
|
||||
|
||||
if(set) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: $('#users-container').children().length
|
||||
}, function(data) {
|
||||
if(data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
|
||||
loadMoreUsers();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}());
|
||||
return Users;
|
||||
});
|
||||
@@ -1,134 +1,171 @@
|
||||
(function() {
|
||||
var cid = templates.get('category_id'),
|
||||
room = 'category_' + cid,
|
||||
twitterEl = document.getElementById('twitter-intent'),
|
||||
facebookEl = document.getElementById('facebook-share'),
|
||||
googleEl = document.getElementById('google-share'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url'),
|
||||
define(['composer'], function(composer) {
|
||||
var Category = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
app.enter_room(room);
|
||||
Category.init = function() {
|
||||
var cid = templates.get('category_id'),
|
||||
twitterEl = jQuery('#twitter-intent'),
|
||||
facebookEl = jQuery('#facebook-share'),
|
||||
googleEl = jQuery('#google-share'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url');
|
||||
|
||||
twitterEl.addEventListener('click', function() {
|
||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
facebookEl.addEventListener('click', function() {
|
||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
googleEl.addEventListener('click', function() {
|
||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
app.enterRoom('category_' + cid);
|
||||
|
||||
var new_post = document.getElementById('new_post');
|
||||
new_post.onclick = function() {
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(0, cid);
|
||||
twitterEl.on('click', function () {
|
||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
facebookEl.on('click', function () {
|
||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
googleEl.on('click', function () {
|
||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#new_post').on('click', function () {
|
||||
composer.newTopic(cid);
|
||||
});
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic'
|
||||
]);
|
||||
|
||||
socket.on('event:new_topic', Category.onNewTopic);
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
socket.on('api:categories.getRecentReplies', function (posts) {
|
||||
if (!posts || posts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var recent_replies = document.getElementById('category_recent_replies');
|
||||
|
||||
recent_replies.innerHTML = '';
|
||||
|
||||
var frag = document.createDocumentFragment(),
|
||||
li = document.createElement('li');
|
||||
for (var i = 0, numPosts = posts.length; i < numPosts; i++) {
|
||||
|
||||
li.setAttribute('data-pid', posts[i].pid);
|
||||
|
||||
|
||||
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded user-img" src="' + posts[i].picture + '" class="" /></a>' +
|
||||
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
|
||||
'<strong><span>'+ posts[i].username + '</span></strong>' +
|
||||
'<p>' +
|
||||
posts[i].content +
|
||||
'</p>' +
|
||||
'</a>' +
|
||||
'<span class="timeago pull-right" title="' + posts[i].relativeTime + '"></span>';
|
||||
|
||||
frag.appendChild(li.cloneNode(true));
|
||||
recent_replies.appendChild(frag);
|
||||
}
|
||||
$('#category_recent_replies span.timeago').timeago();
|
||||
app.createUserTooltips();
|
||||
});
|
||||
|
||||
$(window).off('scroll').on('scroll', function (ev) {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||
Category.loadMoreTopics(cid);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Category.onNewTopic = function(data) {
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||
topics: [data]
|
||||
});
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var topic = $(translatedHTML),
|
||||
container = $('#topics-container'),
|
||||
topics = $('#topics-container').children('.category-item'),
|
||||
numTopics = topics.length;
|
||||
|
||||
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;
|
||||
}
|
||||
topic.insertBefore(topics[x]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
container.append(topic);
|
||||
}
|
||||
|
||||
topic.hide().fadeIn('slow');
|
||||
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
|
||||
|
||||
addActiveUser(data);
|
||||
|
||||
$('#topics-container span.timeago').timeago();
|
||||
});
|
||||
}
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic'
|
||||
]);
|
||||
|
||||
function onNewTopic(data) {
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: [data] }),
|
||||
topic = document.createElement('div'),
|
||||
container = document.getElementById('topics-container'),
|
||||
topics = document.querySelectorAll('#topics-container a'),
|
||||
numTopics = topics.length,
|
||||
x;
|
||||
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
|
||||
topic.innerHTML = html;
|
||||
topic = topic.querySelector('a');
|
||||
|
||||
if (numTopics > 0) {
|
||||
for(x=0;x<numTopics;x++) {
|
||||
if (topics[x].querySelector('.icon-pushpin')) continue;
|
||||
container.insertBefore(topic, topics[x]);
|
||||
$(topic).hide().fadeIn('slow');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
container.insertBefore(topic, null);
|
||||
$(topic).hide().fadeIn('slow');
|
||||
function addActiveUser(data) {
|
||||
var activeUser = $('.category-sidebar .active-users').find('a[data-uid="' + data.uid + '"]');
|
||||
if(!activeUser.length) {
|
||||
var newUser = templates.prepare(templates['category'].blocks['active_users']).parse({
|
||||
active_users: [{
|
||||
uid: data.uid,
|
||||
username: data.username,
|
||||
userslug: data.userslug,
|
||||
picture: data.teaser_userpicture
|
||||
}]
|
||||
});
|
||||
$(newUser).appendTo($('.category-sidebar .active-users'));
|
||||
}
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
}
|
||||
|
||||
socket.on('event:new_topic', onNewTopic);
|
||||
Category.onTopicsLoaded = function(topics) {
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
});
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
socket.on('api:categories.getRecentReplies', function(posts) {
|
||||
if (!posts || posts.length === 0) {
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container');
|
||||
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
|
||||
html = $(translatedHTML);
|
||||
container.append(html);
|
||||
|
||||
$('#topics-container span.timeago').timeago();
|
||||
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
|
||||
});
|
||||
}
|
||||
|
||||
Category.loadMoreTopics = function(cid) {
|
||||
if (loadingMoreTopics) {
|
||||
return;
|
||||
}
|
||||
|
||||
var recent_replies = document.getElementById('category_recent_replies');
|
||||
|
||||
recent_replies.innerHTML = '';
|
||||
|
||||
var frag = document.createDocumentFragment(),
|
||||
li = document.createElement('li');
|
||||
for (var i=0,numPosts=posts.length; i<numPosts; i++) {
|
||||
var dateString = utils.relativeTime(posts[i].timestamp);
|
||||
li.setAttribute('data-pid', posts[i].pid);
|
||||
|
||||
|
||||
li.innerHTML = '<a href="/users/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-polaroid" src="' + posts[i].picture + '" class="" /></a>' +
|
||||
'<a href="/topic/'+ posts[i].topicSlug + '#' + posts[i].pid + '">' +
|
||||
'<p>' +
|
||||
'<strong>' + posts[i].username + '</strong>: ' + posts[i].content +
|
||||
'</p>' +
|
||||
'<span>posted ' + utils.relativeTime(posts[i].timestamp) + ' ago</span>' +
|
||||
'</a>';
|
||||
|
||||
frag.appendChild(li.cloneNode(true));
|
||||
recent_replies.appendChild(frag);
|
||||
}
|
||||
});
|
||||
|
||||
function onTopicsLoaded(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();
|
||||
|
||||
container.append(html);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function loadMoreTopics(cid) {
|
||||
loadingMoreTopics = true;
|
||||
socket.emit('api:category.loadMore', {
|
||||
cid: cid,
|
||||
after: $('#topics-container').children().length
|
||||
}, function(data) {
|
||||
if(data.topics.length) {
|
||||
onTopicsLoaded(data.topics);
|
||||
after: $('#topics-container').children('.category-item').length
|
||||
}, function (data) {
|
||||
if (data.topics.length) {
|
||||
Category.onTopicsLoaded(data.topics);
|
||||
}
|
||||
loadingMoreTopics = false;
|
||||
});
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function(ev) {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics(cid);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
return Category;
|
||||
});
|
||||
@@ -1,11 +1,9 @@
|
||||
(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var AccountHeader = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
AccountHeader.init = function() {
|
||||
header.init();
|
||||
};
|
||||
|
||||
$('.user-favourite-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}());
|
||||
return AccountHeader;
|
||||
});
|
||||
@@ -1,18 +1,20 @@
|
||||
(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var Followers = {};
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
followersCount = templates.get('followersCount');
|
||||
Followers.init = function() {
|
||||
header.init();
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
followersCount = templates.get('followersCount');
|
||||
|
||||
|
||||
if (parseInt(followersCount, 10) === 0) {
|
||||
$('#no-followers-notice').removeClass('hide');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
if(parseInt(followersCount, 10) === 0) {
|
||||
$('#no-followers-notice').show();
|
||||
}
|
||||
|
||||
app.addCommasToNumbers();
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}());
|
||||
return Followers;
|
||||
});
|
||||
@@ -1,39 +1,17 @@
|
||||
(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var Following = {};
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
followingCount = templates.get('followingCount');
|
||||
Following.init = function() {
|
||||
header.init();
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
if(parseInt(followingCount, 10) === 0) {
|
||||
$('#no-following-notice').show();
|
||||
}
|
||||
var followingCount = templates.get('followingCount');
|
||||
|
||||
|
||||
if(yourid !== theirid) {
|
||||
$('.unfollow-btn').hide();
|
||||
}
|
||||
else {
|
||||
$('.unfollow-btn').on('click',function() {
|
||||
var unfollowBtn = $(this);
|
||||
var followingUid = $(this).attr('followingUid');
|
||||
|
||||
socket.emit('api:user.unfollow', {uid: followingUid}, function(success) {
|
||||
var username = unfollowBtn.attr('data-username');
|
||||
if(success) {
|
||||
unfollowBtn.parent().remove();
|
||||
app.alertSuccess('You are no longer following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error unfollowing ' + username + '!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
if (parseInt(followingCount, 10) === 0) {
|
||||
$('#no-following-notice').removeClass('hide');
|
||||
}
|
||||
|
||||
app.addCommasToNumbers();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}());
|
||||
return Following;
|
||||
});
|
||||
@@ -1,178 +1,270 @@
|
||||
(function() {
|
||||
var num_users = document.getElementById('number_of_users'),
|
||||
post_stats = document.getElementById('post_stats'),
|
||||
latest_user = document.getElementById('latest_user'),
|
||||
active_users = document.getElementById('active_users'),
|
||||
user_label = document.getElementById('user_label'),
|
||||
active_record = document.getElementById('active_record'),
|
||||
right_menu = document.getElementById('right-menu');
|
||||
|
||||
socket.emit('user.count', {});
|
||||
socket.on('user.count', function(data) {
|
||||
num_users.innerHTML = "We currently have <b>" + data.count + "</b> registered users.";
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
|
||||
socket.emit('post.stats');
|
||||
socket.on('post.stats', function(data) {
|
||||
post_stats.innerHTML = "Our users have created <b>" + data.topics + "</b> topics and made <b>" + data.posts + "</b> posts.";
|
||||
});
|
||||
|
||||
socket.emit('user.latest', {});
|
||||
socket.on('user.latest', function(data) {
|
||||
if (data.username == '') {
|
||||
latest_user.innerHTML = '';
|
||||
} else {
|
||||
latest_user.innerHTML = "The most recent user to register is <b><a href='/users/"+data.userslug+"'>" + data.username + "</a></b>.";
|
||||
}
|
||||
});
|
||||
|
||||
socket.emit('api:user.active.get');
|
||||
socket.on('api:user.active.get', function(data) {
|
||||
|
||||
var plural_users = parseInt(data.users) !== 1,
|
||||
plural_anon = parseInt(data.anon) !== 1;
|
||||
|
||||
active_users.innerHTML = 'There ' + (plural_users ? 'are' : 'is') + ' <strong>' + data.users + '</strong> user' + (plural_users ? 's' : '') + ' and <strong>' + data.anon + '</strong> guest' + (plural_anon ? 's' : '') + ' online';
|
||||
});
|
||||
|
||||
socket.emit('api:user.active.get_record');
|
||||
socket.on('api:user.active.get_record', function(data) {
|
||||
active_record.innerHTML = "most users ever online was <strong>" + data.record + "</strong> on <strong>" + (new Date(parseInt(data.timestamp,10))).toUTCString() + "</strong>";
|
||||
});
|
||||
|
||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
||||
|
||||
socket.on('api:updateHeader', function(data) {
|
||||
|
||||
var rightMenu = $('#right-menu'),
|
||||
isLoggedIn = data.uid > 0;
|
||||
$('#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() {
|
||||
$('#search-fields').hide();
|
||||
$('#search-button').show();
|
||||
});
|
||||
});
|
||||
|
||||
var loggedInMenu = $('#logged-in-menu'),
|
||||
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();
|
||||
|
||||
var userLabel = rightMenu.find('#user_label');
|
||||
if(userLabel.length) {
|
||||
if(data['userslug'])
|
||||
userLabel.attr('href','/users/' + data['userslug']);
|
||||
if(data['picture'])
|
||||
userLabel.find('img').attr('src',data['picture']);
|
||||
if(data['username'])
|
||||
$('#logged-out-menu').addClass('hide');
|
||||
$('#logged-in-menu').removeClass('hide');
|
||||
|
||||
$('#search-button').removeClass("hide").show();
|
||||
|
||||
var userLabel = loggedInMenu.find('#user_label');
|
||||
|
||||
if (userLabel.length) {
|
||||
if (data['userslug'])
|
||||
userLabel.find('#user-profile-link').attr('href', '/user/' + data['userslug']);
|
||||
if (data['picture'])
|
||||
userLabel.find('img').attr('src', data['picture']);
|
||||
if (data['username'])
|
||||
userLabel.find('span').html(data['username']);
|
||||
} else {
|
||||
var userli = $('<li> \
|
||||
<a id="user_label" href="/users/'+data['userslug']+'"> \
|
||||
<img src="'+data['picture']+'"/> \
|
||||
<span>'+data['username']+'</span> \
|
||||
</a> \
|
||||
</li>');
|
||||
rightMenu.append(userli);
|
||||
|
||||
var logoutli = $('<li><a href="' + RELATIVE_PATH + '/logout">Log out</a></li>');
|
||||
rightMenu.append(logoutli);
|
||||
$('#logout-link').on('click', app.logout);
|
||||
}
|
||||
} else {
|
||||
jQuery('.nodebb-loggedin').hide();
|
||||
jQuery('.nodebb-loggedout').show();
|
||||
if (allowGuestSearching) {
|
||||
$('#search-button').removeClass("hide").show();
|
||||
} else {
|
||||
$('#search-button').addClass("hide").hide();
|
||||
}
|
||||
|
||||
rightMenu.html('');
|
||||
$('.nodebb-loggedin').hide();
|
||||
$('.nodebb-loggedout').show();
|
||||
|
||||
var registerEl = document.createElement('li'),
|
||||
loginEl = document.createElement('li');
|
||||
$('#logged-out-menu').removeClass('hide');
|
||||
$('#logged-in-menu').addClass('hide');
|
||||
|
||||
registerEl.innerHTML = '<a href="/register">Register</a>';
|
||||
loginEl.innerHTML = '<a href="/login">Login</a>';
|
||||
|
||||
right_menu.appendChild(registerEl);
|
||||
right_menu.appendChild(loginEl);
|
||||
}
|
||||
|
||||
$('#main-nav a,#user-control-list a,#logged-out-menu .dropdown-menu a').off('click').on('click', function() {
|
||||
if($('.navbar .navbar-collapse').hasClass('in'))
|
||||
$('.navbar-header button').click();
|
||||
});
|
||||
});
|
||||
|
||||
// Notifications dropdown
|
||||
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) {
|
||||
socket.emit('api:notifications.get', null, function(data) {
|
||||
var notifFrag = document.createDocumentFragment(),
|
||||
var notifFrag = document.createDocumentFragment(),
|
||||
notifEl = document.createElement('li'),
|
||||
numRead = data.read.length,
|
||||
numUnread = data.unread.length,
|
||||
x;
|
||||
notifList.innerHTML = '';
|
||||
if ((data.read.length + data.unread.length) > 0) {
|
||||
for(x=0;x<numUnread;x++) {
|
||||
for (x = 0; x < numUnread; x++) {
|
||||
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
||||
notifEl.className = 'unread';
|
||||
notifEl.innerHTML = '<a href="' + data.unread[x].path + '"><span class="pull-right">' + utils.relativeTime(data.unread[x].datetime, true) + '</span>' + data.unread[x].text + '</a>';
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
}
|
||||
for(x=0;x<numRead;x++) {
|
||||
for (x = 0; x < numRead; x++) {
|
||||
notifEl.setAttribute('data-nid', data.read[x].nid);
|
||||
notifEl.className = '';
|
||||
notifEl.innerHTML = '<a href="' + data.read[x].path + '"><span class="pull-right">' + utils.relativeTime(data.read[x].datetime, true) + '</span>' + data.read[x].text + '</a>';
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
notifEl.className = 'no-notifs';
|
||||
notifEl.innerHTML = '<a>You have no notifications</a>';
|
||||
notifFrag.appendChild(notifEl);
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
}
|
||||
|
||||
// Add dedicated link to /notifications
|
||||
notifEl.removeAttribute('data-nid');
|
||||
notifEl.className = 'pagelink';
|
||||
notifEl.innerHTML = '<a href="' + RELATIVE_PATH + '/notifications">See all Notifications</a>';
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
notifList.addEventListener('click', function(e) {
|
||||
var target;
|
||||
switch(e.target.nodeName) {
|
||||
case 'SPAN': target = e.target.parentNode.parentNode; break;
|
||||
case 'A': target = e.target.parentNode; break;
|
||||
case 'li': target = e.target; break;
|
||||
switch (e.target.nodeName) {
|
||||
case 'SPAN':
|
||||
target = e.target.parentNode.parentNode;
|
||||
break;
|
||||
case 'A':
|
||||
target = e.target.parentNode;
|
||||
break;
|
||||
case 'li':
|
||||
target = e.target;
|
||||
break;
|
||||
}
|
||||
if (target) {
|
||||
var nid = parseInt(target.getAttribute('data-nid'));
|
||||
if (nid > 0) socket.emit('api:notifications.mark_read', nid);
|
||||
}
|
||||
});
|
||||
|
||||
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',
|
||||
message: 'You have unread notifications.',
|
||||
type: 'notify',
|
||||
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) {
|
||||
var username = data.username;
|
||||
var fromuid = data.fromuid;
|
||||
var message = data.message;
|
||||
socket.emit('api:chats.list', function(chats) {
|
||||
var chatsFrag = document.createDocumentFragment(),
|
||||
chatEl = document.createElement('li'),
|
||||
numChats = chats.length,
|
||||
x, userObj;
|
||||
|
||||
require(['chat'], function(chat) {
|
||||
var chatModal = chat.createModalIfDoesntExist(username, fromuid);
|
||||
chatModal.show();
|
||||
chat.bringModalToTop(chatModal);
|
||||
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>';
|
||||
|
||||
chat.appendChatMessage(chatModal, message);
|
||||
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);
|
||||
|
||||
require(['mobileMenu'], function(mobileMenu) {
|
||||
mobileMenu.init();
|
||||
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');
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
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);
|
||||
|
||||
}());
|
||||
|
||||
30
public/src/forum/home.js
Normal file
30
public/src/forum/home.js
Normal file
@@ -0,0 +1,30 @@
|
||||
define(function() {
|
||||
var home = {};
|
||||
|
||||
home.init = function() {
|
||||
|
||||
ajaxify.register_events([
|
||||
'user.count',
|
||||
'post.stats',
|
||||
'api:user.active.get'
|
||||
]);
|
||||
|
||||
socket.emit('user.count', {});
|
||||
socket.on('user.count', function(data) {
|
||||
$('#stats_users').html(utils.makeNumberHumanReadable(data.count)).attr('title', data.count);
|
||||
});
|
||||
|
||||
socket.emit('post.stats');
|
||||
socket.on('post.stats', function(data) {
|
||||
$('#stats_topics').html(utils.makeNumberHumanReadable(data.topics)).attr('title', data.topics);
|
||||
$('#stats_posts').html(utils.makeNumberHumanReadable(data.posts)).attr('title', data.posts);
|
||||
});
|
||||
|
||||
socket.emit('api:user.active.get');
|
||||
socket.on('api:user.active.get', function(data) {
|
||||
$('#stats_online').html(data.users);
|
||||
});
|
||||
}
|
||||
|
||||
return home;
|
||||
});
|
||||
@@ -1,48 +1,65 @@
|
||||
define(function() {
|
||||
var Login = {};
|
||||
|
||||
Login.init = function() {
|
||||
$('#login').on('click', function() {
|
||||
var loginData = {
|
||||
'username': $('#username').val(),
|
||||
'password': $('#password').val(),
|
||||
'_csrf': $('#csrf-token').val()
|
||||
};
|
||||
|
||||
(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').attr('disabled', 'disabled').html('Logging in...');
|
||||
$('#login-error-notify').hide();
|
||||
|
||||
$('#login').on('click', function() {
|
||||
var loginData = {
|
||||
'username': $('#username').val(),
|
||||
'password': $('#password').val(),
|
||||
'_csrf': $('#csrf-token').val()
|
||||
};
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: RELATIVE_PATH + '/login',
|
||||
data: loginData,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: RELATIVE_PATH + '/login',
|
||||
data: loginData,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
if(!data.success) {
|
||||
$('#login-error-notify').html(data.message).show();
|
||||
} else {
|
||||
$('#login-error-notify').hide();
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
}
|
||||
},
|
||||
error : function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').show();
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
timeout: 2000
|
||||
if (!data.success) {
|
||||
$('#login-error-notify').show();
|
||||
$('#login').removeAttr('disabled').html('Login');
|
||||
} else {
|
||||
$('#login').html('Redirecting...');
|
||||
if(!app.previousUrl) {
|
||||
app.previousUrl = '/';
|
||||
}
|
||||
|
||||
if(app.previousUrl.indexOf('/reset/') != -1)
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
else
|
||||
window.location.replace(app.previousUrl + "?loggedin");
|
||||
|
||||
app.loadConfig();
|
||||
}
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').show();
|
||||
$('#login').removeAttr('disabled').html('Login');
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
$('#login-error-notify button').on('click', function() {
|
||||
$('#login-error-notify').hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
document.querySelector('#content input').focus();
|
||||
}());
|
||||
document.querySelector('#content input').focus();
|
||||
|
||||
if(!config.emailSetup)
|
||||
$('#reset-link').addClass('hide');
|
||||
else
|
||||
$('#reset-link').removeClass('hide');
|
||||
|
||||
};
|
||||
|
||||
return Login;
|
||||
});
|
||||
|
||||
31
public/src/forum/notifications.js
Normal file
31
public/src/forum/notifications.js
Normal file
@@ -0,0 +1,31 @@
|
||||
define(function() {
|
||||
var Notifications = {};
|
||||
|
||||
Notifications.init = function() {
|
||||
var listEl = $('.notifications-list'),
|
||||
markAllReadEl = document.getElementById('mark-all-notifs-read');
|
||||
|
||||
$('span.timeago').timeago();
|
||||
|
||||
// Allow the user to click anywhere in the LI
|
||||
listEl.on('click', 'li', function(e) {
|
||||
this.querySelector('a').click();
|
||||
});
|
||||
|
||||
// Mark all as read button
|
||||
$(markAllReadEl).click(function() {
|
||||
socket.emit('api:notifications.mark_all_read', {}, function() {
|
||||
ajaxify.go('notifications');
|
||||
app.alert({
|
||||
alert_id: "notifications:mark_all_read",
|
||||
title: "All Notifications Read",
|
||||
message: "Successfully marked all notifications read",
|
||||
type: 'success',
|
||||
timeout: 2500
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Notifications;
|
||||
});
|
||||
@@ -1,80 +1,114 @@
|
||||
(function() {
|
||||
var loadingMoreTopics = false;
|
||||
define(function() {
|
||||
var Recent = {};
|
||||
|
||||
app.enter_room('recent_posts');
|
||||
Recent.newTopicCount = 0;
|
||||
Recent.newPostCount = 0;
|
||||
Recent.loadingMoreTopics = false;
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
'event:new_post'
|
||||
]);
|
||||
var active = '';
|
||||
|
||||
var newTopicCount = 0, newPostCount = 0;
|
||||
Recent.init = function() {
|
||||
app.enterRoom('recent_posts');
|
||||
|
||||
$('#new-topics-alert').on('click', function() {
|
||||
$(this).hide();
|
||||
});
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
'event:new_post'
|
||||
]);
|
||||
|
||||
socket.on('event:new_topic', function(data) {
|
||||
|
||||
++newTopicCount;
|
||||
updateAlertText();
|
||||
|
||||
});
|
||||
|
||||
function updateAlertText() {
|
||||
|
||||
function getActiveSection() {
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
return active;
|
||||
}
|
||||
|
||||
active = getActiveSection();
|
||||
|
||||
jQuery('.nav-pills li').removeClass('active');
|
||||
jQuery('.nav-pills li a').each(function() {
|
||||
if (this.getAttribute('href').match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$('#new-topics-alert').on('click', function() {
|
||||
$(this).addClass('hide');
|
||||
});
|
||||
|
||||
socket.on('event:new_topic', function(data) {
|
||||
|
||||
++Recent.newTopicCount;
|
||||
Recent.updateAlertText();
|
||||
|
||||
});
|
||||
|
||||
socket.on('event:new_post', function(data) {
|
||||
++Recent.newPostCount;
|
||||
Recent.updateAlertText();
|
||||
});
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !Recent.loadingMoreTopics) {
|
||||
Recent.loadMoreTopics();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Recent.updateAlertText = function() {
|
||||
var text = '';
|
||||
|
||||
if(newTopicCount > 1)
|
||||
text = 'There are ' + newTopicCount + ' new topics';
|
||||
else if(newTopicCount === 1)
|
||||
|
||||
if (Recent.newTopicCount > 1)
|
||||
text = 'There are ' + Recent.newTopicCount + ' new topics';
|
||||
else if (Recent.newTopicCount === 1)
|
||||
text = 'There is 1 new topic';
|
||||
else
|
||||
text = 'There are no new topics';
|
||||
|
||||
if(newPostCount > 1)
|
||||
text += ' and ' + newPostCount + ' new posts.';
|
||||
else if(newPostCount === 1)
|
||||
|
||||
if (Recent.newPostCount > 1)
|
||||
text += ' and ' + Recent.newPostCount + ' new posts.';
|
||||
else if (Recent.newPostCount === 1)
|
||||
text += ' and 1 new post.';
|
||||
else
|
||||
text += ' and no new posts.';
|
||||
|
||||
text += ' Click here to reload.';
|
||||
|
||||
$('#new-topics-alert').html(text).fadeIn('slow');
|
||||
}
|
||||
|
||||
socket.on('event:new_post', function(data) {
|
||||
++newPostCount;
|
||||
updateAlertText();
|
||||
});
|
||||
|
||||
function onTopicsLoaded(topics) {
|
||||
|
||||
var html = templates.prepare(templates['recent'].blocks['topics']).parse({ topics: topics }),
|
||||
container = $('#topics-container');
|
||||
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
container.append(html);
|
||||
$('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow');
|
||||
}
|
||||
|
||||
function loadMoreTopics() {
|
||||
loadingMoreTopics = true;
|
||||
socket.emit('api:topics.loadMoreRecentTopics', {after:$('#topics-container').children().length}, function(data) {
|
||||
if(data.topics && data.topics.length) {
|
||||
onTopicsLoaded(data.topics);
|
||||
}
|
||||
loadingMoreTopics = false;
|
||||
Recent.onTopicsLoaded = function(topics) {
|
||||
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
});
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container');
|
||||
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
html = $(html);
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
|
||||
});
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
Recent.loadMoreTopics = function() {
|
||||
Recent.loadingMoreTopics = true;
|
||||
socket.emit('api:topics.loadMoreRecentTopics', {
|
||||
after: $('#topics-container').children('li').length,
|
||||
term: active
|
||||
}, function(data) {
|
||||
if (data.topics && data.topics.length) {
|
||||
Recent.onTopicsLoaded(data.topics);
|
||||
}
|
||||
Recent.loadingMoreTopics = false;
|
||||
});
|
||||
}
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
return Recent;
|
||||
});
|
||||
|
||||
@@ -1,157 +1,157 @@
|
||||
(function() {
|
||||
var username = document.getElementById('username'),
|
||||
password = document.getElementById('password'),
|
||||
password_confirm = document.getElementById('password-confirm'),
|
||||
register = document.getElementById('register'),
|
||||
emailEl = document.getElementById('email'),
|
||||
username_notify = document.getElementById('username-notify'),
|
||||
email_notify = document.getElementById('email-notify'),
|
||||
password_notify = document.getElementById('password-notify'),
|
||||
password_confirm_notify = document.getElementById('password-confirm-notify'),
|
||||
usernamevalid = false;
|
||||
emailexists = false,
|
||||
emailvalid = false,
|
||||
userexists = false,
|
||||
passwordsmatch = false,
|
||||
passwordvalid = false;
|
||||
define(function() {
|
||||
var Register = {};
|
||||
|
||||
$(username).on('keyup change', function() {
|
||||
usernamevalid = utils.isUserNameValid(username.value);
|
||||
Register.init = function() {
|
||||
var username = $('#username'),
|
||||
password = $('#password'),
|
||||
password_confirm = $('#password-confirm'),
|
||||
register = $('#register'),
|
||||
emailEl = $('#email'),
|
||||
username_notify = $('#username-notify'),
|
||||
email_notify = $('#email-notify'),
|
||||
password_notify = $('#password-notify'),
|
||||
password_confirm_notify = $('#password-confirm-notify'),
|
||||
validationError = false,
|
||||
successIcon = '<i class="fa fa-check"></i>';
|
||||
|
||||
|
||||
if(username.value.length < 3) {
|
||||
username_notify.innerHTML = 'Username too short';
|
||||
username_notify.className = 'label label-important';
|
||||
} else if(username.value.length > 13) {
|
||||
username_notify.innerHTML = 'Username too long';
|
||||
username_notify.className = 'label label-important';
|
||||
} else if(!usernamevalid) {
|
||||
username_notify.innerHTML = 'Invalid username';
|
||||
username_notify.className = 'label label-important';
|
||||
} else {
|
||||
socket.emit('user.exists', {username: username.value});
|
||||
}
|
||||
});
|
||||
$('#referrer').val(app.previousUrl);
|
||||
|
||||
$(emailEl).on('keyup change', function() {
|
||||
emailvalid = utils.isEmailValid(email.value);
|
||||
|
||||
if(!emailvalid) {
|
||||
email_notify.innerHTML = 'Invalid email address';
|
||||
email_notify.className = 'label label-important';
|
||||
}
|
||||
else
|
||||
socket.emit('user.email.exists', { email: emailEl.value });
|
||||
});
|
||||
|
||||
$(password).on('keyup', function() {
|
||||
passwordvalid = utils.isPasswordValid(password.value);
|
||||
if (password.value.length < 6) {
|
||||
password_notify.innerHTML = 'Password too short';
|
||||
password_notify.className = 'label label-important';
|
||||
} else if(!passwordvalid) {
|
||||
password_notify.innerHTML = 'Invalid password';
|
||||
password_notify.className = 'label label-important';
|
||||
} else {
|
||||
password_notify.innerHTML = 'OK!';
|
||||
password_notify.className = 'label label-success';
|
||||
}
|
||||
|
||||
if(password.value !== password_confirm.value) {
|
||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
||||
password_confirm_notify.className = 'label label-important';
|
||||
passwordsmatch = false;
|
||||
}
|
||||
});
|
||||
|
||||
$(password_confirm).on('keyup', function() {
|
||||
if(password.value !== password_confirm.value) {
|
||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
||||
password_confirm_notify.className = 'label label-important';
|
||||
passwordsmatch = false;
|
||||
}
|
||||
else {
|
||||
password_confirm_notify.innerHTML = 'OK!';
|
||||
password_confirm_notify.className = 'label label-success';
|
||||
passwordsmatch = true;
|
||||
}
|
||||
});
|
||||
|
||||
ajaxify.register_events(['user.exists', 'user.email.exists']);
|
||||
|
||||
socket.on('user.exists', function(data) {
|
||||
userexists = data.exists;
|
||||
if (data.exists === true) {
|
||||
username_notify.innerHTML = 'Username exists';
|
||||
username_notify.className = 'label label-important';
|
||||
} else {
|
||||
username_notify.innerHTML = 'OK!';
|
||||
username_notify.className = 'label label-success';
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('user.email.exists', function(data) {
|
||||
emailexists = data.exists;
|
||||
|
||||
if (data.exists === true) {
|
||||
email_notify.innerHTML = 'Email Address exists';
|
||||
email_notify.className = 'label label-important';
|
||||
}
|
||||
else {
|
||||
email_notify.innerHTML = 'OK!';
|
||||
email_notify.className = 'label label-success';
|
||||
}
|
||||
});
|
||||
|
||||
// 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');
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
var validated = true;
|
||||
|
||||
if (username.value.length < 2 || !usernamevalid) {
|
||||
username_notify.innerHTML = 'Invalid username';
|
||||
username_notify.className = 'label label-important';
|
||||
validated = false;
|
||||
function showError(element, msg) {
|
||||
element.html(msg);
|
||||
element.parent()
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger');
|
||||
element.show();
|
||||
validationError = true;
|
||||
}
|
||||
|
||||
if (password.value.length < 5) {
|
||||
password_notify.innerHTML = 'Password too short';
|
||||
validated = false;
|
||||
}
|
||||
|
||||
if(password.value !== password_confirm.value) {
|
||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
||||
function showSuccess(element, msg) {
|
||||
element.html(msg);
|
||||
element.parent()
|
||||
.removeClass('alert-danger')
|
||||
.addClass('alert-success');
|
||||
element.show();
|
||||
}
|
||||
|
||||
if (!emailvalid) {
|
||||
email_notify.innerHTML = 'Invalid email address';
|
||||
validated = false;
|
||||
}
|
||||
|
||||
if(emailexists) {
|
||||
email_notify.innerHTML = 'Email Address exists';
|
||||
validated = false;
|
||||
function validateEmail() {
|
||||
if (!emailEl.val()) {
|
||||
validationError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!utils.isEmailValid(emailEl.val())) {
|
||||
showError(email_notify, 'Invalid email address.');
|
||||
} else {
|
||||
socket.emit('user.email.exists', {
|
||||
email: emailEl.val()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(userexists || !passwordsmatch || !passwordvalid)
|
||||
validated = false;
|
||||
emailEl.on('blur', function() {
|
||||
validateEmail();
|
||||
});
|
||||
|
||||
return validated;
|
||||
}
|
||||
|
||||
register.addEventListener('click', function(e) {
|
||||
if (!validateForm()) e.preventDefault();
|
||||
}, false);
|
||||
|
||||
}());
|
||||
function validateUsername() {
|
||||
if (!username.val()) {
|
||||
validationError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (username.val().length < config.minimumUsernameLength) {
|
||||
showError(username_notify, 'Username too short!');
|
||||
} else if (username.val().length > config.maximumUsernameLength) {
|
||||
showError(username_notify, 'Username too long!');
|
||||
} else if (!utils.isUserNameValid(username.val()) || !utils.slugify(username.val())) {
|
||||
showError(username_notify, 'Invalid username!');
|
||||
} else {
|
||||
socket.emit('user.exists', {
|
||||
username: username.val()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
username.on('keyup', function() {
|
||||
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
|
||||
});
|
||||
username.on('blur', function() {
|
||||
validateUsername();
|
||||
});
|
||||
|
||||
function validatePassword() {
|
||||
if (!password.val()) {
|
||||
validationError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.val().length < config.minimumPasswordLength) {
|
||||
showError(password_notify, 'Password too short!');
|
||||
} else if (!utils.isPasswordValid(password.val())) {
|
||||
showError(password_notify, 'Invalid password!');
|
||||
} else {
|
||||
showSuccess(password_notify, successIcon);
|
||||
}
|
||||
|
||||
if (password.val() !== password_confirm.val() && password_confirm.val() !== '') {
|
||||
showError(password_confirm_notify, 'Passwords must match!');
|
||||
}
|
||||
}
|
||||
|
||||
$(password).on('blur', function() {
|
||||
validatePassword();
|
||||
});
|
||||
|
||||
function validatePasswordConfirm() {
|
||||
if (!password.val() || password_notify.hasClass('alert-error')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.val() !== password_confirm.val()) {
|
||||
showError(password_confirm_notify, 'Passwords must match!');
|
||||
} else {
|
||||
showSuccess(password_confirm_notify, successIcon);
|
||||
}
|
||||
}
|
||||
|
||||
$(password_confirm).on('blur', function() {
|
||||
validatePasswordConfirm();
|
||||
});
|
||||
|
||||
ajaxify.register_events(['user.exists', 'user.email.exists']);
|
||||
|
||||
socket.on('user.exists', function(data) {
|
||||
if (data.exists === true) {
|
||||
showError(username_notify, 'Username already taken!');
|
||||
} else {
|
||||
showSuccess(username_notify, successIcon);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('user.email.exists', function(data) {
|
||||
if (data.exists === true) {
|
||||
showError(email_notify, 'Email address already taken!');
|
||||
} else {
|
||||
showSuccess(email_notify, successIcon);
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm() {
|
||||
validationError = false;
|
||||
|
||||
validateEmail();
|
||||
validateUsername();
|
||||
validatePassword();
|
||||
validatePasswordConfirm();
|
||||
|
||||
return validationError;
|
||||
}
|
||||
|
||||
register.on('click', function(e) {
|
||||
if (validateForm()) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return Register;
|
||||
});
|
||||
@@ -1,39 +1,47 @@
|
||||
(function() {
|
||||
var inputEl = document.getElementById('email'),
|
||||
errorEl = document.getElementById('error'),
|
||||
errorTextEl = errorEl.querySelector('p');
|
||||
define(function() {
|
||||
var ResetPassword = {};
|
||||
|
||||
document.getElementById('reset').onclick = function() {
|
||||
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
|
||||
socket.emit('user:reset.send', { email: inputEl.value });
|
||||
} else {
|
||||
jQuery('#success').hide();
|
||||
jQuery(errorEl).show();
|
||||
errorTextEl.innerHTML = 'Please enter a valid email';
|
||||
}
|
||||
ResetPassword.init = function() {
|
||||
var inputEl = document.getElementById('email'),
|
||||
errorEl = document.getElementById('error'),
|
||||
errorTextEl = errorEl.querySelector('p');
|
||||
|
||||
document.getElementById('reset').onclick = function() {
|
||||
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
|
||||
socket.emit('user:reset.send', {
|
||||
email: inputEl.value
|
||||
});
|
||||
} else {
|
||||
jQuery('#success').hide();
|
||||
jQuery(errorEl).show();
|
||||
errorTextEl.innerHTML = 'Please enter a valid email';
|
||||
}
|
||||
};
|
||||
|
||||
ajaxify.register_events(['user.send_reset']);
|
||||
|
||||
socket.on('user.send_reset', function(data) {
|
||||
var submitEl = document.getElementById('reset');
|
||||
|
||||
if (data.status === 'ok') {
|
||||
jQuery('#error').hide();
|
||||
jQuery('#success').show();
|
||||
jQuery('#success p').html('An email has been dispatched to "' + data.email + '" with instructions on setting a new password.');
|
||||
inputEl.value = '';
|
||||
} else {
|
||||
jQuery('#success').hide();
|
||||
jQuery(errorEl).show();
|
||||
switch (data.message) {
|
||||
case 'invalid-email':
|
||||
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
|
||||
break;
|
||||
case 'send-failed':
|
||||
errorTextEl.innerHTML = 'There was a problem sending the reset code. Please try again later.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ajaxify.register_events(['user.send_reset']);
|
||||
|
||||
socket.on('user.send_reset', function(data) {
|
||||
var submitEl = document.getElementById('reset');
|
||||
|
||||
if (data.status === 'ok') {
|
||||
jQuery('#error').hide();
|
||||
jQuery('#success').show();
|
||||
jQuery('#success p').html('An email has been dispatched to "' + data.email + '" with instructions on setting a new password.');
|
||||
inputEl.value = '';
|
||||
} else {
|
||||
jQuery('#success').hide();
|
||||
jQuery(errorEl).show();
|
||||
switch(data.message) {
|
||||
case 'invalid-email':
|
||||
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
|
||||
break;
|
||||
case 'send-failed':
|
||||
errorTextEl.innerHTML = 'There was a problem sending the reset code. Please try again later.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
return ResetPassword;
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user