mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-16 21:40:23 +01:00
Compare commits
1703 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ab539b518 | ||
|
|
9078c2a536 | ||
|
|
fd20e4a400 | ||
|
|
1a64e40b21 | ||
|
|
cbfba4b45b | ||
|
|
f21a98f37f | ||
|
|
0edd6985ec | ||
|
|
98a646fa62 | ||
|
|
1d69436b44 | ||
|
|
d6c7551120 | ||
|
|
fb53e89023 | ||
|
|
d28beaa4dc | ||
|
|
ac06567617 | ||
|
|
d0a2c077ff | ||
|
|
ebf07626de | ||
|
|
9ef8bb4cdc | ||
|
|
bc8a53aadd | ||
|
|
03c4a1bc73 | ||
|
|
d93163896f | ||
|
|
08bdbc0bcc | ||
|
|
35d6a99775 | ||
|
|
e45e86fcc1 | ||
|
|
9589d340b9 | ||
|
|
91afbf106e | ||
|
|
aff11359ae | ||
|
|
aff8cef5f3 | ||
|
|
879855744d | ||
|
|
b5ab0c9097 | ||
|
|
2c398f81d2 | ||
|
|
520fcadd3f | ||
|
|
e8eb9f91b9 | ||
|
|
8bfb338eee | ||
|
|
bbb655abdd | ||
|
|
095e5527e3 | ||
|
|
4eb8c34855 | ||
|
|
e3185b9560 | ||
|
|
449adfae59 | ||
|
|
714e61b137 | ||
|
|
d0e4689907 | ||
|
|
1996e64c9b | ||
|
|
e2fb617cc0 | ||
|
|
fd88aff195 | ||
|
|
f7a1cca861 | ||
|
|
e3fb996a80 | ||
|
|
fe53037e53 | ||
|
|
438f90d859 | ||
|
|
742c8fb43c | ||
|
|
d43f3cebc6 | ||
|
|
9d452241ad | ||
|
|
c19a51e1b6 | ||
|
|
1b41a8f467 | ||
|
|
f933fc0167 | ||
|
|
8cfb239aac | ||
|
|
a974c6fa99 | ||
|
|
998f780fd2 | ||
|
|
b022d46d47 | ||
|
|
f7793e54b1 | ||
|
|
1e61033667 | ||
|
|
53caa5e422 | ||
|
|
40d20846d8 | ||
|
|
204913c63d | ||
|
|
6c30437c47 | ||
|
|
dd7fe47dfd | ||
|
|
50323c3d23 | ||
|
|
69e0aa338d | ||
|
|
6dcd06b63c | ||
|
|
42d77080f3 | ||
|
|
fbb4998999 | ||
|
|
14744a854f | ||
|
|
2c6afb4244 | ||
|
|
24907e456d | ||
|
|
2039885d96 | ||
|
|
daacdb50f3 | ||
|
|
21155b1b80 | ||
|
|
5d69167a64 | ||
|
|
5db27a835f | ||
|
|
c8e423e9cf | ||
|
|
be3465c5ca | ||
|
|
637e037e27 | ||
|
|
3e6bcd83cc | ||
|
|
dc4aeca427 | ||
|
|
9eb09f14cb | ||
|
|
a55fc364a0 | ||
|
|
2f90949560 | ||
|
|
a940219321 | ||
|
|
aaf6b11dc9 | ||
|
|
0f0913bfe5 | ||
|
|
5569337c40 | ||
|
|
ba2f47ead6 | ||
|
|
b52782deb8 | ||
|
|
2c6bf93eb5 | ||
|
|
4a11307b24 | ||
|
|
d8183c056c | ||
|
|
6ad28dadd4 | ||
|
|
2c489c600c | ||
|
|
abc782f5e6 | ||
|
|
a18e366493 | ||
|
|
12e95df068 | ||
|
|
a078f73e84 | ||
|
|
8f879cd3eb | ||
|
|
8385ceef79 | ||
|
|
83cc8f3ba8 | ||
|
|
cab6ab8e17 | ||
|
|
e9fbed71ae | ||
|
|
b4121f262d | ||
|
|
256a2fa9c6 | ||
|
|
0f362b7fac | ||
|
|
b504e2cd11 | ||
|
|
ea84fd70af | ||
|
|
09efb83ef3 | ||
|
|
b2aeb14094 | ||
|
|
0ed8fd6cbd | ||
|
|
2f1a3b9789 | ||
|
|
d068139d81 | ||
|
|
764e937c43 | ||
|
|
f72cf35348 | ||
|
|
fe1a75d1fd | ||
|
|
3dc9e2f4fa | ||
|
|
3bd8cf69a1 | ||
|
|
2c8725558e | ||
|
|
f68f02d346 | ||
|
|
8fd78199e2 | ||
|
|
1bde86a33f | ||
|
|
b6d4ae2732 | ||
|
|
680dbf138a | ||
|
|
3752a1c691 | ||
|
|
3a00c177d3 | ||
|
|
845e5e7986 | ||
|
|
57d2db36e6 | ||
|
|
8bfea656c4 | ||
|
|
ea2c03e28b | ||
|
|
f29b375ed4 | ||
|
|
07f1e0bcb5 | ||
|
|
0b94297c64 | ||
|
|
8655c2d2a6 | ||
|
|
da9c673ec4 | ||
|
|
1e6863ee19 | ||
|
|
00eb6b4efc | ||
|
|
002826d84f | ||
|
|
289e081e2e | ||
|
|
a717e9626e | ||
|
|
83f20c1cdb | ||
|
|
bc8adff70a | ||
|
|
c4623e2447 | ||
|
|
99fba3b83a | ||
|
|
2580caf864 | ||
|
|
f2d631e42d | ||
|
|
d86aefb518 | ||
|
|
3782ae1647 | ||
|
|
36e1a121ed | ||
|
|
2e52dd59ee | ||
|
|
d7a444d9ab | ||
|
|
f9e2b50826 | ||
|
|
32a32fcf5c | ||
|
|
9435acfa71 | ||
|
|
35ad3be969 | ||
|
|
9cb20c3886 | ||
|
|
a2c9867902 | ||
|
|
58a3f33200 | ||
|
|
25bac03bab | ||
|
|
770cea9329 | ||
|
|
30c11a8b42 | ||
|
|
27a01f6c61 | ||
|
|
bf27ade251 | ||
|
|
9d88b9eed3 | ||
|
|
04ea573caa | ||
|
|
d9eefd667c | ||
|
|
3ad98f3783 | ||
|
|
b89cf6f480 | ||
|
|
4397da144f | ||
|
|
cf8f0ca225 | ||
|
|
885242018f | ||
|
|
1abfe5de63 | ||
|
|
04dd1f9dac | ||
|
|
114294e24a | ||
|
|
dfa4cd4ae3 | ||
|
|
65d5a6cb81 | ||
|
|
64e87b761f | ||
|
|
1021615848 | ||
|
|
69c1ec97c9 | ||
|
|
45e7d64aeb | ||
|
|
b86a01ded1 | ||
|
|
e67af67180 | ||
|
|
9d03147f4e | ||
|
|
c313c4501b | ||
|
|
538356846d | ||
|
|
55d008d71f | ||
|
|
401a30e02c | ||
|
|
9816272b7b | ||
|
|
d72d2decd5 | ||
|
|
43c05d1d85 | ||
|
|
14f35a8c6b | ||
|
|
ffe1549cad | ||
|
|
3ca58a438d | ||
|
|
5da4cead67 | ||
|
|
0000a7f0b9 | ||
|
|
27ac24b1e3 | ||
|
|
95495926fc | ||
|
|
0f254c0b6c | ||
|
|
b27478876e | ||
|
|
a3734f2e15 | ||
|
|
1b843fba9c | ||
|
|
35f17db141 | ||
|
|
bcb364c4d4 | ||
|
|
6e16cb4b30 | ||
|
|
40e71299a1 | ||
|
|
0148cf06d0 | ||
|
|
ffa31ca0e7 | ||
|
|
ba3b8a21ae | ||
|
|
05209b01b9 | ||
|
|
4e0d0c2c20 | ||
|
|
225284073f | ||
|
|
ccef51095a | ||
|
|
cd77a1a457 | ||
|
|
6aeca98cd4 | ||
|
|
07a3b3f00b | ||
|
|
77e0cdcc3e | ||
|
|
e316dd3330 | ||
|
|
b511653e74 | ||
|
|
b5e37a6ce8 | ||
|
|
a34ed92fac | ||
|
|
4ff8509a0e | ||
|
|
e76936abfc | ||
|
|
9471fd8e46 | ||
|
|
2d4ceb8f9f | ||
|
|
4c40ee8e6e | ||
|
|
ddcf46fc73 | ||
|
|
7db234f958 | ||
|
|
f6f7959d28 | ||
|
|
7fa2f474fe | ||
|
|
d5e8044575 | ||
|
|
c0721e105f | ||
|
|
a475e38078 | ||
|
|
932b960aa9 | ||
|
|
24b12e23ea | ||
|
|
2a5d6e04fc | ||
|
|
4459d9d4e0 | ||
|
|
2be3158aff | ||
|
|
f1ad469861 | ||
|
|
0c05ee82b1 | ||
|
|
4f97275d24 | ||
|
|
4b9bfca767 | ||
|
|
202a4c4105 | ||
|
|
090bc2ad10 | ||
|
|
000c7efb1a | ||
|
|
90ad08a00d | ||
|
|
90e1e2436c | ||
|
|
21f5dad1d2 | ||
|
|
bc8bb352a8 | ||
|
|
274310e35a | ||
|
|
0bcc1642c7 | ||
|
|
d1d6605dcf | ||
|
|
da94d6214b | ||
|
|
67e49db797 | ||
|
|
de9100c489 | ||
|
|
4348e1efa4 | ||
|
|
6de3dba239 | ||
|
|
021cf9b8f6 | ||
|
|
ca087e6fa7 | ||
|
|
6c9e28232f | ||
|
|
ceac8e2dc9 | ||
|
|
98cf6eec71 | ||
|
|
5a00767370 | ||
|
|
4c90d22e43 | ||
|
|
e0e153eafb | ||
|
|
5c3c2623f2 | ||
|
|
34fc326a37 | ||
|
|
36745608bf | ||
|
|
090d35f306 | ||
|
|
347f5c132e | ||
|
|
d6f8162f17 | ||
|
|
b0b0f3640c | ||
|
|
4fd08332cc | ||
|
|
aaaffb823f | ||
|
|
76636b64db | ||
|
|
be6ed43223 | ||
|
|
9f2196abfb | ||
|
|
90a75ee045 | ||
|
|
2a21b4855e | ||
|
|
8f769d53a3 | ||
|
|
9ee250b597 | ||
|
|
074d7e7c8d | ||
|
|
870d48dc81 | ||
|
|
9ca10c25d4 | ||
|
|
8e2cc1c883 | ||
|
|
af09f4aca8 | ||
|
|
ab63ca6d92 | ||
|
|
400845ce6c | ||
|
|
351b07bb34 | ||
|
|
f861d44d55 | ||
|
|
2b7e4cbdf4 | ||
|
|
df10bde2db | ||
|
|
0da141e7bc | ||
|
|
6313a5eeb1 | ||
|
|
26de85c1de | ||
|
|
a54f464a13 | ||
|
|
bfbc596348 | ||
|
|
7508bd216e | ||
|
|
8cfc5dda37 | ||
|
|
b81737bc0f | ||
|
|
1c23be8911 | ||
|
|
5f86e31d1e | ||
|
|
746119bd45 | ||
|
|
385aa6df92 | ||
|
|
097810a057 | ||
|
|
3a7fcc2d3d | ||
|
|
95bb838699 | ||
|
|
81055523a0 | ||
|
|
e9fbab0f26 | ||
|
|
53ca7a1143 | ||
|
|
6c70d37f1c | ||
|
|
447073560f | ||
|
|
2c131f172a | ||
|
|
1564e3d530 | ||
|
|
3d9a732c4a | ||
|
|
4819bea378 | ||
|
|
030ce95dea | ||
|
|
2a1671ba9b | ||
|
|
a65c79cb02 | ||
|
|
dcbe4ffd4a | ||
|
|
215b919362 | ||
|
|
58df656c65 | ||
|
|
a8c91e2452 | ||
|
|
806a454b05 | ||
|
|
705754e823 | ||
|
|
fe527ff2a9 | ||
|
|
041e77f688 | ||
|
|
b927f6ce29 | ||
|
|
519d376071 | ||
|
|
d9ee9bf5e3 | ||
|
|
67d5ea83e7 | ||
|
|
7875138c08 | ||
|
|
43b012b32e | ||
|
|
c096656eff | ||
|
|
2dd295118c | ||
|
|
567997ef3c | ||
|
|
c698af17ae | ||
|
|
39b70a9e09 | ||
|
|
9b557cafd8 | ||
|
|
fe4aee177d | ||
|
|
7c4347736c | ||
|
|
16e07d475f | ||
|
|
2125bb2223 | ||
|
|
72a3ab1d6c | ||
|
|
639247a8b0 | ||
|
|
f0caac242c | ||
|
|
e066fbf36a | ||
|
|
b215dbde19 | ||
|
|
1325e4c501 | ||
|
|
2e2938616d | ||
|
|
53a7eab3e8 | ||
|
|
6bd4a34e69 | ||
|
|
d27f2eb214 | ||
|
|
b547d3577b | ||
|
|
4b5988c269 | ||
|
|
cfd3a7d126 | ||
|
|
0471a192ab | ||
|
|
5c6a7d4b94 | ||
|
|
ca01fb9f7d | ||
|
|
b176629b44 | ||
|
|
113cb85c46 | ||
|
|
5b6f5ebf9d | ||
|
|
21bbe68c97 | ||
|
|
28c75e09a9 | ||
|
|
69f453c73c | ||
|
|
dab0435d9b | ||
|
|
b5770be71f | ||
|
|
bf3822e8a5 | ||
|
|
cb6c42ea44 | ||
|
|
3dc3769088 | ||
|
|
3d18c4015a | ||
|
|
610d45bb32 | ||
|
|
66bc4184d8 | ||
|
|
b024d10185 | ||
|
|
e847c015a5 | ||
|
|
10474f8e2a | ||
|
|
8a99eef4fb | ||
|
|
da66efe7a5 | ||
|
|
1bd94b4e41 | ||
|
|
e862a1c4cc | ||
|
|
8b55920acf | ||
|
|
32df811765 | ||
|
|
91d6f83de4 | ||
|
|
7c8f857aaf | ||
|
|
1f970c3bdb | ||
|
|
700cab686b | ||
|
|
af06e0335a | ||
|
|
4a8dc82bd2 | ||
|
|
8a4e2b1ea0 | ||
|
|
1f52717f1e | ||
|
|
304285e874 | ||
|
|
d4eddc6e2c | ||
|
|
6d79521922 | ||
|
|
95db5f93cb | ||
|
|
b900bc9cce | ||
|
|
fc066c21bf | ||
|
|
32d5118266 | ||
|
|
3775c8e50a | ||
|
|
99fbc0dfd5 | ||
|
|
e32d230974 | ||
|
|
c9308efbec | ||
|
|
636551d2e9 | ||
|
|
347d6c2768 | ||
|
|
4f654fb489 | ||
|
|
80e7fd93c6 | ||
|
|
95efb2ae5e | ||
|
|
8d3a647d16 | ||
|
|
53afe6cb68 | ||
|
|
391b8098a3 | ||
|
|
190948336a | ||
|
|
fcda27e251 | ||
|
|
a48a07603c | ||
|
|
d930e2a1be | ||
|
|
7e2166903f | ||
|
|
d5c0ca4a9d | ||
|
|
7695e76494 | ||
|
|
78af47362c | ||
|
|
18a890ed51 | ||
|
|
5f731dd1f6 | ||
|
|
51990142d5 | ||
|
|
b840169a8c | ||
|
|
94fdeb2378 | ||
|
|
68e7ee7f07 | ||
|
|
77d5ecc82a | ||
|
|
437379413e | ||
|
|
ddb7896df1 | ||
|
|
66cdb9a067 | ||
|
|
f5741fd48b | ||
|
|
f405dec4e9 | ||
|
|
cc242ca667 | ||
|
|
2733198f9e | ||
|
|
52700fbe16 | ||
|
|
0f53749e70 | ||
|
|
1aa1ddb4ec | ||
|
|
71125fd1e2 | ||
|
|
5621fb8622 | ||
|
|
b9f1176ec1 | ||
|
|
b3b4d3c37d | ||
|
|
cdbca7d262 | ||
|
|
140f90f7f3 | ||
|
|
a905c6a084 | ||
|
|
bfe081f672 | ||
|
|
46a14715e3 | ||
|
|
c1da56ce45 | ||
|
|
ee63fae803 | ||
|
|
720711756f | ||
|
|
90a12c3253 | ||
|
|
6a00ab3782 | ||
|
|
9ccfa3f18c | ||
|
|
1660d75205 | ||
|
|
f6d57a241d | ||
|
|
bcfb4ca0e4 | ||
|
|
0159a43a20 | ||
|
|
86b019ec89 | ||
|
|
98a12cd1e1 | ||
|
|
e6452cbd4d | ||
|
|
cd44ead595 | ||
|
|
652fda1a6f | ||
|
|
30a7f1a816 | ||
|
|
6ca3d0c4af | ||
|
|
b2074c6dda | ||
|
|
d7c0e1c62e | ||
|
|
56ef05a0bf | ||
|
|
dd36cce329 | ||
|
|
2b2799dae9 | ||
|
|
293c176053 | ||
|
|
3cef5fce2b | ||
|
|
7d0f160c4c | ||
|
|
c5f9f896b2 | ||
|
|
db98b3db55 | ||
|
|
dba47e4bef | ||
|
|
2a46ead29f | ||
|
|
707179edf3 | ||
|
|
53164e96ab | ||
|
|
9702e28a07 | ||
|
|
fa56eca962 | ||
|
|
684839f04a | ||
|
|
0188ea9a3b | ||
|
|
85aa587749 | ||
|
|
48e36e3c31 | ||
|
|
0b6d018f8d | ||
|
|
f2bf65252d | ||
|
|
4335f8c5c6 | ||
|
|
ae82f57c67 | ||
|
|
168052bf45 | ||
|
|
a87ebb64d8 | ||
|
|
38da65ee58 | ||
|
|
e3e1a556cd | ||
|
|
56b618c915 | ||
|
|
7198110b57 | ||
|
|
b7aea63c53 | ||
|
|
78b65c0b12 | ||
|
|
0742590c0c | ||
|
|
c16f04bbcf | ||
|
|
51b38c4c55 | ||
|
|
79eddc9b06 | ||
|
|
21f63ac17f | ||
|
|
fdf5227c35 | ||
|
|
98f03a723e | ||
|
|
69427fa10e | ||
|
|
670986f7ef | ||
|
|
8b62041d28 | ||
|
|
89c5d01efa | ||
|
|
0a06f1ac7d | ||
|
|
df2e9b4b47 | ||
|
|
aed4e2792d | ||
|
|
c860df7975 | ||
|
|
2148f6ff95 | ||
|
|
2d05a06e37 | ||
|
|
e3da005780 | ||
|
|
f0e8633dcc | ||
|
|
590208f0c7 | ||
|
|
7d7ead3f47 | ||
|
|
974629ce85 | ||
|
|
72ef8c839f | ||
|
|
5ee5c8179a | ||
|
|
46d6d7637e | ||
|
|
62e2aa67d7 | ||
|
|
182659d0e1 | ||
|
|
4855131652 | ||
|
|
4d2469b4ce | ||
|
|
4e2326fc84 | ||
|
|
3a8dca6fb9 | ||
|
|
31635b92f3 | ||
|
|
a0c3de0273 | ||
|
|
32b191fa62 | ||
|
|
f616125d02 | ||
|
|
e1f6e064a9 | ||
|
|
633be7ff3c | ||
|
|
6b3863bfbf | ||
|
|
b66ca703b8 | ||
|
|
48a7f9058f | ||
|
|
8f80733563 | ||
|
|
aa1451cfbc | ||
|
|
13ef28118d | ||
|
|
34459e7cf1 | ||
|
|
798e17a954 | ||
|
|
5ad80218a2 | ||
|
|
e90e54cec1 | ||
|
|
bca1fde69c | ||
|
|
d70c688b65 | ||
|
|
541993c80a | ||
|
|
529c8acf6c | ||
|
|
e98d05b1a5 | ||
|
|
0afc7c9761 | ||
|
|
e5c1edd5f5 | ||
|
|
a5e78aab08 | ||
|
|
cec69c2be0 | ||
|
|
bc8815cb94 | ||
|
|
efac6272bb | ||
|
|
bdb30976b5 | ||
|
|
1d4ae8fe4d | ||
|
|
abdb4c34ef | ||
|
|
08d130893c | ||
|
|
b2fb9aa99f | ||
|
|
561ee9e4f1 | ||
|
|
3f70d45f3d | ||
|
|
c07783fa2c | ||
|
|
d4d0e8cd9b | ||
|
|
4be5ac2c23 | ||
|
|
070c95d8de | ||
|
|
8d12ecb758 | ||
|
|
81560c4698 | ||
|
|
390937a20b | ||
|
|
2a8a38b742 | ||
|
|
5a5c3c8c60 | ||
|
|
905e451455 | ||
|
|
69b8b47b15 | ||
|
|
b16e1a0113 | ||
|
|
0b39968a9c | ||
|
|
d8b3abb611 | ||
|
|
7fb0a616a1 | ||
|
|
d987e51a8b | ||
|
|
0f7f6cd0a3 | ||
|
|
0e8b33aa79 | ||
|
|
353b3047cd | ||
|
|
377de06eeb | ||
|
|
4013e27a8b | ||
|
|
181c6eb2e6 | ||
|
|
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 | ||
|
|
d4d4c3cc92 | ||
|
|
33a69abece | ||
|
|
3a12ba177a | ||
|
|
6a4947533f | ||
|
|
28e1538fdb | ||
|
|
879a31f51e | ||
|
|
eed66c099b | ||
|
|
49fc87e295 | ||
|
|
ece2edf579 | ||
|
|
1961f01cab | ||
|
|
fe89f1f096 | ||
|
|
346681ba27 | ||
|
|
4a214b6ef0 | ||
|
|
dda429ab5d | ||
|
|
15feaafd68 | ||
|
|
14e7907e06 | ||
|
|
b4b483b35a | ||
|
|
79c9bdba7f | ||
|
|
a6837a7869 | ||
|
|
0a485a7ff6 | ||
|
|
bca1602474 | ||
|
|
96ee0a2017 | ||
|
|
25550e18d0 | ||
|
|
154d0160bc | ||
|
|
aefa56221b | ||
|
|
dd40cbc139 | ||
|
|
23db2e5c9e | ||
|
|
eff1b174c0 | ||
|
|
545069b069 | ||
|
|
13e13cd5a8 | ||
|
|
f767535ce5 | ||
|
|
aeebd069e2 | ||
|
|
0f8aad52b2 | ||
|
|
b6a5cbf956 | ||
|
|
d2aa2a9a29 | ||
|
|
a482d4db5f | ||
|
|
d7eb30ccbd | ||
|
|
9bc12f28b4 | ||
|
|
4d11fba20a | ||
|
|
df15dceaef | ||
|
|
cb6f587f24 | ||
|
|
9f2e192993 | ||
|
|
c647793512 | ||
|
|
d62f36c6a0 | ||
|
|
2427724868 | ||
|
|
9b35d8f8e1 | ||
|
|
a859f4524c | ||
|
|
8be896aebb | ||
|
|
a008cf971d | ||
|
|
caa057ff4d | ||
|
|
43152bdaf9 | ||
|
|
4cdb7ff32b | ||
|
|
7cbb01a78a | ||
|
|
555eddff83 | ||
|
|
a3cab53b73 | ||
|
|
454d5827fd | ||
|
|
186c426691 | ||
|
|
5e1e1ecf6f | ||
|
|
2d3d0f688a | ||
|
|
7975844e4d | ||
|
|
f2b138510e | ||
|
|
1c95ef4060 | ||
|
|
b43e12a42a | ||
|
|
316077fffb | ||
|
|
4373037071 | ||
|
|
24e81c873c | ||
|
|
9e4a3905a0 | ||
|
|
b54b4a6580 | ||
|
|
f33a9c3941 | ||
|
|
d792798963 | ||
|
|
e5af4f6299 | ||
|
|
ef5bd9dc61 | ||
|
|
8834feac65 | ||
|
|
2f70dd732d | ||
|
|
3f793ae902 | ||
|
|
ac56f3a30a | ||
|
|
e2ffac74bc | ||
|
|
1c08ca54c5 | ||
|
|
f1547a7b1f | ||
|
|
746fa93c80 | ||
|
|
5ab1758d28 | ||
|
|
2e4e1df3d9 | ||
|
|
eded61d66e | ||
|
|
d9360da9a5 | ||
|
|
2b7a1b7515 | ||
|
|
1e66116e1d | ||
|
|
a95582b382 | ||
|
|
7860cfdec3 | ||
|
|
30bbea9c74 | ||
|
|
481105d6be | ||
|
|
f939a632a6 | ||
|
|
c05f56d28c | ||
|
|
b844251587 | ||
|
|
b9bd907a6b | ||
|
|
17d86a2a35 | ||
|
|
c70c67394a | ||
|
|
92d3559146 | ||
|
|
0e9a3c3a9f | ||
|
|
41263f0332 | ||
|
|
3747427538 | ||
|
|
b65554ca15 | ||
|
|
00cb15d3c8 | ||
|
|
6690f49c4e | ||
|
|
ff805a704d | ||
|
|
f83be710a0 | ||
|
|
3933549659 | ||
|
|
4993b74c23 | ||
|
|
76e7a98c88 | ||
|
|
999e98e43d | ||
|
|
74af205426 | ||
|
|
9ad82f4907 | ||
|
|
2e6b37e018 | ||
|
|
67070e335e | ||
|
|
22536e694c | ||
|
|
929282a2f7 | ||
|
|
b0092b68c6 | ||
|
|
91446378bd | ||
|
|
dceec0ce46 | ||
|
|
1856e394f3 | ||
|
|
8dc7a0dbbf | ||
|
|
6e17ff7981 | ||
|
|
1d81f43249 | ||
|
|
645d0f60e4 | ||
|
|
e1d7fed1b6 | ||
|
|
deff75ad06 | ||
|
|
85fb03c0f5 | ||
|
|
74445c3d30 | ||
|
|
ca3629d89b | ||
|
|
16a95dd408 | ||
|
|
b96084fb16 | ||
|
|
c3c5f5ab92 | ||
|
|
0fef0aa582 | ||
|
|
1894d0a469 | ||
|
|
259ba9b9b5 | ||
|
|
46afbc0ba0 | ||
|
|
dd3b01dfed | ||
|
|
48bb1b06c2 | ||
|
|
9fb63d45c1 | ||
|
|
ded0200355 | ||
|
|
64b166ca8c | ||
|
|
33994ed638 | ||
|
|
4457228903 | ||
|
|
f4573d23b5 | ||
|
|
e8f1d645fe | ||
|
|
149e8ac78e | ||
|
|
24b951ab5b | ||
|
|
04d94a7462 | ||
|
|
9bf8739841 | ||
|
|
26944ae686 | ||
|
|
dd6c9e03cb | ||
|
|
45c10d75f3 | ||
|
|
272806a25d | ||
|
|
27f874759e | ||
|
|
e1d6b77eb1 | ||
|
|
0a7d41dafa | ||
|
|
644fb375db | ||
|
|
81f94c56e0 | ||
|
|
50c34e4f33 | ||
|
|
cbd34a4411 | ||
|
|
244801a0bf | ||
|
|
1cc8214d16 | ||
|
|
04e0d075ec | ||
|
|
917468d676 | ||
|
|
1afc4f39a8 | ||
|
|
02e707c3b5 | ||
|
|
34ce17e522 | ||
|
|
a100eb1bb2 | ||
|
|
b6281f020b | ||
|
|
78c1139ad9 | ||
|
|
08a45e40a2 | ||
|
|
e979d1bf0d | ||
|
|
e69928d624 | ||
|
|
8bc60be7c3 | ||
|
|
99ac782875 | ||
|
|
c1c9d24ee5 | ||
|
|
e2d0ca9669 | ||
|
|
661596e4cc | ||
|
|
ac3fe1fc6f | ||
|
|
0bd56196cf | ||
|
|
7251af56e3 | ||
|
|
984ac21e52 | ||
|
|
cb1258da9c | ||
|
|
f0759863e6 | ||
|
|
0561710016 | ||
|
|
8423684dee | ||
|
|
6ff0c55dae | ||
|
|
d6b9a2799b | ||
|
|
797d05a84a | ||
|
|
a5acf31fc6 | ||
|
|
23fcdde25e | ||
|
|
7297a26685 | ||
|
|
720dd9e960 | ||
|
|
dbfd3c19a1 | ||
|
|
f20b7b5113 | ||
|
|
9f2838849e | ||
|
|
59381ee1d3 | ||
|
|
6fbecd00b0 | ||
|
|
a0a1b14e2e | ||
|
|
f4fdabd3ca | ||
|
|
3f6f4e347d | ||
|
|
235553eaf6 | ||
|
|
1bee527f41 | ||
|
|
3578ce1925 | ||
|
|
c2d7bf87e9 | ||
|
|
777173d9f4 | ||
|
|
0a3a970b52 | ||
|
|
b46d81e3e4 | ||
|
|
3273c0558b | ||
|
|
6b2be772e7 | ||
|
|
78f462e1e6 | ||
|
|
871591b92d | ||
|
|
811d2df728 | ||
|
|
307f6f34b9 | ||
|
|
2d64c9979e | ||
|
|
34bb9dddb5 | ||
|
|
25a1d25108 | ||
|
|
ec4ab19a1e | ||
|
|
2e83ad448d | ||
|
|
b35ecd08ea | ||
|
|
d32b130d40 | ||
|
|
cca83b9c5c | ||
|
|
57a4741e9e | ||
|
|
23598361b8 | ||
|
|
3f8b3894d8 | ||
|
|
557c6effdd | ||
|
|
916b46618c | ||
|
|
2647666de6 | ||
|
|
8cc3859e72 |
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*.js, *.css, *.tpl]
|
||||
indent_style = tab
|
||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,13 +1,22 @@
|
||||
#################
|
||||
## 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
|
||||
.project
|
||||
.idea
|
||||
*.swp
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
provision.sh
|
||||
*.komodoproject
|
||||
|
||||
feeds/recent.rss
|
||||
|
||||
# winston?
|
||||
error.log
|
||||
events.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
|
||||
}
|
||||
12
.project
12
.project
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>node-forum</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.aptana.projects.webnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
27
README.md
27
README.md
@@ -1,23 +1,30 @@
|
||||
Please support NodeBB development! Check out our IndieGoGo campaign and like, share, and follow us :)
|
||||
[NodeBB Homepage](http://www.nodebb.org/ "NodeBB") # [IndieGoGo campaign](https://www.indiegogo.com/projects/nodebb-the-discussion-platform-of-the-future/ "IndieGoGo") # [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?
|
||||
|
||||
* Our [Indiegogo campaign](https://www.indiegogo.com/projects/nodebb-the-discussion-platform-of-the-future/) is accepting contributions until August 17th, 2013
|
||||
* Our feature roadmap is hosted on the project wiki's [Version History / Roadmap](https://github.com/designcreateplay/NodeBB/wiki/Version-History-%26-Roadmap)
|
||||
* If you are a developer, feel free to check out the source and submit pull requests.
|
||||
* If you are a designer, NodeBB needs themes! NodeBB will accept any LESS or CSS file and use it in place of the default Twitter Bootstrap theme. Consider extending Bootstrap themes by extending the base bootstrap LESS file.
|
||||
|
||||
## 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
|
||||
|
||||
@@ -25,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
|
||||
@@ -55,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)
|
||||
|
||||
232
app.js
232
app.js
@@ -16,120 +16,166 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Read config.js to grab redis info
|
||||
var fs = require('fs'),
|
||||
nconf = require('nconf'),
|
||||
pkg = require('./package.json'),
|
||||
url = require('url');
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Runtime environment
|
||||
global.env = process.env.NODE_ENV || 'production',
|
||||
// Configuration setup
|
||||
var nconf = require('nconf');
|
||||
nconf.argv().env();
|
||||
|
||||
// Configuration setup
|
||||
nconf.argv().file({ file: __dirname + '/config.json'});
|
||||
var fs = require('fs'),
|
||||
async = require('async'),
|
||||
semver = require('semver'),
|
||||
winston = require('winston'),
|
||||
path = require('path'),
|
||||
pkg = require('./package.json'),
|
||||
utils = require('./public/src/utils.js'),
|
||||
meta;
|
||||
|
||||
// Log GNU copyright info along with server info
|
||||
console.log('Info: NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
||||
console.log('Info: This program comes with ABSOLUTELY NO WARRANTY.');
|
||||
console.log('Info: This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
console.log('Info: ===');
|
||||
// Runtime environment
|
||||
global.env = process.env.NODE_ENV || 'production';
|
||||
|
||||
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/');
|
||||
global.nconf = nconf;
|
||||
winston.remove(winston.transports.Console);
|
||||
winston.add(winston.transports.Console, {
|
||||
colorize: true
|
||||
});
|
||||
|
||||
console.log('Info: Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
console.log('Info: Base Configuration OK.');
|
||||
winston.add(winston.transports.File, {
|
||||
filename: 'error.log',
|
||||
level: 'error'
|
||||
});
|
||||
|
||||
// TODO: Replace this with nconf-redis
|
||||
var meta = require('./src/meta.js');
|
||||
global.config = {};
|
||||
meta.config.get(function(config) {
|
||||
for(c in config) {
|
||||
if (config.hasOwnProperty(c)) {
|
||||
global.config[c] = config[c];
|
||||
}
|
||||
// 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') + path.sep);
|
||||
nconf.set('upload_url', path.join(path.sep, nconf.get('relative_path'), 'uploads', path.sep));
|
||||
nconf.set('base_dir', __dirname);
|
||||
|
||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
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'),
|
||||
RDB = require('./src/redis.js'),
|
||||
templates = require('./public/src/templates.js'),
|
||||
webserver = require('./src/webserver.js'),
|
||||
websockets = require('./src/websockets.js'),
|
||||
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', 'install/header', 'install/footer', 'install/redis',
|
||||
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() {
|
||||
console.log('Info: Checking categories...');
|
||||
categories.getAllCategories(function(data) {
|
||||
if (data.categories.length === 0) {
|
||||
console.log('Info: Setting up default categories...');
|
||||
|
||||
fs.readFile(config.ROOT_DIRECTORY + '/install/data/categories.json', function(err, default_categories) {
|
||||
default_categories = JSON.parse(default_categories);
|
||||
|
||||
for (var category in default_categories) {
|
||||
admin.categories.create(default_categories[category]);
|
||||
}
|
||||
utils.walk(path.join(__dirname, 'public/templates'), function (err, tplsToLoad) {
|
||||
templates.init(tplsToLoad, customTemplates);
|
||||
});
|
||||
|
||||
|
||||
console.log('Info: Hardcoding uid 1 as an admin');
|
||||
var user = require('./src/user.js');
|
||||
user.makeAdministrator(1);
|
||||
plugins.ready(function() {
|
||||
templates.ready(webserver.init);
|
||||
});
|
||||
|
||||
notifications.init();
|
||||
} else {
|
||||
console.log('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')) console.log('Info: NodeBB Setup Triggered via Command Line');
|
||||
else console.log('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) {
|
||||
console.log('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));
|
||||
56
nodebb
56
nodebb
@@ -1,4 +1,54 @@
|
||||
#!/bin/bash
|
||||
clear
|
||||
echo "Launching NodeBB in \"development\" mode"
|
||||
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
|
||||
|
||||
58
package.json
58
package.json
@@ -2,21 +2,22 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.4",
|
||||
"version": "0.2.1",
|
||||
"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,14 +26,36 @@
|
||||
"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"
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2",
|
||||
"rss": "~0.2.0",
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0",
|
||||
"validator": "~1.5.1",
|
||||
"nodebb-plugin-mentions": "~0.1",
|
||||
"nodebb-plugin-markdown": "~0.3",
|
||||
"nodebb-theme-vanilla": "~0.0.12",
|
||||
"nodebb-theme-cerulean": "0.0.10",
|
||||
"cron": "~1.0.1",
|
||||
"semver": "~2.2.1",
|
||||
"string": "~1.7.0",
|
||||
"xregexp": "~2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"redis": "0.8.3",
|
||||
"mongodb": "~1.3.19",
|
||||
"connect-redis": "1.4.5",
|
||||
"connect-mongo": "0.4.0",
|
||||
"hiredis": "~0.1.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.13.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
@@ -43,15 +66,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",
|
||||
@@ -60,6 +90,10 @@
|
||||
{
|
||||
"name": "Matt Smith",
|
||||
"url": "https://github.com/soimafreak"
|
||||
},
|
||||
{
|
||||
"name": "Quinton Marchi",
|
||||
"url": "https://github.com/iamcardinal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
@import "mixins";
|
||||
|
||||
.admin {
|
||||
.entry-row {
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
cursor: move;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
.entry-row {
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
cursor: move;
|
||||
width: 695px;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,821 +0,0 @@
|
||||
@import "mixins";
|
||||
|
||||
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: 10%;
|
||||
}
|
||||
|
||||
#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-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;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.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;
|
||||
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:200px;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
|
||||
&.active {
|
||||
color: #558;
|
||||
text-shadow: 0 0 1em #aaf, 0 0 1em #aaf, 0 0 1em #aaf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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 {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
|
||||
span {
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
width: 98%;
|
||||
text-align: center;
|
||||
border: none;
|
||||
padding: 0.5em 0;
|
||||
-webkit-border-radius: 0px;
|
||||
-moz-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
margin: 1% 1% 2% 1%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background: rgba(64, 64, 64, 0.95);
|
||||
border: none;
|
||||
padding: 0.5em;
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0.5em auto;
|
||||
resize: none;
|
||||
color: white;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#imagedrop {
|
||||
text-align:center;
|
||||
color:white;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height:230px;
|
||||
line-height:230px;
|
||||
font-size:20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#imagelist {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 0px;
|
||||
padding-left:2em;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@-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: */
|
||||
}
|
||||
@@ -1,177 +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;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-block, .post-block {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
.main-post {
|
||||
h3 {
|
||||
margin: 0;
|
||||
|
||||
.topic-title {
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
text-overflow:ellipsis;
|
||||
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!"
|
||||
}
|
||||
43
public/language/en/topic.json
Normal file
43
public/language/en/topic.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"topic": "Topic",
|
||||
"topics": "Topics",
|
||||
|
||||
"no_topics_found": "No topics found!",
|
||||
|
||||
"profile": "Profile",
|
||||
"posted_by": "Posted by",
|
||||
"chat": "Chat",
|
||||
"notify_me": "Be notified of new replies in this topic",
|
||||
"quote": "Quote",
|
||||
"reply": "Reply",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"fork": "Fork",
|
||||
"banned": "banned",
|
||||
"link": "Link",
|
||||
|
||||
"thread_tools.title": "Thread Tools",
|
||||
"thread_tools.pin": "Pin Thread",
|
||||
"thread_tools.lock": "Lock Thread",
|
||||
"thread_tools.move": "Move Thread",
|
||||
"thread_tools.delete": "Delete Thread",
|
||||
|
||||
"load_categories": "Loading Categories",
|
||||
"disabled_categories_note": "Disabled Categories are greyed out",
|
||||
"confirm_move": "Move",
|
||||
|
||||
"favourite": "Favourite",
|
||||
"favourites": "Favorites",
|
||||
"favourites.not_logged_in.title": "Not Logged In",
|
||||
"favourites.not_logged_in.message": "Please log in in order to favourite this post",
|
||||
"favourites.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"
|
||||
}
|
||||
40
public/language/en/user.json
Normal file
40
public/language/en/user.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"banned": "Banned",
|
||||
"offline": "Offline",
|
||||
"email": "Email",
|
||||
"fullname": "Full Name",
|
||||
"website": "Website",
|
||||
"location": "Location",
|
||||
"age": "Age",
|
||||
"joined": "Joined",
|
||||
"lastonline": "Last Online",
|
||||
"profile_views": "Profile views",
|
||||
"reputation": "Reputation",
|
||||
"posts": "Posts",
|
||||
"followers": "Followers",
|
||||
"following": "Following",
|
||||
"signature": "Signature",
|
||||
"gravatar": "Gravatar",
|
||||
"birthday": "Birthday",
|
||||
|
||||
"change_picture": "Change Picture",
|
||||
"edit": "Edit",
|
||||
"uploaded_picture": "Uploaded Picture",
|
||||
"upload_new_picture": "Upload New Picture",
|
||||
"change_password": "Change Password",
|
||||
"confirm_password": "Confirm Password",
|
||||
"password": "Password",
|
||||
|
||||
"upload_picture": "Upload picture",
|
||||
"upload_a_picture": "Upload a picture",
|
||||
"image_spec": "You may only upload PNG, JPG, or GIF files under 256kb.",
|
||||
|
||||
"settings": "settings",
|
||||
"show_email": "Show My Email",
|
||||
|
||||
"has_no_follower": "This user doesn't have any followers :(",
|
||||
"follows_no_one": "This user isn't following anyone :(",
|
||||
|
||||
"email_hidden": "Email Hidden",
|
||||
"hidden": "hidden"
|
||||
}
|
||||
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,8 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
var ajaxify = {};
|
||||
|
||||
(function ($) {
|
||||
/*global app, templates, utils*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var location = document.location || window.location,
|
||||
rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : ''),
|
||||
content = null;
|
||||
@@ -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,101 +22,185 @@ 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) {
|
||||
// leave room and join global
|
||||
app.enter_room('global');
|
||||
app.showLoginMessage();
|
||||
var pagination, paginator_bar;
|
||||
|
||||
var url = url.replace(/\/$/, "");
|
||||
ajaxify.currentPage = null;
|
||||
|
||||
if(url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
|
||||
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) {
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
} else if (templates[url]) {
|
||||
tpl_url = url;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
jQuery('#content, #footer').stop(true, true).fadeIn(200);
|
||||
}, url, template);
|
||||
|
||||
app.processPage();
|
||||
|
||||
jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying');
|
||||
|
||||
if (window.location.hash) {
|
||||
hash = window.location.hash;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (this.href == window.location.href + "#") return;
|
||||
var url = this.href.replace(rootUrl +'/', '');
|
||||
|
||||
if (this.target !== '') return;
|
||||
$(document.body).on('click', 'a', function (e) {
|
||||
function hrefEmpty(href) {
|
||||
return href === 'javascript:;' || href === window.location.href + "#" || href.slice(-1) === "#";
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && e.which === 1) {
|
||||
if (ajaxify.go(url)) {
|
||||
e.preventDefault();
|
||||
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!window.location.pathname.match(/\/(403|404)$/g)) {
|
||||
app.previousUrl = window.location.href;
|
||||
}
|
||||
|
||||
if (this.getAttribute('data-ajaxify') === 'false') {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -124,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);
|
||||
}
|
||||
}
|
||||
@@ -147,6 +233,6 @@ var ajaxify = {};
|
||||
}
|
||||
evalScript(scripts[i]);
|
||||
}
|
||||
};
|
||||
|
||||
}(jQuery));
|
||||
}
|
||||
|
||||
}(jQuery));
|
||||
|
||||
@@ -1,245 +1,305 @@
|
||||
var socket,
|
||||
config,
|
||||
app = {},
|
||||
API_URL = null;
|
||||
app = {
|
||||
"username": null,
|
||||
"uid": null,
|
||||
"isFocused": true,
|
||||
"currentRoom": null
|
||||
};
|
||||
|
||||
(function () {
|
||||
var showWelcomeMessage = false;
|
||||
|
||||
(function() {
|
||||
|
||||
function loadConfig() {
|
||||
|
||||
app.loadConfig = function() {
|
||||
$.ajax({
|
||||
url: RELATIVE_PATH + '/config.json?v=' + new Date().getTime(),
|
||||
success: function(data) {
|
||||
API_URL = data.api_url;
|
||||
|
||||
url: RELATIVE_PATH + '/api/config',
|
||||
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;
|
||||
});
|
||||
|
||||
socket.on('event:alert', function(data) {
|
||||
app.alert(data);
|
||||
});
|
||||
|
||||
socket.on('event:consolelog', function(data) {
|
||||
console.log(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 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="icon-circle"></i>');
|
||||
} else {
|
||||
el.find('i').remove();
|
||||
el.prepend('<i class="icon-circle-blank"></i>');
|
||||
|
||||
var reconnecting = false,
|
||||
reconnectEl, reconnectTimer;
|
||||
|
||||
socket.on('event:connect', function (data) {
|
||||
app.username = data.username;
|
||||
app.uid = data.uid;
|
||||
|
||||
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;
|
||||
});
|
||||
});
|
||||
|
||||
app.enter_room('global');
|
||||
|
||||
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
});
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
// takes a string like 1000 and returns 1,000
|
||||
app.addCommas = function(text) {
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||
}
|
||||
};
|
||||
|
||||
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
|
||||
app.strip_tags = function(input, allowed) {
|
||||
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
||||
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
||||
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
||||
|
||||
return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
|
||||
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
||||
app.logout = function() {
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: $('#csrf_token').val()
|
||||
}, function() {
|
||||
window.location.href = RELATIVE_PATH + '/';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// use unique alert_id to have multiple alerts visible at a time, use the same alert_id to fade out the current instance
|
||||
// takes a string like 1000 and returns 1,000
|
||||
app.addCommas = function (text) {
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||
};
|
||||
|
||||
// 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
|
||||
// title = bolded title text
|
||||
// message = alert message content
|
||||
// timeout default = permanent
|
||||
// location : alert_window (default) or content
|
||||
app.alert = function(params) {
|
||||
var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime());
|
||||
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);
|
||||
|
||||
|
||||
$(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.on('click', function () {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
button.className = 'close';
|
||||
button.innerHTML = '×';
|
||||
button.onclick = function(ev) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
|
||||
if (params.location == null)
|
||||
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.current_room = null;
|
||||
app.enter_room = function(room) {
|
||||
|
||||
if(socket) {
|
||||
if (app.current_room === room)
|
||||
return;
|
||||
|
||||
socket.emit('event:enter_room', {
|
||||
'enter': room,
|
||||
'leave': app.current_room
|
||||
});
|
||||
|
||||
app.current_room = room;
|
||||
}
|
||||
};
|
||||
|
||||
app.populate_online_users = function() {
|
||||
app.alertSuccess = function (message, timeout) {
|
||||
if (!timeout)
|
||||
timeout = 2000;
|
||||
|
||||
app.alert({
|
||||
title: 'Success',
|
||||
message: message,
|
||||
type: 'success',
|
||||
timeout: timeout
|
||||
});
|
||||
};
|
||||
|
||||
app.alertError = function (message, timeout) {
|
||||
if (!timeout)
|
||||
timeout = 2000;
|
||||
|
||||
app.alert({
|
||||
title: 'Error',
|
||||
message: message,
|
||||
type: 'danger',
|
||||
timeout: timeout
|
||||
});
|
||||
};
|
||||
|
||||
app.enterRoom = function (room, force) {
|
||||
if (socket) {
|
||||
if (app.currentRoom === room && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('event:enter_room', {
|
||||
'enter': room,
|
||||
'leave': app.currentRoom
|
||||
});
|
||||
|
||||
app.currentRoom = room;
|
||||
}
|
||||
};
|
||||
|
||||
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() {
|
||||
function highlightNavigationLink() {
|
||||
var path = window.location.pathname,
|
||||
parts = path.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
|
||||
// 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];
|
||||
|
||||
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');
|
||||
@@ -247,15 +307,42 @@ var socket,
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||
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() {
|
||||
if(location.href.indexOf('loggedin') !== -1) {
|
||||
app.showLoginMessage = function () {
|
||||
function showAlert() {
|
||||
app.alert({
|
||||
type: 'success',
|
||||
title: 'Welcome Back ' + app.username + '!',
|
||||
@@ -263,65 +350,128 @@ var socket,
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
addTouchEvents();
|
||||
if (showWelcomeMessage) {
|
||||
showWelcomeMessage = false;
|
||||
if (document.readyState !== 'complete') {
|
||||
$(document).ready(showAlert);
|
||||
} else {
|
||||
showAlert();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.addCommasToNumbers = function () {
|
||||
$('.formatted-number').each(function (index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
};
|
||||
|
||||
app.openChat = function (username, touid) {
|
||||
if (username === app.username) {
|
||||
app.alert({
|
||||
type: 'warning',
|
||||
title: 'Invalid Chat',
|
||||
message: "You can't chat with yourself!",
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!app.username) {
|
||||
app.alert({
|
||||
type: 'danger',
|
||||
title: 'Not Logged In',
|
||||
message: 'Please log in to chat with <strong>' + username + '</strong>',
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
require(['chat'], function (chat) {
|
||||
var chatModal;
|
||||
if (!chat.modalExists(touid)) {
|
||||
chatModal = chat.createModal(username, touid);
|
||||
} else {
|
||||
chatModal = chat.getModal(touid);
|
||||
}
|
||||
chat.load(chatModal.attr('UUID'));
|
||||
chat.center(chatModal);
|
||||
});
|
||||
};
|
||||
|
||||
app.scrollToTop = function () {
|
||||
$('body,html').animate({
|
||||
scrollTop: 0
|
||||
});
|
||||
};
|
||||
|
||||
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());
|
||||
input.val('');
|
||||
return false;
|
||||
});
|
||||
|
||||
$(window).blur(function(){
|
||||
app.isFocused = false;
|
||||
});
|
||||
|
||||
$(window).focus(function(){
|
||||
app.isFocused = true;
|
||||
|
||||
app.alternatingTitle('');
|
||||
});
|
||||
});
|
||||
|
||||
loadConfig();
|
||||
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||
|
||||
|
||||
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,55 +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();
|
||||
|
||||
var rep = $('#reputation');
|
||||
rep.html(app.addCommas(rep.html()));
|
||||
|
||||
var postcount = $('#postcount');
|
||||
postcount.html(app.addCommas(postcount.html()));
|
||||
|
||||
var followBtn = $('#follow-btn');
|
||||
if(yourid === "0") {
|
||||
followBtn.hide();
|
||||
}
|
||||
else if(yourid !== theirid) {
|
||||
if(isFollowing)
|
||||
followBtn.hide();
|
||||
else
|
||||
followBtn.show();
|
||||
}
|
||||
else {
|
||||
followBtn.hide();
|
||||
}
|
||||
|
||||
followBtn.on('click', function() {
|
||||
|
||||
followBtn.remove();
|
||||
socket.emit('api:user.follow', {uid: theirid});
|
||||
return false;
|
||||
});
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
isFollowing = templates.get('isFollowing');
|
||||
|
||||
$('.user-recent-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
|
||||
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');
|
||||
$(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 {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||
followBtn.addClass('hide');
|
||||
unfollowBtn.addClass('hide');
|
||||
chatBtn.addClass('hide');
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
socket.emit('api:user.isOnline', theirid);
|
||||
};
|
||||
|
||||
});
|
||||
Account.handleUserOnline = function(data) {
|
||||
var onlineStatus = $('.account-online-status');
|
||||
|
||||
}());
|
||||
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,254 +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;
|
||||
});
|
||||
|
||||
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) {
|
||||
var userData = {
|
||||
type: type
|
||||
};
|
||||
|
||||
socket.emit('api:user.changePicture', userData);
|
||||
}
|
||||
|
||||
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);
|
||||
return false;
|
||||
});
|
||||
|
||||
function updateImages() {
|
||||
var currentPicture = $('#user-current-picture').attr('src');
|
||||
|
||||
if(gravatarPicture) {
|
||||
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
||||
$('#gravatar-box').show();
|
||||
}
|
||||
else
|
||||
$('#gravatar-box').hide();
|
||||
|
||||
if(uploadedPicture) {
|
||||
$('#user-uploaded-picture').attr('src', uploadedPicture);
|
||||
$('#uploaded-box').show();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
$('#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()
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
socket.on('api:user.changePassword', function(data) {
|
||||
currentPassword.val('');
|
||||
password.val('');
|
||||
password_confirm.val('');
|
||||
password_notify.html('');
|
||||
password_confirm_notify.html('');
|
||||
passwordsmatch = false;
|
||||
passwordvalid = false;
|
||||
|
||||
function getSignatureCharsLeft() {
|
||||
return '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')';
|
||||
}
|
||||
|
||||
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
|
||||
|
||||
$('#inputSignature').on('keyup change', function(ev) {
|
||||
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
|
||||
});
|
||||
|
||||
}());
|
||||
$('#changePictureBtn').on('click', function() {
|
||||
selectedImageType = '';
|
||||
AccountEdit.updateImages();
|
||||
|
||||
$('#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) {
|
||||
app.alertError('There was an error changing picture!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AccountEdit.updateImages = function() {
|
||||
var currentPicture = $('#user-current-picture').attr('src');
|
||||
|
||||
if (gravatarPicture) {
|
||||
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
||||
$('#gravatar-box').show();
|
||||
} else {
|
||||
$('#gravatar-box').hide();
|
||||
}
|
||||
|
||||
if (uploadedPicture) {
|
||||
$('#user-uploaded-picture').attr('src', uploadedPicture);
|
||||
$('#uploaded-box').show();
|
||||
} else {
|
||||
$('#uploaded-box').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();
|
||||
}
|
||||
}
|
||||
|
||||
return AccountEdit;
|
||||
});
|
||||
@@ -1,20 +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');
|
||||
|
||||
AccountHeader.createMenu();
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
var editLink = $('#editLink');
|
||||
var settingsLink = $('#settingsLink');
|
||||
|
||||
if(yourid === "0") {
|
||||
editLink.hide();
|
||||
settingsLink.hide();
|
||||
}
|
||||
else if(yourid !== theirid) {
|
||||
editLink.hide();
|
||||
settingsLink.hide();
|
||||
}
|
||||
});
|
||||
var favouritesLink = $('#favouritesLink');
|
||||
|
||||
}());
|
||||
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,16 +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() {
|
||||
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;
|
||||
});
|
||||
};
|
||||
|
||||
var settings = {
|
||||
showemail: $('#showemailCheckBox').is(':checked')?1:0
|
||||
};
|
||||
|
||||
socket.emit('api:user.saveSettings', settings);
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
return AccountSettings;
|
||||
});
|
||||
|
||||
@@ -1,79 +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;
|
||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', {cid:cid}, function(imageUrlOnServer) {
|
||||
inputEl.value = imageUrlOnServer;
|
||||
$(inputEl).parents('li[data-cid]').find('.preview-box').css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
|
||||
modified(inputEl);
|
||||
});
|
||||
});
|
||||
|
||||
$('.admin-categories').delegate('.delete-image', 'click', function() {
|
||||
var parent = $(this).parents('li[data-cid]'),
|
||||
inputEl = parent.find('.upload-button'),
|
||||
preview = parent.find('.preview-box'),
|
||||
bgColor = parent.find('.category_bgColor').val();
|
||||
|
||||
inputEl.value = '';
|
||||
modified(inputEl);
|
||||
|
||||
preview.css('background', bgColor);
|
||||
|
||||
$(this).hide();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Categories.launchPermissionsModal = function(cid) {
|
||||
var modal = $('#category-permissions-modal'),
|
||||
searchEl = modal.find('#permission-search'),
|
||||
resultsEl = modal.find('.search-results'),
|
||||
groupsResultsEl = modal.find('.groups-results'),
|
||||
searchDelay;
|
||||
|
||||
searchEl.off().on('keyup', function() {
|
||||
var searchEl = this,
|
||||
resultsFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
clearTimeout(searchDelay);
|
||||
|
||||
searchDelay = setTimeout(function() {
|
||||
socket.emit('api:admin.categories.search', searchEl.value, cid, function(err, results) {
|
||||
var numResults = results.length,
|
||||
resultObj;
|
||||
for(var x=0;x<numResults;x++) {
|
||||
resultObj = results[x];
|
||||
|
||||
liEl.setAttribute('data-uid', resultObj.uid);
|
||||
liEl.innerHTML = '<div class="pull-right">' +
|
||||
'<div class="btn-group">' +
|
||||
'<button type="button" data-priv="+r" class="btn btn-default' + (resultObj.privileges['+r'] ? ' active' : '') + '">Read</button>' +
|
||||
'<button type="button" data-priv="+w" class="btn btn-default' + (resultObj.privileges['+w'] ? ' active' : '') + '">Write</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<img src="' + resultObj.picture + '" /> ' + resultObj.username;
|
||||
|
||||
resultsFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
resultsEl.html(resultsFrag);
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}());
|
||||
|
||||
modal.off().on('click', '.members li > img', function() {
|
||||
searchEl.val(this.getAttribute('title'));
|
||||
searchEl.keyup();
|
||||
});
|
||||
|
||||
// User Groups and privileges
|
||||
socket.emit('api:admin.categories.groupsearch', cid, function(err, results) {
|
||||
var groupsFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
var numResults = results.length,
|
||||
resultObj;
|
||||
|
||||
for(var x=0;x<numResults;x++) {
|
||||
resultObj = results[x];
|
||||
liEl.setAttribute('data-gid', resultObj.gid);
|
||||
liEl.innerHTML = '<div class="pull-right">' +
|
||||
'<div class="btn-group">' +
|
||||
'<button type="button" data-gpriv="+gr" class="btn btn-default' + (resultObj.privileges['+gr'] ? ' active' : '') + '">Read</button>' +
|
||||
'<button type="button" data-gpriv="+gw" class="btn btn-default' + (resultObj.privileges['+gw'] ? ' active' : '') + '">Write</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
' '+resultObj.name;
|
||||
|
||||
groupsFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
groupsResultsEl.html(groupsFrag);
|
||||
});
|
||||
|
||||
groupsResultsEl.off().on('click', '[data-gpriv]', function(e) {
|
||||
var btnEl = $(this),
|
||||
gid = btnEl.parents('li[data-gid]').attr('data-gid'),
|
||||
privilege = this.getAttribute('data-gpriv');
|
||||
e.preventDefault();
|
||||
socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
|
||||
btnEl.toggleClass('active', privileges[privilege]);
|
||||
});
|
||||
})
|
||||
|
||||
modal.modal();
|
||||
};
|
||||
|
||||
Categories.refreshPrivilegeList = function (cid) {
|
||||
var modalEl = $('#category-permissions-modal'),
|
||||
readMembers = modalEl.find('#category-permissions-read'),
|
||||
writeMembers = modalEl.find('#category-permissions-write');
|
||||
socket.emit('api:admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
|
||||
var readLength = privilegeList['+r'].length,
|
||||
writeLength = privilegeList['+w'].length,
|
||||
readFrag = document.createDocumentFragment(),
|
||||
writeFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li'),
|
||||
x, userObj;
|
||||
|
||||
if (readLength > 0) {
|
||||
for(x=0;x<readLength;x++) {
|
||||
userObj = privilegeList['+r'][x];
|
||||
liEl.setAttribute('data-uid', userObj.uid);
|
||||
|
||||
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
|
||||
readFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
liEl.className = 'empty';
|
||||
liEl.innerHTML = 'No users are in this list';
|
||||
readFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
if (writeLength > 0) {
|
||||
for(x=0;x<writeLength;x++) {
|
||||
userObj = privilegeList['+w'][x];
|
||||
liEl.setAttribute('data-uid', userObj.uid);
|
||||
|
||||
liEl.innerHTML = '<img src="' + userObj.picture + '" title="' + userObj.username + '" />';
|
||||
writeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
liEl.className = 'empty';
|
||||
liEl.innerHTML = 'No users are in this list';
|
||||
writeFrag.appendChild(liEl.cloneNode(true));
|
||||
}
|
||||
|
||||
readMembers.html(readFrag);
|
||||
writeMembers.html(writeFrag);
|
||||
});
|
||||
};
|
||||
|
||||
return Categories;
|
||||
});
|
||||
|
||||
@@ -1,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;
|
||||
});
|
||||
|
||||
33
public/src/forum/admin/plugins.js
Normal file
33
public/src/forum/admin/plugins.js
Normal file
@@ -0,0 +1,33 @@
|
||||
define(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);
|
||||
});
|
||||
|
||||
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';
|
||||
|
||||
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>');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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,112 +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?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.once('api:admin:themes.getInstalled', function(themes) {
|
||||
var instListEl = document.getElementById('installed_themes'),
|
||||
themeFrag = document.createDocumentFragment(),
|
||||
liEl = document.createElement('li');
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
instListEl.innerHTML = '';
|
||||
instListEl.appendChild(themeFrag);
|
||||
});
|
||||
socket.emit('api:admin:themes.getInstalled');
|
||||
})();
|
||||
return Themes;
|
||||
});
|
||||
@@ -1,118 +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();
|
||||
|
||||
$(topicsListEl).on('click', '[data-action]', function() {
|
||||
var $this = $(this),
|
||||
action = this.getAttribute('data-action'),
|
||||
tid = $this.parents('[data-tid]').attr('data-tid');
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
loadMoreEl.addEventListener('click', function() {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
var topics = document.querySelectorAll('.topics li[data-tid]');
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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'));
|
||||
|
||||
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
|
||||
socket.emit('api:admin.topics.getMore', {
|
||||
limit: 10,
|
||||
after: lastTid
|
||||
});
|
||||
}
|
||||
}, 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')) topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-locked')) topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-deleted')) 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');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:admin.topics.getMore', function(topics) {
|
||||
var btnEl = document.getElementById('topics_loadmore');
|
||||
|
||||
topics = JSON.parse(topics);
|
||||
console.log(topics);
|
||||
if (topics.length > 0) {
|
||||
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
}),
|
||||
topicsListEl = document.querySelector('.topics');
|
||||
|
||||
topicsListEl.innerHTML += html;
|
||||
btnEl.innerHTML = 'Load More Topics';
|
||||
} else {
|
||||
// Exhausted all topics
|
||||
btnEl.className += ' disabled';
|
||||
btnEl.innerHTML = 'No more topics';
|
||||
}
|
||||
return Topics;
|
||||
});
|
||||
@@ -1,144 +1,271 @@
|
||||
define(function() {
|
||||
var Users = {};
|
||||
|
||||
(function() {
|
||||
|
||||
function initUsers() {
|
||||
Users.init = function() {
|
||||
var yourid = templates.get('yourid');
|
||||
|
||||
function isUserAdmin(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return (parent.attr('data-admin') !== "0");
|
||||
}
|
||||
|
||||
function getUID(element) {
|
||||
function isUserBanned(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return parent.attr('data-uid');
|
||||
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
|
||||
}
|
||||
|
||||
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');
|
||||
function getUID(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return parent.attr('data-uid');
|
||||
}
|
||||
|
||||
});
|
||||
function updateUserBanButtons() {
|
||||
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 if (!isUserAdmin(banBtn))
|
||||
banBtn.removeClass('disabled');
|
||||
else
|
||||
banBtn.removeClass('btn-warning');
|
||||
updateUserAdminButtons();
|
||||
});
|
||||
}
|
||||
|
||||
jQuery('.delete-btn').each(function(index, element) {
|
||||
var deleteBtn = $(element);
|
||||
var isAdmin = isUserAdmin(deleteBtn);
|
||||
|
||||
if(isAdmin)
|
||||
deleteBtn.addClass('disabled');
|
||||
else
|
||||
deleteBtn.show();
|
||||
});
|
||||
|
||||
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);
|
||||
function updateUserAdminButtons() {
|
||||
jQuery('.admin-btn').each(function(index, element) {
|
||||
var adminBtn = $(element);
|
||||
var uid = getUID(adminBtn);
|
||||
if (isUserAdmin(adminBtn)) {
|
||||
adminBtn.attr('value', 'UnMake Admin').html('Remove Admin');
|
||||
if (uid === yourid) {
|
||||
adminBtn.addClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else if (isUserBanned(adminBtn))
|
||||
adminBtn.addClass('disabled');
|
||||
else if (!isUserBanned(adminBtn))
|
||||
adminBtn.removeClass('disabled');
|
||||
else
|
||||
adminBtn.removeClass('btn-warning');
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
function initUsers() {
|
||||
updateUserBanButtons();
|
||||
updateUserAdminButtons();
|
||||
|
||||
$('#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);
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
if (!isAdmin) {
|
||||
if (isBanned) {
|
||||
socket.emit('api:admin.user.unbanUser', uid);
|
||||
banBtn.removeClass('btn-warning');
|
||||
parent.attr('data-banned', 0);
|
||||
updateUserAdminButtons();
|
||||
} else {
|
||||
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:admin.user.banUser', uid);
|
||||
banBtn.addClass('btn-warning');
|
||||
parent.attr('data-banned', 1);
|
||||
updateUserAdminButtons();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var yourid = templates.get('yourid');
|
||||
var timeoutId = 0;
|
||||
|
||||
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();
|
||||
$('#users-container').on('click', '.admin-btn', function() {
|
||||
var adminBtn = $(this);
|
||||
var isAdmin = isUserAdmin(adminBtn);
|
||||
var parent = adminBtn.parents('.users-box');
|
||||
var isBanned = isUserBanned(adminBtn);
|
||||
var uid = getUID(adminBtn);
|
||||
|
||||
if(uid === yourid){
|
||||
app.alert({
|
||||
title: 'Error',
|
||||
message: 'You can\'t remove yourself as Administrator!',
|
||||
type: 'danger',
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
else if (!isAdmin) {
|
||||
socket.emit('api:admin.user.makeAdmin', uid);
|
||||
adminBtn.attr('value', 'UnMake Admin').html('Remove Admin');
|
||||
parent.attr('data-admin', 1);
|
||||
updateUserBanButtons();
|
||||
|
||||
} else if(uid !== yourid) {
|
||||
bootbox.confirm('Do you really want to remove this user as admin "' + parent.attr('data-username') + '"?', function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('api:admin.user.removeAdmin', uid);
|
||||
adminBtn.attr('value', 'Make Admin').html('Make Admin');
|
||||
parent.attr('data-admin', 0);
|
||||
updateUserBanButtons();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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({
|
||||
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 = document.querySelector('.users');
|
||||
|
||||
userListEl.innerHTML = html;
|
||||
jQuery('.icon-spinner').addClass('none');
|
||||
userListEl.innerHTML = html;
|
||||
jQuery('.fa-spinner').addClass('none');
|
||||
|
||||
if(data && data.length === 0) {
|
||||
$('#user-notfound-notify').html('User not found!')
|
||||
.show()
|
||||
.addClass('label-important')
|
||||
.removeClass('label-success');
|
||||
if (data && data.length === 0) {
|
||||
$('#user-notfound-notify').html('User not found!')
|
||||
.show()
|
||||
.addClass('label-danger')
|
||||
.removeClass('label-success');
|
||||
} else {
|
||||
$('#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();
|
||||
}
|
||||
else {
|
||||
$('#user-notfound-notify').html(data.length + ' user'+(data.length>1?'s':'') + ' found!')
|
||||
.show()
|
||||
.addClass('label-success')
|
||||
.removeClass('label-important');
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initUsers();
|
||||
|
||||
$('#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,95 +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');
|
||||
|
||||
app.enter_room(room);
|
||||
define(['composer'], function(composer) {
|
||||
var Category = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
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);
|
||||
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');
|
||||
|
||||
var new_post = document.getElementById('new_post');
|
||||
new_post.onclick = function() {
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(0, cid);
|
||||
app.enterRoom('category_' + 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'
|
||||
]);
|
||||
|
||||
socket.on('event:new_topic', function(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'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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');
|
||||
loadingMoreTopics = true;
|
||||
socket.emit('api:category.loadMore', {
|
||||
cid: cid,
|
||||
after: $('#topics-container').children('.category-item').length
|
||||
}, function (data) {
|
||||
if (data.topics.length) {
|
||||
Category.onTopicsLoaded(data.topics);
|
||||
}
|
||||
loadingMoreTopics = false;
|
||||
});
|
||||
}
|
||||
|
||||
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].tid + '">' +
|
||||
'<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);
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
return Category;
|
||||
});
|
||||
9
public/src/forum/favourites.js
Normal file
9
public/src/forum/favourites.js
Normal file
@@ -0,0 +1,9 @@
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var AccountHeader = {};
|
||||
|
||||
AccountHeader.init = function() {
|
||||
header.init();
|
||||
};
|
||||
|
||||
return AccountHeader;
|
||||
});
|
||||
@@ -1,24 +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();
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
if(parseInt(followersCount, 10) === 0) {
|
||||
$('#no-followers-notice').show();
|
||||
}
|
||||
|
||||
$('.reputation').each(function(index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
|
||||
$('.postcount').each(function(index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
followersCount = templates.get('followersCount');
|
||||
|
||||
}());
|
||||
|
||||
if (parseInt(followersCount, 10) === 0) {
|
||||
$('#no-followers-notice').removeClass('hide');
|
||||
}
|
||||
|
||||
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 (parseInt(followingCount, 10) === 0) {
|
||||
$('#no-following-notice').removeClass('hide');
|
||||
}
|
||||
|
||||
if(yourid !== theirid) {
|
||||
$('.unfollow-btn').hide();
|
||||
}
|
||||
else {
|
||||
$('.unfollow-btn').on('click',function() {
|
||||
app.addCommasToNumbers();
|
||||
};
|
||||
|
||||
var removeBtn = $(this);
|
||||
var followingUid = $(this).attr('followingUid');
|
||||
|
||||
removeBtn.parent().remove();
|
||||
socket.emit('api:user.unfollow', {uid: followingUid});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
$('.reputation').each(function(index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
|
||||
$('.postcount').each(function(index, element) {
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
}());
|
||||
return Following;
|
||||
});
|
||||
@@ -1,166 +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');
|
||||
if (data.uid > 0) {
|
||||
|
||||
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'])
|
||||
$('#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) {
|
||||
$('.nodebb-loggedin').show();
|
||||
$('.nodebb-loggedout').hide();
|
||||
|
||||
$('#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 {
|
||||
rightMenu.html('');
|
||||
if (allowGuestSearching) {
|
||||
$('#search-button').removeClass("hide").show();
|
||||
} else {
|
||||
$('#search-button').addClass("hide").hide();
|
||||
}
|
||||
|
||||
var registerEl = document.createElement('li'),
|
||||
loginEl = document.createElement('li');
|
||||
$('.nodebb-loggedin').hide();
|
||||
$('.nodebb-loggedout').show();
|
||||
|
||||
registerEl.innerHTML = '<a href="/register">Register</a>';
|
||||
loginEl.innerHTML = '<a href="/login">Login</a>';
|
||||
$('#logged-out-menu').removeClass('hide');
|
||||
$('#logged-in-menu').addClass('hide');
|
||||
|
||||
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');
|
||||
notifList = document.getElementById('notif-list'),
|
||||
notifIcon = $('.notifications a');
|
||||
|
||||
notifTrigger.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (notifContainer.className.indexOf('open') === -1) socket.emit('api:notifications.get');
|
||||
if (notifContainer.className.indexOf('open') === -1) {
|
||||
socket.emit('api:notifications.get', null, function(data) {
|
||||
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++) {
|
||||
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++) {
|
||||
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.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.toggleClass('active', true);
|
||||
} else {
|
||||
notifIcon.toggleClass('active', false);
|
||||
}
|
||||
|
||||
socket.emit('api:notifications.mark_all_read', null, function() {
|
||||
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);
|
||||
}
|
||||
})
|
||||
socket.on('api:notifications.get', function(data) {
|
||||
var notifFrag = document.createDocumentFragment(),
|
||||
notifEl = document.createElement('li'),
|
||||
notifIcon = document.querySelector('.notifications a i'),
|
||||
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++) {
|
||||
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++) {
|
||||
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));
|
||||
}
|
||||
});
|
||||
|
||||
var updateNotifCount = function(count) {
|
||||
// Update notification icon, if necessary
|
||||
if (count > 0) {
|
||||
notifIcon.toggleClass('active', true);
|
||||
} else {
|
||||
notifEl.innerHTML = '<a>You have no notifications</a>';
|
||||
notifFrag.appendChild(notifEl);
|
||||
notifIcon.toggleClass('active', false);
|
||||
}
|
||||
notifList.appendChild(notifFrag);
|
||||
|
||||
socket.emit('api:notifications.removeFlag');
|
||||
notifIcon.className = 'icon-circle-blank';
|
||||
});
|
||||
socket.on('api:notifications.hasFlag', function(flag) {
|
||||
var notifIcon = document.querySelector('.notifications a i');
|
||||
if(notifIcon) {
|
||||
if (flag > 0) notifIcon.className = 'icon-circle active';
|
||||
else notifIcon.className = 'icon-circle-blank';
|
||||
// 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: 'warning',
|
||||
timeout: 2000
|
||||
});
|
||||
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);
|
||||
});
|
||||
socket.emit('api:notifications.hasFlag');
|
||||
|
||||
// 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;
|
||||
|
||||
require(['chat'], function(chat) {
|
||||
var chatModal = chat.createModalIfDoesntExist(username, fromuid);
|
||||
chatModal.show();
|
||||
chat.bringModalToTop(chatModal);
|
||||
|
||||
chat.appendChatMessage(chatModal, message);
|
||||
socket.emit('api:chats.list', function(chats) {
|
||||
var chatsFrag = document.createDocumentFragment(),
|
||||
chatEl = document.createElement('li'),
|
||||
numChats = chats.length,
|
||||
x, userObj;
|
||||
|
||||
if (numChats > 0) {
|
||||
for(x=0;x<numChats;x++) {
|
||||
userObj = chats[x];
|
||||
chatEl.setAttribute('data-uid', userObj.uid);
|
||||
chatEl.innerHTML = '<a href="javascript:app.openChat(\'' + userObj.username + '\', ' + userObj.uid + ');"><img src="' + userObj.picture + '" title="' + userObj.username + '" />' + userObj.username + '</a>';
|
||||
|
||||
chatsFrag.appendChild(chatEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
chatEl.innerHTML = '<a href="#">No Recent Chats</a>';
|
||||
chatsFrag.appendChild(chatEl.cloneNode(true));
|
||||
}
|
||||
|
||||
chatsListEl.empty();
|
||||
chatsListEl.html(chatsFrag);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('event:chats.receive', function(data) {
|
||||
require(['chat'], function(chat) {
|
||||
var modal = null;
|
||||
if (chat.modalExists(data.fromuid)) {
|
||||
modal = chat.getModal(data.fromuid);
|
||||
chat.appendChatMessage(modal, data.message, data.timestamp);
|
||||
|
||||
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,44 +1,64 @@
|
||||
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').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) {
|
||||
$('#login-error-notify').hide();
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
},
|
||||
error : function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').show().delay(1000).fadeOut(250);
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
timeout: 2000
|
||||
$('#login').attr('disabled', 'disabled').html('Logging in...');
|
||||
$('#login-error-notify').hide();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: RELATIVE_PATH + '/login',
|
||||
data: loginData,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
|
||||
if (!data.success) {
|
||||
$('#login-error-notify').show();
|
||||
$('#login').removeAttr('disabled').html('Login');
|
||||
} else {
|
||||
$('#login').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
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
}());
|
||||
$('#login-error-notify button').on('click', function() {
|
||||
$('#login-error-notify').hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
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,50 +1,114 @@
|
||||
(function() {
|
||||
app.enter_room('recent_posts');
|
||||
define(function() {
|
||||
var Recent = {};
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
'event:new_post'
|
||||
]);
|
||||
Recent.newTopicCount = 0;
|
||||
Recent.newPostCount = 0;
|
||||
Recent.loadingMoreTopics = false;
|
||||
|
||||
var newTopicCount = 0, newPostCount = 0;
|
||||
var active = '';
|
||||
|
||||
$('#new-topics-alert').on('click', function() {
|
||||
$(this).hide();
|
||||
});
|
||||
Recent.init = function() {
|
||||
app.enterRoom('recent_posts');
|
||||
|
||||
socket.on('event:new_topic', function(data) {
|
||||
|
||||
++newTopicCount;
|
||||
updateAlertText();
|
||||
|
||||
});
|
||||
|
||||
function updateAlertText() {
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
'event:new_post'
|
||||
]);
|
||||
|
||||
|
||||
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');
|
||||
$('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow');
|
||||
}
|
||||
|
||||
socket.on('event:new_post', function(data) {
|
||||
++newPostCount;
|
||||
updateAlertText();
|
||||
|
||||
});
|
||||
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'));
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
return Recent;
|
||||
});
|
||||
|
||||
@@ -1,156 +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(!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