mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-19 23:10:21 +01:00
Compare commits
464 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
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 | ||
|
|
f5c4f98834 |
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,7 +1,3 @@
|
||||
#################
|
||||
## npm
|
||||
#################
|
||||
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
sftp-config.json
|
||||
@@ -9,11 +5,13 @@ config.json
|
||||
public/src/nodebb.min.js
|
||||
public/config.json
|
||||
public/css/*.css
|
||||
public/themes/*
|
||||
!/public/themes/vanilla
|
||||
!/public/themes/cerulean
|
||||
!/public/themes/modern
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
plugins/*
|
||||
.project
|
||||
*.swp
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
provision.sh
|
||||
*.komodoproject
|
||||
|
||||
feeds/recent.rss
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
|
||||
# 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")
|
||||
* [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/nodebb) - #nodebb on Freenode
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## How can I follow along/contribute?
|
||||
|
||||
|
||||
61
app.js
61
app.js
@@ -55,7 +55,7 @@
|
||||
winston.info('');
|
||||
|
||||
|
||||
if (fs.existsSync(__dirname + '/config.json') && (!nconf.get('setup') && !nconf.get('upgrade'))) {
|
||||
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
|
||||
// Load server-side configs
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
@@ -64,9 +64,10 @@
|
||||
|
||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||
nconf.set('base_dir', __dirname);
|
||||
|
||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
winston.info('NodeBB instance bound to: ' + (nconf.get('bind_address') || 'Any address'));
|
||||
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.');
|
||||
@@ -86,8 +87,13 @@
|
||||
webserver = require('./src/webserver.js'),
|
||||
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
|
||||
websockets = require('./src/websockets.js'),
|
||||
plugins = require('./src/plugins'); // Don't remove this - plugins initializes itself
|
||||
posts = require('./src/posts.js'),
|
||||
plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself
|
||||
Notifications = require('./src/notifications'),
|
||||
Upgrade = require('./src/upgrade');
|
||||
|
||||
Upgrade.check(function(schema_ok) {
|
||||
if (schema_ok || nconf.get('check-schema') === false) {
|
||||
websockets.init(SocketIO);
|
||||
|
||||
global.templates = {};
|
||||
@@ -95,6 +101,8 @@
|
||||
|
||||
translator.loadServer();
|
||||
|
||||
var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false;
|
||||
|
||||
// todo: replace below with read directory code, derp.
|
||||
templates.init([
|
||||
'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index',
|
||||
@@ -102,18 +110,24 @@
|
||||
'emails/header', 'emails/footer',
|
||||
|
||||
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
||||
]);
|
||||
], customTemplates);
|
||||
|
||||
|
||||
plugins.ready(function() {
|
||||
templates.ready(webserver.init);
|
||||
});
|
||||
|
||||
} else if (nconf.get('upgrade')) {
|
||||
meta = require('./src/meta.js');
|
||||
|
||||
meta.configs.init(function () {
|
||||
require('./src/upgrade').upgrade();
|
||||
});
|
||||
Notifications.init();
|
||||
} else {
|
||||
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
|
||||
winston.warn(' node app --upgrade');
|
||||
winston.warn('To ignore this error (not recommended):');
|
||||
winston.warn(' node app --no-check-schema')
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (nconf.get('setup') || !fs.existsSync(__dirname + '/config.json')) {
|
||||
// New install, ask setup questions
|
||||
if (nconf.get('setup')) {
|
||||
winston.info('NodeBB Setup Triggered via Command Line');
|
||||
@@ -121,6 +135,10 @@
|
||||
winston.warn('Configuration not found, starting NodeBB setup');
|
||||
}
|
||||
|
||||
nconf.file({
|
||||
file: __dirname + '/config.json'
|
||||
});
|
||||
|
||||
var install = require('./src/install');
|
||||
|
||||
winston.info('Welcome to NodeBB!');
|
||||
@@ -131,10 +149,29 @@
|
||||
if (err) {
|
||||
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||
} else {
|
||||
winston.info('NodeBB Setup Completed.');
|
||||
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'
|
||||
});
|
||||
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)');
|
||||
};
|
||||
}());
|
||||
@@ -3,72 +3,84 @@
|
||||
"name": "Announcements",
|
||||
"description": "Announcements regarding our community",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-bullhorn"
|
||||
"icon" : "icon-bullhorn",
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"name": "General Discussion",
|
||||
"description": "A place to talk about whateeeever you want",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-comment"
|
||||
"icon" : "icon-comment",
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Development",
|
||||
"description": "NodeBB development news and announcements",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-github"
|
||||
"icon" : "icon-github",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"name": "Blogs",
|
||||
"description": "Blog posts from individual members",
|
||||
"blockclass": "category-blue",
|
||||
"icon" : "icon-pencil"
|
||||
"icon" : "icon-pencil",
|
||||
"order": 4
|
||||
},
|
||||
{
|
||||
"name": "Feature Requests",
|
||||
"description": "Got a feature request you'd like to see? Give us a shout here.",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-lightbulb"
|
||||
"icon" : "icon-lightbulb",
|
||||
"order": 5
|
||||
},
|
||||
{
|
||||
"name": "Bug Reports",
|
||||
"description": "Having trouble with NodeBB? Let us know...",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-cogs"
|
||||
"icon" : "icon-cogs",
|
||||
"order": 6
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Plugins",
|
||||
"description": "Enhance your NodeBB with plugins!",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-plus-sign"
|
||||
"icon" : "icon-plus-sign",
|
||||
"order": 7
|
||||
},
|
||||
{
|
||||
"name": "NodeBB Link Exchange",
|
||||
"description": "Link exchange",
|
||||
"blockclass": "category-purple",
|
||||
"icon" : "icon-exchange"
|
||||
"icon" : "icon-exchange",
|
||||
"order": 8
|
||||
},
|
||||
{
|
||||
"name": "News",
|
||||
"description": "News from around the world",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-globe"
|
||||
"icon" : "icon-globe",
|
||||
"order": 9
|
||||
},
|
||||
{
|
||||
"name": "Movies",
|
||||
"description": "Discuss the latest movies here",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-film"
|
||||
"icon" : "icon-film",
|
||||
"order": 10
|
||||
},
|
||||
{
|
||||
"name": "Games",
|
||||
"description": "Discuss the latest games here",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-screenshot"
|
||||
"icon" : "icon-screenshot",
|
||||
"order": 11
|
||||
},
|
||||
{
|
||||
"name": "Random",
|
||||
"description": "Anything and (almost) everything welcome!",
|
||||
"blockclass": "category-darkblue",
|
||||
"icon" : "icon-beer"
|
||||
"icon" : "icon-beer",
|
||||
"order": 12
|
||||
}
|
||||
]
|
||||
69
mocks/redismock.js
Normal file
69
mocks/redismock.js
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Redis Mock - wrapper for redis.js, makes system use separate test db, instead of production
|
||||
* ATTENTION: testing db is flushed before every use!
|
||||
*/
|
||||
|
||||
(function(module) {
|
||||
'use strict';
|
||||
|
||||
var RedisDB,
|
||||
redis = require('redis'),
|
||||
utils = require('./../public/src/utils.js'),
|
||||
path = require('path'),
|
||||
nconf = require('nconf'),
|
||||
winston = require('winston'),
|
||||
errorText;
|
||||
|
||||
|
||||
nconf.file({ file: path.join(__dirname, '../config.json') });
|
||||
|
||||
var testDbConfig = nconf.get('redis_test'),
|
||||
productionDbConfig = nconf.get('redis');
|
||||
if(!testDbConfig){
|
||||
errorText = 'redis_test database is not defined';
|
||||
winston.info(
|
||||
"\n===========================================================\n"+
|
||||
"Please, add parameters for test database in config.json\n"+
|
||||
"For example:\n"+
|
||||
'"redis_test": {' + '\n' +
|
||||
' "host": "127.0.0.1",' + '\n' +
|
||||
' "port": "6379",' + '\n' +
|
||||
' "password": "",' + '\n' +
|
||||
' "database": "1"' + '\n' +
|
||||
'}\n'+
|
||||
"==========================================================="
|
||||
);
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
if( testDbConfig.database === productionDbConfig.database &&
|
||||
testDbConfig.host === productionDbConfig.host &&
|
||||
testDbConfig.port === productionDbConfig.port
|
||||
){
|
||||
errorText = 'redis_test database has the same config as production db';
|
||||
winston.error(errorText);
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
nconf.set('redis',testDbConfig);
|
||||
|
||||
RedisDB = require('../src/redis.js');
|
||||
|
||||
|
||||
//Clean up
|
||||
RedisDB.send_command('flushdb', [], function(error){
|
||||
if(error){
|
||||
winston.error(error);
|
||||
throw new Error(error);
|
||||
} else {
|
||||
winston.info('redis_test db flushed');
|
||||
}
|
||||
});
|
||||
|
||||
//TODO: data seeding, if needed at all
|
||||
|
||||
|
||||
module.exports = RedisDB;
|
||||
|
||||
}(module));
|
||||
2
nodebb
2
nodebb
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
clear
|
||||
echo "Launching NodeBB in \"development\" mode."
|
||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||
|
||||
35
package.json
35
package.json
@@ -2,13 +2,16 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.7",
|
||||
"version": "0.1.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.16",
|
||||
"redis": "0.8.3",
|
||||
@@ -30,20 +33,25 @@
|
||||
"gravatar": "1.0.6",
|
||||
"nconf": "~0.6.7",
|
||||
"sitemap": "~0.6.0",
|
||||
"cheerio": "~0.12.0",
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2",
|
||||
"nodebb-plugin-mentions": "~0.1.0",
|
||||
"nodebb-plugin-markdown": "~0.1.0",
|
||||
"rss": "~0.2.0",
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0",
|
||||
"validator": "~1.5.1"
|
||||
"validator": "~1.5.1",
|
||||
"nodebb-plugin-mentions": "~0.1.14",
|
||||
"nodebb-plugin-markdown": "~0.1.8",
|
||||
"nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla",
|
||||
"nodebb-theme-cerulean": "0.0.7",
|
||||
"cron": "~1.0.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"hiredis": "~0.1.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.13.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
},
|
||||
@@ -53,15 +61,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",
|
||||
@@ -70,6 +85,10 @@
|
||||
{
|
||||
"name": "Matt Smith",
|
||||
"url": "https://github.com/soimafreak"
|
||||
},
|
||||
{
|
||||
"name": "Quinton Marchi",
|
||||
"url": "https://github.com/iamcardinal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
0
plugins/.gitignore
vendored
0
plugins/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
@import "../themes/cerulean/cerulean.less";
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"chat.chatting_with": "Chat with <span id='chat-with-name'></span>",
|
||||
"chat.placeholder": "type chat message, here press enter to send",
|
||||
"chat.placeholder": "type chat message here, press enter to send",
|
||||
"chat.send": "Send",
|
||||
"stats.online": "Online",
|
||||
"stats.users": "Users",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"logout": "Logout",
|
||||
"logout.title": "You are now logged out.",
|
||||
"logout.message": "You have successfully logged out of NodeBB",
|
||||
"header.admin": "Admin",
|
||||
"header.recent": "Recent",
|
||||
"header.unread": "Unread",
|
||||
"header.users": "Users",
|
||||
|
||||
3
public/language/en/notifications.json
Normal file
3
public/language/en/notifications.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Notifications"
|
||||
}
|
||||
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,6 +16,7 @@
|
||||
"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",
|
||||
"favourites.not_logged_in.title": "Not Logged In",
|
||||
"favourites.not_logged_in.message": "Please log in in order to favourite this post"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var ajaxify = {};
|
||||
"use strict";
|
||||
|
||||
var ajaxify = {};
|
||||
|
||||
(function ($) {
|
||||
/*global app, templates, utils*/
|
||||
@@ -23,7 +24,9 @@ var ajaxify = {};
|
||||
|
||||
window.onpopstate = function (event) {
|
||||
// "quiet": If set to true, will not call pushState
|
||||
if (event !== null && event.state && event.state.url !== undefined) ajaxify.go(event.state.url, null, null, true);
|
||||
if (event !== null && event.state && event.state.url !== undefined) {
|
||||
ajaxify.go(event.state.url, null, null, true);
|
||||
}
|
||||
};
|
||||
|
||||
var pagination;
|
||||
@@ -31,10 +34,13 @@ var ajaxify = {};
|
||||
ajaxify.go = function (url, callback, template, quiet) {
|
||||
// start: the following should be set like so: ajaxify.onchange(function(){}); where the code actually belongs
|
||||
$(window).off('scroll');
|
||||
app.enter_room('global');
|
||||
app.enterRoom('global');
|
||||
|
||||
pagination = pagination || document.getElementById('pagination');
|
||||
if (pagination) pagination.parentNode.style.display = 'none';
|
||||
if (pagination) {
|
||||
pagination.parentNode.style.display = 'none';
|
||||
}
|
||||
|
||||
window.onscroll = null;
|
||||
// end
|
||||
|
||||
@@ -61,13 +67,26 @@ var ajaxify = {};
|
||||
}
|
||||
|
||||
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
|
||||
if (quiet !== true) {
|
||||
//if (quiet !== true) {
|
||||
if (window.history && window.history.pushState) {
|
||||
window.history.pushState({
|
||||
"url": url
|
||||
}, url, RELATIVE_PATH + "/" + url);
|
||||
url: url
|
||||
}, url, RELATIVE_PATH + '/' + url);
|
||||
|
||||
$.ajax(RELATIVE_PATH + '/plugins/fireHook', {
|
||||
type: 'PUT',
|
||||
data: {
|
||||
_csrf: $('#csrf_token').val(),
|
||||
hook: 'page.load',
|
||||
args: {
|
||||
template: tpl_url,
|
||||
url: url,
|
||||
uid: app.uid
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
//}
|
||||
|
||||
translator.load(tpl_url);
|
||||
|
||||
@@ -76,18 +95,28 @@ var ajaxify = {};
|
||||
templates.flush();
|
||||
templates.load_template(function () {
|
||||
exec_body_scripts(content);
|
||||
require(['forum/' + tpl_url], function(script) {
|
||||
if (script && script.init) {
|
||||
script.init();
|
||||
}
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
jQuery('#content, #footer').stop(true, true).fadeIn(200, function () {
|
||||
app.processPage();
|
||||
|
||||
app.process_page();
|
||||
if (window.location.hash)
|
||||
jQuery('#content, #footer').stop(true, true).fadeIn(200, function () {
|
||||
if (window.location.hash) {
|
||||
hash = window.location.hash;
|
||||
if (hash)
|
||||
app.scrollToPost(hash.substr(1));
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
require(['forum/topic'], function(topic) {
|
||||
topic.scrollToPost(hash.substr(1))
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
utils.refreshTitle(url);
|
||||
@@ -101,20 +130,29 @@ var ajaxify = {};
|
||||
};
|
||||
|
||||
$('document').ready(function () {
|
||||
if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers
|
||||
if (!window.history || !window.history.pushState) {
|
||||
return; // no ajaxification for old browsers
|
||||
}
|
||||
|
||||
content = content || document.getElementById('content');
|
||||
|
||||
// Enhancing all anchors to ajaxify...
|
||||
$(document.body).on('click', 'a', function (e) {
|
||||
function hrefEmpty(href) {
|
||||
return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#";
|
||||
return href === 'javascript:;' || href === window.location.href + "#" || href.slice(-1) === "#";
|
||||
}
|
||||
|
||||
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:')
|
||||
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!window.location.pathname.match(/\/(403|404)$/g)) {
|
||||
app.previousUrl = window.location.href;
|
||||
}
|
||||
|
||||
if (this.getAttribute('data-ajaxify') === 'false') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && e.which === 1) {
|
||||
if (this.host === window.location.host) {
|
||||
@@ -127,10 +165,13 @@ var ajaxify = {};
|
||||
}
|
||||
} else if (window.location.pathname !== '/outgoing') {
|
||||
// External Link
|
||||
|
||||
if (config.useOutgoingLinksPage == true) {
|
||||
ajaxify.go('outgoing?url=' + encodeURIComponent(this.href));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -165,7 +206,7 @@ var ajaxify = {};
|
||||
|
||||
var scripts = [],
|
||||
script,
|
||||
children_nodes = $(body_el).children(),
|
||||
children_nodes = $(body_el).find('script'),
|
||||
child,
|
||||
i;
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
var socket,
|
||||
config,
|
||||
app = {};
|
||||
app = {
|
||||
'username': null,
|
||||
'uid': null
|
||||
};
|
||||
|
||||
(function () {
|
||||
var showWelcomeMessage = false;
|
||||
|
||||
|
||||
app.loadConfig = function() {
|
||||
|
||||
$.ajax({
|
||||
@@ -17,13 +21,20 @@ var socket,
|
||||
socket.socket.connect();
|
||||
}, 200);
|
||||
} else {
|
||||
socket = io.connect(config.socket.address);
|
||||
var max_reconnection_attemps = 5;
|
||||
var reconnection_delay = 200;
|
||||
socket = io.connect(RELATIVE_PATH, {
|
||||
'max reconnection attempts': max_reconnection_attemps,
|
||||
'reconnection delay': reconnection_delay
|
||||
});
|
||||
|
||||
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']
|
||||
@@ -53,7 +64,13 @@ var socket,
|
||||
socket.socket.connect();
|
||||
});
|
||||
|
||||
socket.on('reconnecting', function (data) {
|
||||
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;
|
||||
|
||||
@@ -97,13 +114,32 @@ var socket,
|
||||
});
|
||||
});
|
||||
|
||||
app.enter_room('global');
|
||||
socket.on('event:banned', function() {
|
||||
app.alert({
|
||||
title: 'Banned',
|
||||
message: 'You are banned you will be logged out!',
|
||||
type: 'warning',
|
||||
timeout: 1000
|
||||
});
|
||||
|
||||
setTimeout(app.logout, 1000);
|
||||
});
|
||||
|
||||
app.enterRoom('global');
|
||||
}
|
||||
},
|
||||
async: false
|
||||
});
|
||||
}
|
||||
|
||||
app.logout = function() {
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: $('#csrf_token').val()
|
||||
}, function() {
|
||||
window.location.reload(false);
|
||||
});
|
||||
}
|
||||
|
||||
// takes a string like 1000 and returns 1,000
|
||||
app.addCommas = function (text) {
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||
@@ -130,6 +166,7 @@ var socket,
|
||||
var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime());
|
||||
|
||||
var alert = $('#' + alert_id);
|
||||
var title = params.title || '';
|
||||
|
||||
function startTimeout(div, timeout) {
|
||||
var timeoutId = setTimeout(function () {
|
||||
@@ -142,50 +179,42 @@ var socket,
|
||||
}
|
||||
|
||||
if (alert.length > 0) {
|
||||
alert.find('strong').html(params.title);
|
||||
alert.find('strong').html(title);
|
||||
alert.find('p').html(params.message);
|
||||
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');
|
||||
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 " + "alert-" + params.type;
|
||||
|
||||
div.setAttribute('id', alert_id);
|
||||
div.appendChild(button);
|
||||
div.appendChild(strong);
|
||||
div.appendChild(p);
|
||||
|
||||
button.className = 'close';
|
||||
button.innerHTML = '×';
|
||||
button.onclick = function (ev) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
button.on('click', function () {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
if (params.location == null)
|
||||
params.location = 'alert_window';
|
||||
|
||||
jQuery('#' + params.location).prepend(jQuery(div).fadeIn('100'));
|
||||
$('#' + params.location).prepend(div.fadeIn('100'));
|
||||
|
||||
if (params.timeout) {
|
||||
startTimeout(div, params.timeout);
|
||||
}
|
||||
|
||||
if (params.clickfn) {
|
||||
div.onclick = function () {
|
||||
div.on('click', function () {
|
||||
params.clickfn();
|
||||
jQuery(div).fadeOut(500, function () {
|
||||
this.remove();
|
||||
div.fadeOut(500, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,22 +243,23 @@ var socket,
|
||||
});
|
||||
}
|
||||
|
||||
app.current_room = null;
|
||||
app.enter_room = function (room) {
|
||||
app.currentRoom = null;
|
||||
app.enterRoom = function (room) {
|
||||
if (socket) {
|
||||
if (app.current_room === room)
|
||||
if (app.currentRoom === room) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('event:enter_room', {
|
||||
'enter': room,
|
||||
'leave': app.current_room
|
||||
'leave': app.currentRoom
|
||||
});
|
||||
|
||||
app.current_room = room;
|
||||
app.currentRoom = room;
|
||||
}
|
||||
};
|
||||
|
||||
app.populate_online_users = function () {
|
||||
app.populateOnlineUsers = function () {
|
||||
var uids = [];
|
||||
|
||||
jQuery('.post-row').each(function () {
|
||||
@@ -239,17 +269,9 @@ var socket,
|
||||
socket.emit('api:user.get_online_users', uids);
|
||||
}
|
||||
|
||||
app.process_page = function () {
|
||||
|
||||
// here is where all modules' onNavigate should be called, I think.
|
||||
require(['mobileMenu'], function (mobileMenu) {
|
||||
mobileMenu.onNavigate();
|
||||
});
|
||||
|
||||
app.populate_online_users();
|
||||
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
function highlightNavigationLink() {
|
||||
var path = window.location.pathname,
|
||||
parts = path.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
|
||||
jQuery('#main-nav li').removeClass('active');
|
||||
@@ -264,9 +286,26 @@ var socket,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
app.createUserTooltips = function() {
|
||||
$('img[title].teaser-pic,img[title].user-img').each(function() {
|
||||
$(this).tooltip({
|
||||
placement: 'top',
|
||||
title: $(this).attr('title')
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
app.processPage = function () {
|
||||
app.populateOnlineUsers();
|
||||
|
||||
highlightNavigationLink();
|
||||
|
||||
$('span.timeago').timeago();
|
||||
$('.post-content img').addClass('img-responsive');
|
||||
|
||||
app.createUserTooltips();
|
||||
|
||||
setTimeout(function () {
|
||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||
@@ -300,6 +339,28 @@ var socket,
|
||||
}
|
||||
|
||||
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)) {
|
||||
@@ -308,57 +369,7 @@ var socket,
|
||||
chatModal = chat.getModal(touid);
|
||||
}
|
||||
chat.load(chatModal.attr('UUID'));
|
||||
});
|
||||
}
|
||||
|
||||
app.createNewPosts = function (data) {
|
||||
data.posts[0].display_moderator_tools = 'none';
|
||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var uniqueid = new Date().getTime(),
|
||||
tempContainer = jQuery('<div id="' + uniqueid + '"></div>')
|
||||
.appendTo("#post-container")
|
||||
.hide()
|
||||
.append(translatedHTML)
|
||||
.fadeIn('slow');
|
||||
|
||||
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
|
||||
socket.emit('api:post.privileges', data.posts[x].pid);
|
||||
}
|
||||
|
||||
tempContainer.replaceWith(tempContainer.contents());
|
||||
infiniteLoaderActive = false;
|
||||
|
||||
app.populate_online_users();
|
||||
app.addCommasToNumbers();
|
||||
$('span.timeago').timeago();
|
||||
});
|
||||
}
|
||||
|
||||
app.infiniteLoaderActive = false;
|
||||
|
||||
app.loadMorePosts = function (tid, callback) {
|
||||
if (app.infiniteLoaderActive)
|
||||
return;
|
||||
app.infiniteLoaderActive = true;
|
||||
|
||||
if ($('#loading-indicator').attr('done') === '0')
|
||||
$('#loading-indicator').removeClass('hide');
|
||||
|
||||
socket.emit('api:topic.loadMore', {
|
||||
tid: tid,
|
||||
after: document.querySelectorAll('#post-container li[data-pid]').length
|
||||
}, function (data) {
|
||||
app.infiniteLoaderActive = false;
|
||||
if (data.posts.length) {
|
||||
$('#loading-indicator').attr('done', '0');
|
||||
app.createNewPosts(data);
|
||||
} else {
|
||||
$('#loading-indicator').attr('done', '1');
|
||||
}
|
||||
$('#loading-indicator').addClass('hide');
|
||||
if (callback)
|
||||
callback(data.posts);
|
||||
chat.center(chatModal);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -374,43 +385,6 @@ var socket,
|
||||
});
|
||||
}
|
||||
|
||||
app.scrollToPost = function (pid) {
|
||||
|
||||
if (!pid)
|
||||
return;
|
||||
|
||||
var container = $(document.body),
|
||||
scrollTo = $('#post_anchor_' + pid),
|
||||
tid = $('#post-container').attr('data-tid');
|
||||
|
||||
function animateScroll() {
|
||||
$('body,html').animate({
|
||||
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
||||
}, 400);
|
||||
//$('body,html').scrollTop(scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height());
|
||||
}
|
||||
|
||||
if (!scrollTo.length && tid) {
|
||||
|
||||
var intervalID = setInterval(function () {
|
||||
app.loadMorePosts(tid, function (posts) {
|
||||
scrollTo = $('#post_anchor_' + pid);
|
||||
|
||||
if (tid && scrollTo.length) {
|
||||
animateScroll();
|
||||
}
|
||||
|
||||
if (!posts.length || scrollTo.length)
|
||||
clearInterval(intervalID);
|
||||
});
|
||||
}, 100);
|
||||
|
||||
} else if (tid) {
|
||||
animateScroll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
jQuery('document').ready(function () {
|
||||
$('#search-form').on('submit', function () {
|
||||
var input = $(this).find('input');
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var Account = {};
|
||||
|
||||
Account.init = function() {
|
||||
header.init();
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
isFollowing = templates.get('isFollowing');
|
||||
|
||||
$(document).ready(function() {
|
||||
var username = $('.account-username a').html();
|
||||
app.enter_room('user/' + theirid);
|
||||
app.enterRoom('user/' + theirid);
|
||||
|
||||
app.addCommasToNumbers();
|
||||
$('.user-recent-posts img').addClass('img-responsive');
|
||||
|
||||
var followBtn = $('#follow-btn');
|
||||
var unfollowBtn = $('#unfollow-btn');
|
||||
|
||||
if (yourid !== theirid) {
|
||||
if (yourid !== theirid && yourid !== "0") {
|
||||
if (isFollowing) {
|
||||
followBtn.hide();
|
||||
unfollowBtn.show();
|
||||
@@ -59,21 +65,9 @@
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
|
||||
var onlineStatus = $('.account-online-status');
|
||||
socket.on('api:user.isOnline', Account.handleUserOnline);
|
||||
|
||||
function handleUserOnline(data) {
|
||||
if (data.online) {
|
||||
onlineStatus.find('span span').text('online');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||
} else {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||
}
|
||||
}
|
||||
|
||||
socket.on('api:user.isOnline', handleUserOnline);
|
||||
|
||||
socket.emit('api:user.isOnline', theirid, 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);
|
||||
@@ -81,5 +75,19 @@
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
||||
Account.handleUserOnline = function(data) {
|
||||
var onlineStatus = $('.account-online-status');
|
||||
|
||||
if (data.online) {
|
||||
onlineStatus.find('span span').text('online');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||
} else {
|
||||
onlineStatus.find('span span').text('offline');
|
||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||
}
|
||||
};
|
||||
|
||||
return Account;
|
||||
});
|
||||
@@ -1,99 +1,12 @@
|
||||
define(['forum/accountheader', 'uploader'], function(header, uploader) {
|
||||
var AccountEdit = {};
|
||||
|
||||
AccountEdit.init = function() {
|
||||
header.init();
|
||||
|
||||
var gravatarPicture = templates.get('gravatarpicture');
|
||||
var uploadedPicture = templates.get('uploadedpicture');
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
|
||||
|
||||
$('#uploadForm').submit(function() {
|
||||
status('uploading the file ...');
|
||||
|
||||
$('#upload-progress-bar').css('width', '0%');
|
||||
$('#upload-progress-box').show();
|
||||
$('#upload-progress-box').removeClass('hide');
|
||||
|
||||
if (!$('#userPhotoInput').val()) {
|
||||
error('select an image to upload!');
|
||||
return false;
|
||||
}
|
||||
|
||||
$(this).find('#imageUploadCsrf').val($('#csrf_token').val());
|
||||
|
||||
|
||||
$(this).ajaxSubmit({
|
||||
|
||||
error: function(xhr) {
|
||||
error('Error: ' + xhr.status);
|
||||
},
|
||||
|
||||
uploadProgress: function(event, position, total, percent) {
|
||||
console.log(percent);
|
||||
$('#upload-progress-bar').css('width', percent + '%');
|
||||
},
|
||||
|
||||
|
||||
success: function(response) {
|
||||
if (response.error) {
|
||||
error(response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
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').addClass('hide');
|
||||
$('#alert-success').addClass('hide');
|
||||
$('#alert-error').addClass('hide');
|
||||
$('#upload-progress-box').addClass('hide');
|
||||
}
|
||||
|
||||
function status(message) {
|
||||
hideAlerts();
|
||||
$('#alert-status').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
function success(message) {
|
||||
hideAlerts();
|
||||
$('#alert-success').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
hideAlerts();
|
||||
$('#alert-error').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
function changeUserPicture(type) {
|
||||
var userData = {
|
||||
type: type
|
||||
};
|
||||
|
||||
socket.emit('api:user.changePicture', userData, function(success) {
|
||||
if (!success) {
|
||||
app.alertError('There was an error changing picture!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var selectedImageType = '';
|
||||
|
||||
$('#submitBtn').on('click', function() {
|
||||
@@ -126,37 +39,9 @@ $(document).ready(function() {
|
||||
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();
|
||||
AccountEdit.updateImages();
|
||||
|
||||
$('#change-picture-modal').modal('show');
|
||||
$('#change-picture-modal').removeClass('hide');
|
||||
@@ -180,7 +65,7 @@ $(document).ready(function() {
|
||||
$('#change-picture-modal').modal('hide');
|
||||
|
||||
if (selectedImageType) {
|
||||
changeUserPicture(selectedImageType);
|
||||
AccountEdit.changeUserPicture(selectedImageType);
|
||||
|
||||
if (selectedImageType == 'gravatar')
|
||||
$('#user-current-picture').attr('src', gravatarPicture);
|
||||
@@ -197,17 +82,21 @@ $(document).ready(function() {
|
||||
$('#uploadPictureBtn').on('click', function() {
|
||||
|
||||
$('#change-picture-modal').modal('hide');
|
||||
$('#upload-picture-modal').modal('show');
|
||||
$('#upload-picture-modal').removeClass('hide');
|
||||
uploader.open(config.relative_path + '/user/uploadpicture', function(imageUrlOnServer) {
|
||||
$('#user-current-picture').attr('src', imageUrlOnServer);
|
||||
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
|
||||
|
||||
uploadedPicture = imageUrlOnServer;
|
||||
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
});
|
||||
|
||||
hideAlerts();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#pictureUploadSubmitBtn').on('click', function() {
|
||||
$('#uploadForm').submit();
|
||||
});
|
||||
|
||||
(function handlePasswordChange() {
|
||||
var currentPassword = $('#inputCurrentPassword');
|
||||
@@ -288,4 +177,49 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
}());
|
||||
};
|
||||
|
||||
|
||||
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');
|
||||
var gravatarPicture = templates.get('gravatarpicture');
|
||||
var uploadedPicture = templates.get('uploadedpicture');
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return AccountEdit;
|
||||
});
|
||||
@@ -1,24 +1,11 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var AccountHeader = {};
|
||||
|
||||
AccountHeader.init = function() {
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid');
|
||||
|
||||
|
||||
function createMenu() {
|
||||
var userslug = $('.account-username-box').attr('data-userslug');
|
||||
var links = $('<div class="account-sub-links inline-block pull-right">\
|
||||
<span id="settingsLink" class="pull-right"><a href="/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);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
createMenu();
|
||||
AccountHeader.createMenu();
|
||||
|
||||
var editLink = $('#editLink');
|
||||
var settingsLink = $('#settingsLink');
|
||||
@@ -37,6 +24,20 @@
|
||||
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,4 +1,8 @@
|
||||
$(document).ready(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var AccountSettings = {};
|
||||
|
||||
AccountSettings.init = function() {
|
||||
header.init();
|
||||
|
||||
$('#submitBtn').on('click', function() {
|
||||
|
||||
@@ -15,5 +19,7 @@ $(document).ready(function() {
|
||||
});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return AccountSettings;
|
||||
});
|
||||
@@ -1,11 +1,16 @@
|
||||
define(function() {
|
||||
var Categories = {};
|
||||
|
||||
Categories.init = function() {
|
||||
var modified_categories = {};
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
socket.emit('api:admin.categories.update', modified_categories);
|
||||
@@ -24,6 +29,7 @@ function select_icon(el) {
|
||||
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
|
||||
el.attr('class', iconClass + ' icon-2x');
|
||||
el.val(iconClass);
|
||||
el.attr('value', iconClass);
|
||||
|
||||
modified(el);
|
||||
}
|
||||
@@ -42,14 +48,26 @@ function update_blockclass(el) {
|
||||
el.parentNode.parentNode.className = 'entry-row ' + el.value;
|
||||
}
|
||||
|
||||
jQuery('#entry-container').sortable();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
jQuery('#entry-container').sortable({
|
||||
stop: function( event, ui ) {
|
||||
updateCategoryOrders();
|
||||
}
|
||||
});
|
||||
jQuery('.blockclass').each(function() {
|
||||
jQuery(this).val(this.getAttribute('data-value'));
|
||||
});
|
||||
|
||||
|
||||
//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() {
|
||||
function showCreateCategoryModal() {
|
||||
$('#new-category-modal').modal();
|
||||
}
|
||||
@@ -58,7 +76,7 @@ jQuery('.blockclass').each(function() {
|
||||
var category = {
|
||||
name: $('#inputName').val(),
|
||||
description: $('#inputDescription').val(),
|
||||
icon: $('#new-category-modal i').attr('value'),
|
||||
icon: $('#new-category-modal i').val(),
|
||||
blockclass: $('#inputBlockclass').val()
|
||||
};
|
||||
|
||||
@@ -103,11 +121,15 @@ jQuery('.blockclass').each(function() {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
jQuery('#new-category-modal').on('click', '.icon', function(ev) {
|
||||
select_icon($(this).find('i'));
|
||||
});
|
||||
|
||||
jQuery('.blockclass').on('change', function(ev) {
|
||||
update_blockclass(ev.target);
|
||||
});
|
||||
|
||||
jQuery('.category_name, .category_description, .blockclass').on('change', function(ev) {
|
||||
jQuery('.category_name, .category_description, .blockclass .category_bgColor').on('change', function(ev) {
|
||||
modified(ev.target);
|
||||
});
|
||||
|
||||
@@ -120,7 +142,7 @@ jQuery('.blockclass').each(function() {
|
||||
|
||||
});
|
||||
|
||||
jQuery('.entry-row button').on('click', function(ev) {
|
||||
jQuery('#entry-container').on('click', '.disable-btn', function(ev) {
|
||||
var btn = jQuery(this);
|
||||
var categoryRow = btn.parents('li');
|
||||
var cid = categoryRow.attr('data-cid');
|
||||
@@ -134,6 +156,22 @@ jQuery('.blockclass').each(function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Colour Picker
|
||||
$('[data-name="bgColor"], [data-name="color"]').each(function(idx, inputEl) {
|
||||
var jinputEl = $(this),
|
||||
parentEl = jinputEl.parents('[data-cid]');
|
||||
jinputEl.ColorPicker({
|
||||
color: this.value || '#000',
|
||||
onChange: function(hsb, hex) {
|
||||
jinputEl.val('#' + hex);
|
||||
if (inputEl.getAttribute('data-name') === 'bgColor') parentEl.css('background', '#' + hex);
|
||||
else if (inputEl.getAttribute('data-name') === 'color') parentEl.css('color', '#' + hex);
|
||||
modified(inputEl);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
||||
return Categories;
|
||||
});
|
||||
@@ -1,78 +1,3 @@
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
socket.emit('api:config.set', {
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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'),
|
||||
@@ -91,7 +16,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
});
|
||||
|
||||
socket.once('api:config.get', function(config) {
|
||||
nodebb_admin.config = config;
|
||||
app.config = config;
|
||||
});
|
||||
|
||||
socket.emit('api:config.get');
|
||||
@@ -115,7 +40,3 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return nodebb_admin;
|
||||
|
||||
}(nodebb_admin || {}));
|
||||
@@ -1,4 +1,7 @@
|
||||
$(document).ready(function() {
|
||||
define(function() {
|
||||
var Groups = {};
|
||||
|
||||
Groups.init = function() {
|
||||
var createEl = document.getElementById('create'),
|
||||
createModal = $('#create-modal'),
|
||||
createSubmitBtn = document.getElementById('create-modal-go'),
|
||||
@@ -42,10 +45,12 @@ $(document).ready(function() {
|
||||
|
||||
errorEl.html(errorText).removeClass('hide');
|
||||
} else {
|
||||
createModal.modal('hide');
|
||||
errorEl.addClass('hide');
|
||||
createNameEl.val('');
|
||||
createModal.on('hidden.bs.modal', function() {
|
||||
ajaxify.go('admin/groups');
|
||||
});
|
||||
createModal.modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -186,9 +191,14 @@ $(document).ready(function() {
|
||||
}
|
||||
}, function(err) {
|
||||
if (!err) {
|
||||
detailsModal.modal('hide');
|
||||
detailsModal.on('hidden.bs.modal', function() {
|
||||
ajaxify.go('admin/groups');
|
||||
});
|
||||
detailsModal.modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return Groups;
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
define(function() {
|
||||
var Admin = {};
|
||||
|
||||
(function() {
|
||||
|
||||
Admin.init = function() {
|
||||
ajaxify.register_events(['api:get_all_rooms']);
|
||||
socket.on('api:get_all_rooms', function(data) {
|
||||
|
||||
@@ -19,7 +20,9 @@
|
||||
document.getElementById('connections').innerHTML = total;
|
||||
});
|
||||
|
||||
app.enter_room('admin');
|
||||
app.enterRoom('admin');
|
||||
socket.emit('api:get_all_rooms');
|
||||
};
|
||||
|
||||
}());
|
||||
return Admin;
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
var nodebb_admin = nodebb_admin || {};
|
||||
|
||||
(function() {
|
||||
var plugins = {
|
||||
define(function() {
|
||||
var Plugins = {
|
||||
init: function() {
|
||||
var pluginsList = $('.plugins'),
|
||||
numPlugins = pluginsList[0].querySelectorAll('li').length,
|
||||
@@ -31,8 +29,5 @@ var nodebb_admin = nodebb_admin || {};
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
nodebb_admin.plugins = plugins;
|
||||
nodebb_admin.plugins.init();
|
||||
return Plugins;
|
||||
});
|
||||
})();
|
||||
88
public/src/forum/admin/settings.js
Normal file
88
public/src/forum/admin/settings.js
Normal file
@@ -0,0 +1,88 @@
|
||||
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 = app.config[key] === '1' ? true : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (fields[x].nodeName === 'TEXTAREA') {
|
||||
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;
|
||||
}
|
||||
|
||||
socket.emit('api:config.set', {
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#uploadLogoBtn').on('click', function() {
|
||||
|
||||
uploader.open(config.relative_path + '/admin/uploadlogo', function(image) {
|
||||
$('#logoUrl').val(image);
|
||||
});
|
||||
|
||||
uploader.hideAlerts();
|
||||
});
|
||||
};
|
||||
|
||||
Settings.remove = function(key) {
|
||||
socket.emit('api:config.remove', key);
|
||||
};
|
||||
|
||||
return Settings;
|
||||
});
|
||||
@@ -1,43 +1,9 @@
|
||||
var nodebb_admin = (function(nodebb_admin) {
|
||||
define(function() {
|
||||
var Themes = {};
|
||||
|
||||
var themes = {};
|
||||
|
||||
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++) {
|
||||
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 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() {
|
||||
Themes.init = function() {
|
||||
var scriptEl = document.createElement('script');
|
||||
scriptEl.src = 'http://api.bootswatch.com/3/?callback=nodebb_admin.themes.render';
|
||||
scriptEl.src = 'http://api.bootswatch.com/3/?callback=bootswatchListener';
|
||||
document.body.appendChild(scriptEl);
|
||||
|
||||
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
||||
@@ -53,15 +19,22 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
break;
|
||||
case 'use':
|
||||
var parentEl = $(e.target).parents('li'),
|
||||
themeType = parentEl.attr('data-type'),
|
||||
cssSrc = parentEl.attr('data-css'),
|
||||
cssName = parentEl.attr('data-theme');
|
||||
socket.emit('api:config.set', {
|
||||
key: 'theme:id',
|
||||
value: 'bootswatch:' + cssName
|
||||
themeId = parentEl.attr('data-theme');
|
||||
|
||||
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
|
||||
});
|
||||
socket.emit('api:config.set', {
|
||||
key: 'theme:src',
|
||||
value: cssSrc
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -74,8 +47,18 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
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');
|
||||
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);
|
||||
@@ -85,12 +68,12 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
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.setAttribute('data-css', themes[x].src);
|
||||
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
|
||||
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> ' +
|
||||
@@ -115,4 +98,35 @@ var nodebb_admin = (function(nodebb_admin) {
|
||||
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;
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
return Themes;
|
||||
});
|
||||
@@ -1,7 +1,12 @@
|
||||
$(document).ready(function() {
|
||||
define(function() {
|
||||
var Topics = {};
|
||||
|
||||
Topics.init = function() {
|
||||
var topicsListEl = document.querySelector('.topics'),
|
||||
loadMoreEl = document.getElementById('topics_loadmore');
|
||||
|
||||
this.resolveButtonStates();
|
||||
|
||||
$(topicsListEl).on('click', '[data-action]', function() {
|
||||
var $this = $(this),
|
||||
action = this.getAttribute('data-action'),
|
||||
@@ -37,8 +42,13 @@ $(document).ready(function() {
|
||||
|
||||
loadMoreEl.addEventListener('click', function() {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
var topics = document.querySelectorAll('.topics li[data-tid]'),
|
||||
lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
|
||||
var topics = document.querySelectorAll('.topics li[data-tid]');
|
||||
|
||||
if(!topics.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
|
||||
|
||||
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
|
||||
socket.emit('api:admin.topics.getMore', {
|
||||
@@ -54,8 +64,15 @@ $(document).ready(function() {
|
||||
}),
|
||||
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';
|
||||
@@ -65,19 +82,6 @@ $(document).ready(function() {
|
||||
}
|
||||
}, false);
|
||||
|
||||
// Resolve proper button state for all topics
|
||||
var topicEls = topicsListEl.querySelectorAll('li'),
|
||||
numTopics = topicEls.length;
|
||||
for (var x = 0; x < numTopics; x++) {
|
||||
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
||||
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
|
||||
topicEls[x].removeAttribute('data-pinned');
|
||||
topicEls[x].removeAttribute('data-locked');
|
||||
topicEls[x].removeAttribute('data-deleted');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:topic.pin', function(response) {
|
||||
if (response.status === 'ok') {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
|
||||
@@ -115,6 +119,7 @@ socket.on('api:topic.delete', function(response) {
|
||||
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
|
||||
|
||||
$(btnEl).addClass('active');
|
||||
$(btnEl).siblings('[data-action="lock"]').addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -123,5 +128,31 @@ socket.on('api:topic.restore', function(response) {
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Topics;
|
||||
});
|
||||
@@ -1,5 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Users = {};
|
||||
|
||||
Users.init = function() {
|
||||
var yourid = templates.get('yourid');
|
||||
|
||||
function isUserAdmin(element) {
|
||||
@@ -166,5 +168,7 @@
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
||||
return Users;
|
||||
});
|
||||
@@ -1,70 +1,42 @@
|
||||
(function () {
|
||||
define(function () {
|
||||
var Category = {};
|
||||
|
||||
Category.init = 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'),
|
||||
twitterEl = jQuery('#twitter-intent'),
|
||||
facebookEl = jQuery('#facebook-share'),
|
||||
googleEl = jQuery('#google-share'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url'),
|
||||
loadingMoreTopics = false;
|
||||
|
||||
app.enter_room(room);
|
||||
app.enterRoom('category_' + cid);
|
||||
|
||||
twitterEl.addEventListener('click', function () {
|
||||
twitterEl.on('click', function () {
|
||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
facebookEl.addEventListener('click', function () {
|
||||
});
|
||||
facebookEl.on('click', function () {
|
||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
googleEl.addEventListener('click', function () {
|
||||
});
|
||||
googleEl.on('click', function () {
|
||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
}, false);
|
||||
});
|
||||
|
||||
var new_post = document.getElementById('new_post');
|
||||
new_post.onclick = function () {
|
||||
$('#new_post').on('click', function () {
|
||||
require(['composer'], function (cmp) {
|
||||
cmp.push(0, cid);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic'
|
||||
]);
|
||||
|
||||
function onNewTopic(data) {
|
||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||
topics: [data]
|
||||
}),
|
||||
topic = $(html),
|
||||
container = $('#topics-container'),
|
||||
topics = $('#topics-container').children(),
|
||||
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('.icon-pushpin').length)
|
||||
continue;
|
||||
topic.insertBefore(topics[x]);
|
||||
topic.hide().fadeIn('slow');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
container.append(topic);
|
||||
topic.hide().fadeIn('slow');
|
||||
}
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
$('#topics-container span.timeago').timeago();
|
||||
}
|
||||
|
||||
socket.on('event:new_topic', onNewTopic);
|
||||
socket.on('event:new_topic', Category.onNewTopic);
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
socket.on('api:categories.getRecentReplies', function (posts) {
|
||||
@@ -83,21 +55,82 @@
|
||||
li.setAttribute('data-pid', posts[i].pid);
|
||||
|
||||
|
||||
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded" src="' + posts[i].picture + '" class="" /></a>' +
|
||||
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded user-img" src="' + posts[i].picture + '" class="" /></a>' +
|
||||
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
|
||||
'<strong><span>'+ posts[i].username + '</span></strong>' +
|
||||
'<p>' +
|
||||
posts[i].content +
|
||||
'</p>' +
|
||||
'<p class="meta"><strong>' + posts[i].username + '</strong></span> -<span class="timeago" title="' + posts[i].relativeTime + '"></span></p>' +
|
||||
'</a>';
|
||||
'</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();
|
||||
});
|
||||
|
||||
function onTopicsLoaded(topics) {
|
||||
$(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]
|
||||
}),
|
||||
topic = $(html),
|
||||
container = $('#topics-container'),
|
||||
topics = $('#topics-container').children('.category-item'),
|
||||
numTopics = topics.length;
|
||||
|
||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||
jQuery('#category-no-topics').remove();
|
||||
|
||||
if (numTopics > 0) {
|
||||
for (var x = 0; x < numTopics; x++) {
|
||||
if ($(topics[x]).find('.icon-pushpin').length) {
|
||||
if(x === numTopics - 1) {
|
||||
topic.insertAfter(topics[x]);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -113,26 +146,18 @@
|
||||
}
|
||||
|
||||
|
||||
function loadMoreTopics(cid) {
|
||||
Category.loadMoreTopics = function(cid) {
|
||||
loadingMoreTopics = true;
|
||||
socket.emit('api:category.loadMore', {
|
||||
cid: cid,
|
||||
after: $('#topics-container').children().length
|
||||
after: $('#topics-container').children('.category-item').length
|
||||
}, function (data) {
|
||||
if (data.topics.length) {
|
||||
onTopicsLoaded(data.topics);
|
||||
Category.onTopicsLoaded(data.topics);
|
||||
}
|
||||
loadingMoreTopics = false;
|
||||
});
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function (ev) {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics(cid);
|
||||
}
|
||||
return Category;
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
@@ -1,7 +1,13 @@
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var AccountHeader = {};
|
||||
|
||||
AccountHeader.init = function() {
|
||||
header.init();
|
||||
|
||||
$('.user-favourite-posts .topic-row').on('click', function() {
|
||||
ajaxify.go($(this).attr('topic-url'));
|
||||
});
|
||||
};
|
||||
|
||||
return AccountHeader;
|
||||
});
|
||||
}());
|
||||
@@ -1,18 +1,20 @@
|
||||
(function() {
|
||||
define(['forum/accountheader'], function(header) {
|
||||
var Followers = {};
|
||||
|
||||
Followers.init = function() {
|
||||
header.init();
|
||||
|
||||
var yourid = templates.get('yourid'),
|
||||
theirid = templates.get('theirid'),
|
||||
followersCount = templates.get('followersCount');
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
if (parseInt(followersCount, 10) === 0) {
|
||||
$('#no-followers-notice').removeClass('hide');
|
||||
}
|
||||
|
||||
app.addCommasToNumbers();
|
||||
};
|
||||
|
||||
return Followers;
|
||||
});
|
||||
|
||||
|
||||
}());
|
||||
@@ -1,40 +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() {
|
||||
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() {
|
||||
var unfollowBtn = $(this);
|
||||
var followingUid = $(this).attr('followingUid');
|
||||
|
||||
socket.emit('api:user.unfollow', {
|
||||
uid: followingUid
|
||||
}, function(success) {
|
||||
var username = unfollowBtn.attr('data-username');
|
||||
if (success) {
|
||||
unfollowBtn.parent().remove();
|
||||
app.alertSuccess('You are no longer following ' + username + '!');
|
||||
} else {
|
||||
app.alertError('There was an error unfollowing ' + username + '!');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
app.addCommasToNumbers();
|
||||
};
|
||||
|
||||
return Following;
|
||||
});
|
||||
|
||||
|
||||
}());
|
||||
@@ -1,25 +1,4 @@
|
||||
(function() {
|
||||
var stats_users = document.getElementById('stats_users'),
|
||||
stats_topics = document.getElementById('stats_topics'),
|
||||
stats_posts = document.getElementById('stats_posts'),
|
||||
stats_online = document.getElementById('stats_online'),
|
||||
user_label = document.getElementById('user_label');
|
||||
|
||||
socket.emit('user.count', {});
|
||||
socket.on('user.count', function(data) {
|
||||
stats_users.innerHTML = data.count;
|
||||
});
|
||||
|
||||
socket.emit('post.stats');
|
||||
socket.on('post.stats', function(data) {
|
||||
stats_topics.innerHTML = data.topics;
|
||||
stats_posts.innerHTML = data.posts;
|
||||
});
|
||||
|
||||
socket.emit('api:user.active.get');
|
||||
socket.on('api:user.active.get', function(data) {
|
||||
stats_online.innerHTML = data.users;
|
||||
});
|
||||
|
||||
socket.emit('api:updateHeader', {
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
@@ -55,23 +34,16 @@
|
||||
$('#search-button').show();
|
||||
|
||||
var userLabel = loggedInMenu.find('#user_label');
|
||||
|
||||
if (userLabel.length) {
|
||||
if (data['userslug'])
|
||||
userLabel.attr('href', '/user/' + 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']);
|
||||
|
||||
$('#logout-link').on('click', function() {
|
||||
var csrf_token = $('#csrf_token').val();
|
||||
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: csrf_token
|
||||
}, function() {
|
||||
window.location = RELATIVE_PATH + '/';
|
||||
});
|
||||
});
|
||||
$('#logout-link').on('click', app.logout);
|
||||
}
|
||||
} else {
|
||||
$('#search-button').hide();
|
||||
@@ -84,7 +56,7 @@
|
||||
|
||||
}
|
||||
|
||||
$('#main-nav a,#right-menu a').off('click').on('click', function() {
|
||||
$('#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();
|
||||
});
|
||||
@@ -105,6 +77,7 @@
|
||||
numUnread = data.unread.length,
|
||||
x;
|
||||
notifList.innerHTML = '';
|
||||
console.log(data);
|
||||
if ((data.read.length + data.unread.length) > 0) {
|
||||
for (x = 0; x < numUnread; x++) {
|
||||
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
||||
@@ -119,9 +92,17 @@
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
notifEl.className = 'no-notifs';
|
||||
notifEl.innerHTML = '<a>You have no notifications</a>';
|
||||
notifFrag.appendChild(notifEl);
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
}
|
||||
|
||||
// Add dedicated link to /notifications
|
||||
notifEl.removeAttribute('data-nid');
|
||||
notifEl.className = 'pagelink';
|
||||
notifEl.innerHTML = '<a href="' + RELATIVE_PATH + '/notifications">See all Notifications</a>';
|
||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||
|
||||
notifList.appendChild(notifFrag);
|
||||
|
||||
if (data.unread.length > 0) notifIcon.className = 'icon-circle active';
|
||||
|
||||
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,4 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Login = {};
|
||||
|
||||
Login.init = function() {
|
||||
// Alternate Logins
|
||||
var altLoginEl = document.querySelector('.alt-logins');
|
||||
altLoginEl.addEventListener('click', function(e) {
|
||||
@@ -32,6 +35,11 @@
|
||||
$('#login-error-notify').show();
|
||||
} else {
|
||||
$('#login-error-notify').hide();
|
||||
|
||||
if(!app.previousUrl) {
|
||||
app.previousUrl = '/';
|
||||
}
|
||||
|
||||
if(app.previousUrl.indexOf('/reset/') != -1)
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
else
|
||||
@@ -57,4 +65,13 @@
|
||||
});
|
||||
|
||||
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,55 +1,86 @@
|
||||
(function() {
|
||||
var loadingMoreTopics = false;
|
||||
define(function() {
|
||||
var Recent = {};
|
||||
|
||||
app.enter_room('recent_posts');
|
||||
Recent.newTopicCount = 0;
|
||||
Recent.newPostCount = 0;
|
||||
Recent.loadingMoreTopics = false;
|
||||
|
||||
var active = '';
|
||||
|
||||
Recent.init = function() {
|
||||
app.enterRoom('recent_posts');
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic',
|
||||
'event:new_post'
|
||||
]);
|
||||
|
||||
var newTopicCount = 0,
|
||||
newPostCount = 0;
|
||||
|
||||
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).hide();
|
||||
$(this).addClass('hide');
|
||||
});
|
||||
|
||||
socket.on('event:new_topic', function(data) {
|
||||
|
||||
++newTopicCount;
|
||||
updateAlertText();
|
||||
++Recent.newTopicCount;
|
||||
Recent.updateAlertText();
|
||||
|
||||
});
|
||||
|
||||
function 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();
|
||||
});
|
||||
|
||||
function onTopicsLoaded(topics) {
|
||||
Recent.onTopicsLoaded = function(topics) {
|
||||
|
||||
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
|
||||
topics: topics
|
||||
@@ -59,27 +90,21 @@
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
}
|
||||
|
||||
function loadMoreTopics() {
|
||||
loadingMoreTopics = true;
|
||||
Recent.loadMoreTopics = function() {
|
||||
Recent.loadingMoreTopics = true;
|
||||
socket.emit('api:topics.loadMoreRecentTopics', {
|
||||
after: $('#topics-container').children().length
|
||||
after: $('#topics-container').children('li').length,
|
||||
term: active
|
||||
}, function(data) {
|
||||
if (data.topics && data.topics.length) {
|
||||
onTopicsLoaded(data.topics);
|
||||
Recent.onTopicsLoaded(data.topics);
|
||||
}
|
||||
loadingMoreTopics = false;
|
||||
Recent.loadingMoreTopics = false;
|
||||
});
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics();
|
||||
}
|
||||
return Recent;
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
@@ -1,4 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Register = {};
|
||||
|
||||
Register.init = function() {
|
||||
var username = $('#username'),
|
||||
password = $('#password'),
|
||||
password_confirm = $('#password-confirm'),
|
||||
@@ -58,7 +61,7 @@
|
||||
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())) {
|
||||
} else if (!utils.isUserNameValid(username.val()) || !utils.slugify(username.val())) {
|
||||
showError(username_notify, 'Invalid username!');
|
||||
} else {
|
||||
socket.emit('user.exists', {
|
||||
@@ -150,5 +153,7 @@
|
||||
register.on('click', function(e) {
|
||||
if (validateForm()) e.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
||||
return Register;
|
||||
});
|
||||
@@ -1,4 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var ResetPassword = {};
|
||||
|
||||
ResetPassword.init = function() {
|
||||
var inputEl = document.getElementById('email'),
|
||||
errorEl = document.getElementById('error'),
|
||||
errorTextEl = errorEl.querySelector('p');
|
||||
@@ -38,4 +41,7 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
};
|
||||
|
||||
return ResetPassword;
|
||||
});
|
||||
@@ -1,4 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var ResetCode = {};
|
||||
|
||||
ResetCode.init = function() {
|
||||
var reset_code = templates.get('reset_code');
|
||||
|
||||
var resetEl = document.getElementById('reset'),
|
||||
@@ -49,4 +52,7 @@
|
||||
$('#success').show();
|
||||
}
|
||||
});
|
||||
}());
|
||||
};
|
||||
|
||||
return ResetCode;
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Search = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
Search.init = function() {
|
||||
var searchQuery = $('#topics-container').attr('data-search-query');
|
||||
|
||||
$('.search-result-text').each(function() {
|
||||
@@ -19,6 +20,7 @@
|
||||
input.val('');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
||||
return Search;
|
||||
});
|
||||
@@ -1,4 +1,9 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Topic = {},
|
||||
infiniteLoaderActive = false;
|
||||
|
||||
|
||||
Topic.init = function() {
|
||||
var expose_tools = templates.get('expose_tools'),
|
||||
tid = templates.get('topic_id'),
|
||||
postListEl = document.getElementById('post-container'),
|
||||
@@ -8,17 +13,47 @@
|
||||
deleted: templates.get('deleted'),
|
||||
pinned: templates.get('pinned')
|
||||
},
|
||||
topic_name = templates.get('topic_name');
|
||||
topic_name = templates.get('topic_name'),
|
||||
twitter_url = templates.get('twitter-intent-url'),
|
||||
facebook_url = templates.get('facebook-share-url'),
|
||||
google_url = templates.get('google-share-url');
|
||||
|
||||
|
||||
function fixDeleteStateForPosts() {
|
||||
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
|
||||
for (var x = 0, numPosts = postEls.length; x < numPosts; x++) {
|
||||
if (postEls[x].getAttribute('data-deleted') === '1') {
|
||||
toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
|
||||
}
|
||||
postEls[x].removeAttribute('data-deleted');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
|
||||
app.addCommasToNumbers();
|
||||
|
||||
var room = 'topic_' + tid,
|
||||
adminTools = document.getElementById('thread-tools');
|
||||
app.enterRoom('topic_' + tid);
|
||||
|
||||
app.enter_room(room);
|
||||
if($('#post-container .sub-posts').length) {
|
||||
$('.topic-main-buttons').removeClass('hide').parent().removeClass('hide');
|
||||
}
|
||||
|
||||
$('.twitter-share').on('click', function () {
|
||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.facebook-share').on('click', function () {
|
||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.google-share').on('click', function () {
|
||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||
return false;
|
||||
});
|
||||
|
||||
// Resetting thread state
|
||||
if (thread_state.locked === '1') set_locked_state(true);
|
||||
@@ -27,16 +62,17 @@
|
||||
|
||||
if (expose_tools === '1') {
|
||||
var moveThreadModal = $('#move_thread_modal');
|
||||
|
||||
adminTools.style.visibility = 'inherit';
|
||||
$('.thread-tools').removeClass('hide');
|
||||
|
||||
// Add events to the thread tools
|
||||
$('#delete_thread').on('click', function(e) {
|
||||
$('.delete_thread').on('click', function(e) {
|
||||
if (thread_state.deleted !== '1') {
|
||||
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
|
||||
if (confirm) socket.emit('api:topic.delete', {
|
||||
if (confirm) {
|
||||
socket.emit('api:topic.delete', {
|
||||
tid: tid
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bootbox.confirm('Are you sure you want to restore this thread?', function(confirm) {
|
||||
@@ -48,7 +84,7 @@
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#lock_thread').on('click', function(e) {
|
||||
$('.lock_thread').on('click', function(e) {
|
||||
if (thread_state.locked !== '1') {
|
||||
socket.emit('api:topic.lock', {
|
||||
tid: tid
|
||||
@@ -61,7 +97,7 @@
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#pin_thread').on('click', function(e) {
|
||||
$('.pin_thread').on('click', function(e) {
|
||||
if (thread_state.pinned !== '1') {
|
||||
socket.emit('api:topic.pin', {
|
||||
tid: tid
|
||||
@@ -74,7 +110,7 @@
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#move_thread').on('click', function(e) {
|
||||
$('.move_thread').on('click', function(e) {
|
||||
moveThreadModal.modal('show');
|
||||
return false;
|
||||
});
|
||||
@@ -99,7 +135,7 @@
|
||||
categoriesEl.className = 'category-list';
|
||||
for (x = 0; x < numCategories; x++) {
|
||||
info = data.categories[x];
|
||||
categoryEl.className = info.blockclass;
|
||||
categoryEl.className = info.blockclass + (info.disabled === '1' ? ' disabled' : '');
|
||||
categoryEl.innerHTML = '<i class="' + info.icon + '"></i> ' + info.name;
|
||||
categoryEl.setAttribute('data-cid', info.cid);
|
||||
categoriesFrag.appendChild(categoryEl.cloneNode(true));
|
||||
@@ -156,12 +192,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Fix delete state for this thread's posts
|
||||
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
|
||||
for (var x = 0, numPosts = postEls.length; x < numPosts; x++) {
|
||||
if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
|
||||
postEls[x].removeAttribute('data-deleted');
|
||||
}
|
||||
fixDeleteStateForPosts();
|
||||
|
||||
|
||||
// Follow Thread State
|
||||
var followEl = $('.main-post .follow'),
|
||||
@@ -220,7 +252,7 @@
|
||||
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
|
||||
|
||||
if(bookmark) {
|
||||
app.scrollToPost(parseInt(bookmark, 10));
|
||||
Topic.scrollToPost(parseInt(bookmark, 10));
|
||||
}
|
||||
|
||||
$('#post-container').on('click', '.deleted', function(ev) {
|
||||
@@ -232,13 +264,15 @@
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||
|
||||
if ($(window).scrollTop() > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
|
||||
app.loadMorePosts(tid);
|
||||
if ($(window).scrollTop() > bottom && !infiniteLoaderActive && $('#post-container').children().length) {
|
||||
loadMorePosts(tid, function(posts) {
|
||||
fixDeleteStateForPosts();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var reply_fn = function() {
|
||||
$('.topic').on('click', '.post_reply', function() {
|
||||
var selectionText = '',
|
||||
selection = window.getSelection() || document.getSelection();
|
||||
|
||||
@@ -252,9 +286,7 @@
|
||||
cmp.push(tid, null, null, selectionText.length > 0 ? selectionText + '\n\n' : '');
|
||||
});
|
||||
}
|
||||
};
|
||||
$('#post-container').on('click', '.post_reply', reply_fn);
|
||||
$('#post_reply').on('click', reply_fn);
|
||||
});
|
||||
|
||||
$('#post-container').on('click', '.quote', function() {
|
||||
if (thread_state.locked !== '1') {
|
||||
@@ -281,12 +313,12 @@
|
||||
if (element.attr('class') == 'icon-star-empty') {
|
||||
socket.emit('api:posts.favourite', {
|
||||
pid: pid,
|
||||
room_id: app.current_room
|
||||
room_id: app.currentRoom
|
||||
});
|
||||
} else {
|
||||
socket.emit('api:posts.unfavourite', {
|
||||
pid: pid,
|
||||
room_id: app.current_room
|
||||
room_id: app.currentRoom
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -315,13 +347,25 @@
|
||||
confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?');
|
||||
|
||||
if (confirmDel) {
|
||||
deleteAction ?
|
||||
if(deleteAction) {
|
||||
socket.emit('api:posts.delete', {
|
||||
pid: pid
|
||||
}) :
|
||||
socket.emit('api:posts.restore', {
|
||||
pid: pid
|
||||
pid: pid,
|
||||
tid: tid
|
||||
}, function(err) {
|
||||
if(err) {
|
||||
return app.alertError('Can\'t delete post!');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
socket.emit('api:posts.restore', {
|
||||
pid: pid,
|
||||
tid: tid
|
||||
}, function(err) {
|
||||
if(err) {
|
||||
return app.alertError('Can\'t restore post!');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -329,9 +373,6 @@
|
||||
var username = $(this).parents('li.row').attr('data-username');
|
||||
var touid = $(this).parents('li.row').attr('data-uid');
|
||||
|
||||
if (username === app.username || !app.username)
|
||||
return;
|
||||
|
||||
app.openChat(username, touid);
|
||||
});
|
||||
|
||||
@@ -345,11 +386,84 @@
|
||||
|
||||
|
||||
socket.on('api:get_users_in_room', function(data) {
|
||||
var activeEl = $('#thread_active_users');
|
||||
if (activeEl.length)
|
||||
activeEl.html(data);
|
||||
if(data) {
|
||||
var activeEl = $('.thread_active_users');
|
||||
|
||||
app.populate_online_users();
|
||||
function createUserIcon(uid, picture, userslug, username) {
|
||||
if(!activeEl.find("[href='/user/"+ data.users[i].userslug + "']").length) {
|
||||
var userIcon = $('<img src="'+ picture +'"/>');
|
||||
|
||||
var userLink = $('<a href="/user/' + userslug + '"></a>').append(userIcon);
|
||||
userLink.attr('data-uid', uid);
|
||||
|
||||
var div = $('<div class="inline-block"></div>');
|
||||
div.append(userLink);
|
||||
|
||||
userLink.tooltip({
|
||||
placement: 'top',
|
||||
title: username
|
||||
});
|
||||
|
||||
return div;
|
||||
}
|
||||
}
|
||||
|
||||
// remove users that are no longer here
|
||||
activeEl.children().each(function(index, element) {
|
||||
if(element) {
|
||||
var uid = $(element).attr('data-uid');
|
||||
for(var i=0; i<data.users.length; ++i) {
|
||||
if(data.users[i].uid == uid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$(element).remove();
|
||||
}
|
||||
});
|
||||
|
||||
var i=0;
|
||||
// add self
|
||||
for(i = 0; i<data.users.length; ++i) {
|
||||
if(data.users[i].uid == app.uid) {
|
||||
var icon = createUserIcon(data.users[i].uid, data.users[i].picture, data.users[i].userslug, data.users[i].username);
|
||||
activeEl.prepend(icon);
|
||||
data.users.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add other users
|
||||
for(i=0; i<data.users.length; ++i) {
|
||||
icon = createUserIcon(data.users[i].uid, data.users[i].picture, data.users[i].userslug, data.users[i].username)
|
||||
activeEl.append(icon);
|
||||
if(activeEl.children().length > 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var remainingUsers = data.users.length - 9;
|
||||
remainingUsers = remainingUsers < 0 ? 0 : remainingUsers;
|
||||
var anonymousCount = parseInt(data.anonymousCount, 10);
|
||||
activeEl.find('.anonymous-box').remove();
|
||||
if(anonymousCount || remainingUsers) {
|
||||
|
||||
var anonLink = $('<div class="anonymous-box inline-block"><i class="icon-user"></i></div>');
|
||||
activeEl.append(anonLink);
|
||||
|
||||
var title = '';
|
||||
if(remainingUsers && anonymousCount)
|
||||
title = remainingUsers + ' more user(s) and ' + anonymousCount + ' guest(s)';
|
||||
else if(remainingUsers)
|
||||
title = remainingUsers + ' more user(s)';
|
||||
else
|
||||
title = anonymousCount + ' guest(s)';
|
||||
|
||||
anonLink.tooltip({
|
||||
placement: 'top',
|
||||
title: title
|
||||
});
|
||||
}
|
||||
}
|
||||
app.populateOnlineUsers();
|
||||
});
|
||||
|
||||
socket.on('event:rep_up', function(data) {
|
||||
@@ -360,7 +474,7 @@
|
||||
adjust_rep(-1, data.pid, data.uid);
|
||||
});
|
||||
|
||||
socket.on('event:new_post', app.createNewPosts);
|
||||
socket.on('event:new_post', createNewPosts);
|
||||
|
||||
socket.on('event:topic_deleted', function(data) {
|
||||
if (data.tid === tid && data.status === 'ok') {
|
||||
@@ -444,15 +558,19 @@
|
||||
});
|
||||
|
||||
socket.on('event:post_deleted', function(data) {
|
||||
if (data.pid) toggle_post_delete_state(data.pid, true);
|
||||
if (data.pid) {
|
||||
toggle_post_delete_state(data.pid);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('event:post_restored', function(data) {
|
||||
if (data.pid) toggle_post_delete_state(data.pid, true);
|
||||
if (data.pid) {
|
||||
toggle_post_delete_state(data.pid);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:post.privileges', function(privileges) {
|
||||
if (privileges.editable) toggle_mod_tools(privileges.pid, true);
|
||||
toggle_mod_tools(privileges.pid, privileges.editable);
|
||||
});
|
||||
|
||||
function adjust_rep(value, pid, uid) {
|
||||
@@ -470,19 +588,19 @@
|
||||
}
|
||||
|
||||
function set_locked_state(locked, alert) {
|
||||
var threadReplyBtn = document.getElementById('post_reply'),
|
||||
var threadReplyBtn = $('.topic-main-buttons .post_reply'),
|
||||
postReplyBtns = document.querySelectorAll('#post-container .post_reply'),
|
||||
quoteBtns = document.querySelectorAll('#post-container .quote'),
|
||||
editBtns = document.querySelectorAll('#post-container .edit'),
|
||||
deleteBtns = document.querySelectorAll('#post-container .delete'),
|
||||
numPosts = document.querySelectorAll('#post_container li[data-pid]').length,
|
||||
lockThreadEl = document.getElementById('lock_thread'),
|
||||
lockThreadEl = $('.lock_thread'),
|
||||
x;
|
||||
|
||||
if (locked === true) {
|
||||
lockThreadEl.innerHTML = '<i class="icon-unlock"></i> Unlock Thread';
|
||||
threadReplyBtn.disabled = true;
|
||||
threadReplyBtn.innerHTML = 'Locked <i class="icon-lock"></i>';
|
||||
lockThreadEl.html('<i class="icon-unlock"></i> Unlock Thread');
|
||||
threadReplyBtn.attr('disabled', true);
|
||||
threadReplyBtn.html('Locked <i class="icon-lock"></i>');
|
||||
for (x = 0; x < numPosts; x++) {
|
||||
postReplyBtns[x].innerHTML = 'Locked <i class="icon-lock"></i>';
|
||||
quoteBtns[x].style.display = 'none';
|
||||
@@ -502,9 +620,9 @@
|
||||
|
||||
thread_state.locked = '1';
|
||||
} else {
|
||||
lockThreadEl.innerHTML = '<i class="icon-lock"></i> Lock Thread';
|
||||
threadReplyBtn.disabled = false;
|
||||
threadReplyBtn.innerHTML = 'Reply';
|
||||
lockThreadEl.html('<i class="icon-lock"></i> Lock Thread');
|
||||
threadReplyBtn.attr('disabled', false);
|
||||
threadReplyBtn.html('Reply');
|
||||
for (x = 0; x < numPosts; x++) {
|
||||
postReplyBtns[x].innerHTML = 'Reply <i class="icon-reply"></i>';
|
||||
quoteBtns[x].style.display = 'inline-block';
|
||||
@@ -527,13 +645,14 @@
|
||||
}
|
||||
|
||||
function set_delete_state(deleted) {
|
||||
var deleteThreadEl = document.getElementById('delete_thread'),
|
||||
deleteTextEl = deleteThreadEl.getElementsByTagName('span')[0],
|
||||
var deleteThreadEl = $('.delete_thread'),
|
||||
deleteTextEl = $('.delete_thread span'),
|
||||
//deleteThreadEl.getElementsByTagName('span')[0],
|
||||
threadEl = $('#post-container'),
|
||||
deleteNotice = document.getElementById('thread-deleted') || document.createElement('div');
|
||||
|
||||
if (deleted) {
|
||||
deleteTextEl.innerHTML = '<i class="icon-comment"></i> Restore Thread';
|
||||
deleteTextEl.html('<i class="icon-comment"></i> Restore Thread');
|
||||
threadEl.addClass('deleted');
|
||||
|
||||
// Spawn a 'deleted' notice at the top of the page
|
||||
@@ -544,7 +663,7 @@
|
||||
|
||||
thread_state.deleted = '1';
|
||||
} else {
|
||||
deleteTextEl.innerHTML = '<i class="icon-trash"></i> Delete Thread';
|
||||
deleteTextEl.html('<i class="icon-trash"></i> Delete Thread');
|
||||
threadEl.removeClass('deleted');
|
||||
deleteNotice.parentNode.removeChild(deleteNotice);
|
||||
|
||||
@@ -553,10 +672,10 @@
|
||||
}
|
||||
|
||||
function set_pinned_state(pinned, alert) {
|
||||
var pinEl = document.getElementById('pin_thread');
|
||||
var pinEl = $('.pin_thread');
|
||||
|
||||
if (pinned) {
|
||||
pinEl.innerHTML = '<i class="icon-pushpin"></i> Unpin Thread';
|
||||
pinEl.html('<i class="icon-pushpin"></i> Unpin Thread');
|
||||
if (alert) {
|
||||
app.alert({
|
||||
'alert_id': 'thread_pin',
|
||||
@@ -569,7 +688,7 @@
|
||||
|
||||
thread_state.pinned = '1';
|
||||
} else {
|
||||
pinEl.innerHTML = '<i class="icon-pushpin"></i> Pin Thread';
|
||||
pinEl.html('<i class="icon-pushpin"></i> Pin Thread');
|
||||
if (alert) {
|
||||
app.alert({
|
||||
'alert_id': 'thread_pin',
|
||||
@@ -606,6 +725,7 @@
|
||||
} else {
|
||||
postEl.toggleClass('none');
|
||||
}
|
||||
updatePostCount();
|
||||
});
|
||||
socket.emit('api:post.privileges', pid);
|
||||
}
|
||||
@@ -713,4 +833,140 @@
|
||||
|
||||
window.onscroll = updateHeader;
|
||||
window.onload = updateHeader;
|
||||
})();
|
||||
};
|
||||
|
||||
Topic.scrollToPost = function(pid) {
|
||||
if (!pid) {
|
||||
return;
|
||||
}
|
||||
|
||||
var container = $(document.body),
|
||||
scrollTo = $('#post_anchor_' + pid),
|
||||
tid = $('#post-container').attr('data-tid');
|
||||
|
||||
function animateScroll() {
|
||||
$('body,html').animate({
|
||||
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
||||
}, 400);
|
||||
}
|
||||
|
||||
if (!scrollTo.length && tid) {
|
||||
|
||||
var intervalID = setInterval(function () {
|
||||
loadMorePosts(tid, function (posts) {
|
||||
scrollTo = $('#post_anchor_' + pid);
|
||||
|
||||
if (tid && scrollTo.length) {
|
||||
animateScroll();
|
||||
}
|
||||
|
||||
if (!posts.length || scrollTo.length)
|
||||
clearInterval(intervalID);
|
||||
});
|
||||
}, 100);
|
||||
|
||||
} else if (tid) {
|
||||
animateScroll();
|
||||
}
|
||||
}
|
||||
|
||||
function createNewPosts(data, infiniteLoaded) {
|
||||
if(!data || (data.posts && !data.posts.length))
|
||||
return;
|
||||
|
||||
if (data.posts[0].uid !== app.uid) {
|
||||
data.posts[0].display_moderator_tools = 'none';
|
||||
}
|
||||
|
||||
function removeAlreadyAddedPosts() {
|
||||
data.posts = data.posts.filter(function(post) {
|
||||
return $('#post-container li[data-pid="' + post.pid +'"]').length === 0;
|
||||
});
|
||||
}
|
||||
|
||||
function findInsertionPoint() {
|
||||
var after = null,
|
||||
firstPid = data.posts[0].pid;
|
||||
$('#post-container li[data-pid]').each(function() {
|
||||
if(parseInt(firstPid, 10) > parseInt($(this).attr('data-pid'), 10)) {
|
||||
after = $(this);
|
||||
if(after.hasClass('main-post')) {
|
||||
after = after.next();
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return after;
|
||||
}
|
||||
|
||||
removeAlreadyAddedPosts();
|
||||
if(!data.posts.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var insertAfter = findInsertionPoint();
|
||||
|
||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var translated = $(translatedHTML);
|
||||
if(!infiniteLoaded) {
|
||||
translated.removeClass('infiniteloaded');
|
||||
}
|
||||
|
||||
translated.insertAfter(insertAfter)
|
||||
.hide()
|
||||
.fadeIn('slow');
|
||||
|
||||
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
|
||||
socket.emit('api:post.privileges', data.posts[x].pid);
|
||||
}
|
||||
|
||||
infiniteLoaderActive = false;
|
||||
|
||||
app.populateOnlineUsers();
|
||||
app.addCommasToNumbers();
|
||||
$('span.timeago').timeago();
|
||||
$('.post-content img').addClass('img-responsive');
|
||||
updatePostCount();
|
||||
});
|
||||
}
|
||||
|
||||
function updatePostCount() {
|
||||
$('#topic-post-count').html($('#post-container li[data-pid]:not(.deleted)').length);
|
||||
}
|
||||
|
||||
function loadMorePosts(tid, callback) {
|
||||
var indicatorEl = $('.loading-indicator');
|
||||
|
||||
if (infiniteLoaderActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
infiniteLoaderActive = true;
|
||||
|
||||
if (indicatorEl.attr('done') === '0') {
|
||||
indicatorEl.fadeIn();
|
||||
}
|
||||
|
||||
socket.emit('api:topic.loadMore', {
|
||||
tid: tid,
|
||||
after: $('#post-container .post-row.infiniteloaded').length
|
||||
}, function (data) {
|
||||
infiniteLoaderActive = false;
|
||||
if (data.posts.length) {
|
||||
indicatorEl.attr('done', '0');
|
||||
createNewPosts(data, true);
|
||||
} else {
|
||||
indicatorEl.attr('done', '1');
|
||||
}
|
||||
indicatorEl.fadeOut();
|
||||
if (callback) {
|
||||
callback(data.posts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Topic;
|
||||
});
|
||||
@@ -1,4 +1,7 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Unread = {};
|
||||
|
||||
Unread.init = function() {
|
||||
var loadingMoreTopics = false;
|
||||
|
||||
app.enter_room('recent_posts');
|
||||
@@ -12,7 +15,7 @@
|
||||
newPostCount = 0;
|
||||
|
||||
$('#new-topics-alert').on('click', function() {
|
||||
$(this).hide();
|
||||
$(this).addClass('hide');
|
||||
});
|
||||
|
||||
socket.on('event:new_topic', function(data) {
|
||||
@@ -41,7 +44,8 @@
|
||||
|
||||
text += ' Click here to reload.';
|
||||
|
||||
$('#new-topics-alert').html(text).fadeIn('slow');
|
||||
$('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow');
|
||||
$('#category-no-topics').addClass('hidden');
|
||||
}
|
||||
|
||||
socket.on('event:new_post', function(data) {
|
||||
@@ -77,6 +81,7 @@
|
||||
$('#category-no-topics').remove();
|
||||
|
||||
container.append(html);
|
||||
$('span.timeago').timeago();
|
||||
}
|
||||
|
||||
function loadMoreTopics() {
|
||||
@@ -110,5 +115,7 @@
|
||||
$('#load-more-btn').on('click', function() {
|
||||
loadMoreTopics();
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
||||
return Unread;
|
||||
});
|
||||
@@ -1,12 +1,18 @@
|
||||
(function() {
|
||||
define(function() {
|
||||
var Users = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
Users.init = function() {
|
||||
var timeoutId = 0;
|
||||
var loadingMoreUsers = false;
|
||||
|
||||
function getActiveSection() {
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
active = parts[parts.length - 1];
|
||||
return active;
|
||||
}
|
||||
|
||||
var active = getActiveSection();
|
||||
|
||||
var lastSearch = null;
|
||||
|
||||
@@ -59,9 +65,9 @@
|
||||
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
||||
users: data
|
||||
}),
|
||||
userListEl = document.querySelector('#users-container');
|
||||
userListEl = $('#users-container');
|
||||
|
||||
userListEl.innerHTML = html;
|
||||
userListEl.html(html);
|
||||
|
||||
|
||||
if (data && data.length === 0) {
|
||||
@@ -75,17 +81,27 @@
|
||||
});
|
||||
|
||||
socket.on('api:user.isOnline', function(data) {
|
||||
if(active == 'online' && !loadingMoreUsers) {
|
||||
$('#users-container').empty();
|
||||
startLoading('users:online', 0);
|
||||
if(getActiveSection() == 'online' && !loadingMoreUsers) {
|
||||
startLoading('users:online', 0, true);
|
||||
socket.emit('api:user.getOnlineAnonCount', {} , function(anonCount) {
|
||||
if(parseInt(anonCount, 10) > 0) {
|
||||
$('#users-container .anon-user').removeClass('hide');
|
||||
$('#online_anon_count').html(anonCount);
|
||||
} else {
|
||||
$('#users-container .anon-user').addClass('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
function onUsersLoaded(users, emptyContainer) {
|
||||
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
||||
users: users
|
||||
});
|
||||
if(emptyContainer)
|
||||
$('#users-container .registered-user').remove();
|
||||
$('#users-container').append(html);
|
||||
$('#users-container .anon-user').appendTo($('#users-container'));
|
||||
}
|
||||
|
||||
function loadMoreUsers() {
|
||||
@@ -101,18 +117,18 @@
|
||||
}
|
||||
|
||||
if (set) {
|
||||
startLoading(set, $('#users-container').children().length);
|
||||
startLoading(set, $('#users-container').children('.registered-user').length);
|
||||
}
|
||||
}
|
||||
|
||||
function startLoading(set, after) {
|
||||
function startLoading(set, after, emptyContainer) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: after
|
||||
}, function(data) {
|
||||
if (data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
onUsersLoaded(data.users, emptyContainer);
|
||||
$('#load-more-users-btn').removeClass('disabled');
|
||||
} else {
|
||||
$('#load-more-users-btn').addClass('disabled');
|
||||
@@ -131,6 +147,7 @@
|
||||
loadMoreUsers();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
||||
return Users;
|
||||
});
|
||||
@@ -85,6 +85,13 @@ define(['taskbar'], function(taskbar) {
|
||||
return chatModal;
|
||||
}
|
||||
|
||||
module.center = function(chatModal) {
|
||||
chatModal.css("position", "fixed");
|
||||
chatModal.css("top", "100px");
|
||||
chatModal.css("left", Math.max(0, (($(window).width() - $(chatModal).outerWidth()) / 2) + $(window).scrollLeft()) + "px");
|
||||
return chatModal;
|
||||
}
|
||||
|
||||
module.load = function(uuid) {
|
||||
var chatModal = $('div[UUID="'+uuid+'"]');
|
||||
chatModal.show();
|
||||
|
||||
@@ -150,7 +150,8 @@ define(['taskbar'], function(taskbar) {
|
||||
cid: threadData.cid,
|
||||
pid: threadData.pid,
|
||||
title: threadData.title || '',
|
||||
body: threadData.body || ''
|
||||
body: threadData.body || '',
|
||||
modified: false
|
||||
};
|
||||
composer.load(uuid);
|
||||
} else {
|
||||
@@ -179,6 +180,9 @@ define(['taskbar'], function(taskbar) {
|
||||
var uuid = $(this).parents('.post-window')[0].getAttribute('data-uuid');
|
||||
if (this.nodeName === 'INPUT') composer.posts[uuid].title = this.value;
|
||||
else if (this.nodeName === 'TEXTAREA') composer.posts[uuid].body = this.value;
|
||||
|
||||
// Mark this post window as having been changed
|
||||
composer.posts[uuid].modified = true;
|
||||
});
|
||||
|
||||
jPostContainer.on('click', '.action-bar button', function() {
|
||||
@@ -188,7 +192,7 @@ define(['taskbar'], function(taskbar) {
|
||||
case 'post': composer.post(uuid); break;
|
||||
case 'minimize': composer.minimize(uuid); break;
|
||||
case 'discard':
|
||||
if (postContentEl.value.length > 0) {
|
||||
if (composer.posts[uuid].modified) {
|
||||
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
|
||||
if (discard) composer.discard(uuid);
|
||||
});
|
||||
@@ -206,13 +210,17 @@ define(['taskbar'], function(taskbar) {
|
||||
selectionEnd = postContentEl.selectionEnd,
|
||||
selectionLength = selectionEnd - selectionStart;
|
||||
|
||||
function insertIntoInput(element, value) {
|
||||
var start = postContentEl.selectionStart;
|
||||
element.value = element.value.slice(0, start) + value + element.value.slice(start, element.value.length);
|
||||
postContentEl.selectionStart = postContentEl.selectionEnd = start + value.length;
|
||||
}
|
||||
|
||||
switch(iconClass) {
|
||||
case 'icon-bold':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
postContentEl.value = postContentEl.value + '**bolded text**';
|
||||
postContentEl.selectionStart = cursorEnd+2;
|
||||
postContentEl.selectionEnd = postContentEl.value.length - 2;
|
||||
insertIntoInput(postContentEl, "**bolded text**");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '**' + postContentEl.value.slice(selectionStart, selectionEnd) + '**' + postContentEl.value.slice(selectionEnd);
|
||||
@@ -223,9 +231,7 @@ define(['taskbar'], function(taskbar) {
|
||||
case 'icon-italic':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
postContentEl.value = postContentEl.value + '*italicised text*';
|
||||
postContentEl.selectionStart = cursorEnd+1;
|
||||
postContentEl.selectionEnd = postContentEl.value.length - 1;
|
||||
insertIntoInput(postContentEl, "*italicised text*");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '*' + postContentEl.value.slice(selectionStart, selectionEnd) + '*' + postContentEl.value.slice(selectionEnd);
|
||||
@@ -235,16 +241,12 @@ define(['taskbar'], function(taskbar) {
|
||||
break;
|
||||
case 'icon-list':
|
||||
// Nothing selected
|
||||
postContentEl.value = postContentEl.value + "\n\n* list item";
|
||||
postContentEl.selectionStart = cursorEnd+4;
|
||||
postContentEl.selectionEnd = postContentEl.value.length;
|
||||
insertIntoInput(postContentEl, "\n\n* list item");
|
||||
break;
|
||||
case 'icon-link':
|
||||
if (selectionStart === selectionEnd) {
|
||||
// Nothing selected
|
||||
postContentEl.value = postContentEl.value + '[link text](link url)';
|
||||
postContentEl.selectionStart = cursorEnd+12;
|
||||
postContentEl.selectionEnd = postContentEl.value.length - 1;
|
||||
insertIntoInput(postContentEl, "[link text](link url)");
|
||||
} else {
|
||||
// Text selected
|
||||
postContentEl.value = postContentEl.value.slice(0, selectionStart) + '[' + postContentEl.value.slice(selectionStart, selectionEnd) + '](link url)' + postContentEl.value.slice(selectionEnd);
|
||||
@@ -254,6 +256,7 @@ define(['taskbar'], function(taskbar) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
if (composer.active !== undefined) composer.reposition(composer.active);
|
||||
});
|
||||
@@ -384,6 +387,7 @@ define(['taskbar'], function(taskbar) {
|
||||
if (composer.posts[post_uuid]) {
|
||||
$(composer.postContainer).find('.imagedrop').hide();
|
||||
delete composer.posts[post_uuid];
|
||||
uploadsInProgress.length = 0;
|
||||
composer.minimize();
|
||||
taskbar.discard('composer', post_uuid);
|
||||
}
|
||||
|
||||
83
public/src/modules/uploader.js
Normal file
83
public/src/modules/uploader.js
Normal file
@@ -0,0 +1,83 @@
|
||||
define(function() {
|
||||
|
||||
var module = {};
|
||||
|
||||
module.open = function(route, callback) {
|
||||
$('#upload-picture-modal').modal('show').removeClass('hide');
|
||||
module.hideAlerts();
|
||||
|
||||
$('#uploadForm')[0].reset();
|
||||
$('#uploadForm').attr('action', route);
|
||||
|
||||
$('#pictureUploadSubmitBtn').off('click').on('click', function() {
|
||||
$('#uploadForm').submit();
|
||||
});
|
||||
|
||||
$('#uploadForm').off('submit').submit(function() {
|
||||
|
||||
function status(message) {
|
||||
module.hideAlerts();
|
||||
$('#alert-status').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
function success(message) {
|
||||
module.hideAlerts();
|
||||
$('#alert-success').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
module.hideAlerts();
|
||||
$('#alert-error').text(message).removeClass('hide');
|
||||
}
|
||||
|
||||
status('uploading the file ...');
|
||||
|
||||
$('#upload-progress-bar').css('width', '0%');
|
||||
$('#upload-progress-box').show().removeClass('hide');
|
||||
|
||||
if (!$('#userPhotoInput').val()) {
|
||||
error('select an image to upload!');
|
||||
return false;
|
||||
}
|
||||
|
||||
$(this).find('#imageUploadCsrf').val($('#csrf_token').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;
|
||||
}
|
||||
callback(response.path);
|
||||
|
||||
success('File uploaded successfully!');
|
||||
setTimeout(function() {
|
||||
module.hideAlerts();
|
||||
$('#upload-picture-modal').modal('hide');
|
||||
}, 750);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
module.hideAlerts = function() {
|
||||
$('#alert-status').addClass('hide');
|
||||
$('#alert-success').addClass('hide');
|
||||
$('#alert-error').addClass('hide');
|
||||
$('#upload-progress-box').addClass('hide');
|
||||
}
|
||||
|
||||
return module;
|
||||
});
|
||||
@@ -57,13 +57,14 @@
|
||||
return template;
|
||||
};
|
||||
|
||||
function loadTemplates(templatesToLoad) {
|
||||
function loadTemplates(templatesToLoad, customTemplateDir) {
|
||||
function loadServer() {
|
||||
var loaded = templatesToLoad.length;
|
||||
|
||||
function getTemplates(directory) {
|
||||
for (var t in templatesToLoad) {
|
||||
(function (file) {
|
||||
fs.readFile(__dirname + '/../templates/' + file + '.tpl', function (err, html) {
|
||||
fs.readFile(directory + '/' + file + '.tpl', function (err, html) {
|
||||
var template = function () {
|
||||
this.toString = function () {
|
||||
return this.html;
|
||||
@@ -82,6 +83,16 @@
|
||||
}(templatesToLoad[t]));
|
||||
}
|
||||
}
|
||||
if (customTemplateDir) {
|
||||
fs.exists(customTemplateDir, function (exists) {
|
||||
var directory = (exists ? customTemplateDir : __dirname + '/../templates');
|
||||
getTemplates(directory);
|
||||
});
|
||||
} else {
|
||||
getTemplates(__dirname + '/../templates');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadClient() {
|
||||
jQuery.when(jQuery.getJSON(RELATIVE_PATH + '/templates/config.json'), jQuery.getJSON(RELATIVE_PATH + '/api/get_templates_listing')).done(function (config_data, templates_data) {
|
||||
@@ -96,8 +107,8 @@
|
||||
}
|
||||
|
||||
|
||||
templates.init = function (templates_to_load) {
|
||||
loadTemplates(templates_to_load || []);
|
||||
templates.init = function (templates_to_load, custom_templates) {
|
||||
loadTemplates(templates_to_load || [], custom_templates || false);
|
||||
}
|
||||
|
||||
templates.getTemplateNameFromUrl = function (url) {
|
||||
@@ -156,6 +167,10 @@
|
||||
template_data = data;
|
||||
parse_template();
|
||||
}).fail(function (data) {
|
||||
if(data && data.status == 404) {
|
||||
ajaxify.go('404');
|
||||
return;
|
||||
}
|
||||
app.alertError("Can't load template data!");
|
||||
});
|
||||
|
||||
@@ -168,25 +183,26 @@
|
||||
template_data['relative_path'] = RELATIVE_PATH;
|
||||
|
||||
translator.translate(templates[tpl_url].parse(template_data), function (translatedTemplate) {
|
||||
document.getElementById('content').innerHTML = translatedTemplate;
|
||||
|
||||
$('#content').html(translatedTemplate);
|
||||
|
||||
jQuery('#content [template-variable]').each(function (index, element) {
|
||||
var value = null;
|
||||
|
||||
switch (element.getAttribute('template-type')) {
|
||||
switch ($(element).attr('template-type')) {
|
||||
case 'boolean':
|
||||
value = (element.value === 'true' || element.value === '1') ? true : false;
|
||||
value = ($(element).val() === 'true' || $(element).val() === '1') ? true : false;
|
||||
break;
|
||||
case 'int': // Intentional fall-through
|
||||
case 'integer':
|
||||
value = parseInt(element.value);
|
||||
value = parseInt($(element).val());
|
||||
break;
|
||||
default:
|
||||
value = element.value;
|
||||
value = $(element).val();
|
||||
break;
|
||||
}
|
||||
|
||||
templates.set(element.getAttribute('template-variable'), value);
|
||||
templates.set($(element).attr('template-variable'), value);
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
@@ -219,7 +235,11 @@
|
||||
}
|
||||
|
||||
function makeRegex(block) {
|
||||
return new RegExp("<!-- BEGIN " + block + " -->[\\s\\S]*<!-- END " + block + " -->", 'g');
|
||||
return new RegExp("<!--[\\s]*BEGIN " + block + "[\\s]*-->[\\s\\S]*<!--[\\s]*END " + block + "[\\s]*-->", 'g');
|
||||
}
|
||||
|
||||
function makeConditionalRegex(block) {
|
||||
return new RegExp("<!--[\\s]*IF " + block + "[\\s]*-->[\\s\\S]*<!--[\\s]*ENDIF " + block + "[\\s]*-->", 'g');
|
||||
}
|
||||
|
||||
function getBlock(regex, block, template) {
|
||||
@@ -229,8 +249,8 @@
|
||||
if (self.blocks && block !== undefined) self.blocks[block] = data[0];
|
||||
|
||||
data = data[0]
|
||||
.replace("<!-- BEGIN " + block + " -->", "")
|
||||
.replace("<!-- END " + block + " -->", "");
|
||||
.replace("<!--[\\s]*BEGIN " + block + "[\\s]*-->", "")
|
||||
.replace("<!--[\\s]*END " + block + "[\\s]*-->", "");
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -249,7 +269,9 @@
|
||||
|
||||
for (var d in data) {
|
||||
if (data.hasOwnProperty(d)) {
|
||||
if (data[d] === null) {
|
||||
if (typeof data[d] === 'undefined') {
|
||||
continue;
|
||||
} else if (data[d] === null) {
|
||||
template = replace(namespace + d, '', template);
|
||||
} else if (data[d].constructor == Array) {
|
||||
namespace += d + '.';
|
||||
@@ -282,6 +304,29 @@
|
||||
block = parse(data[d], namespace, block);
|
||||
template = setBlock(regex, block, template);
|
||||
} else {
|
||||
var conditional = makeConditionalRegex(namespace + d);
|
||||
|
||||
var conditionalBlock = conditional.exec(template);
|
||||
|
||||
if (conditionalBlock !== null) {
|
||||
conditionalBlock = conditionalBlock[0].split(/<!-- ELSE -->/);
|
||||
|
||||
if (conditionalBlock[1]) {
|
||||
// there is an else statement
|
||||
if (!data[d]) {
|
||||
template = template.replace(conditional, conditionalBlock[1]);
|
||||
} else {
|
||||
template = template.replace(conditional, conditionalBlock[0]);
|
||||
}
|
||||
|
||||
} else {
|
||||
// regular if
|
||||
if (!data[d]) {
|
||||
template = template.replace(conditional, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template = replace(namespace + d, data[d], template);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
languageFile = parsedKey[0];
|
||||
|
||||
parsedKey = parsedKey[1];
|
||||
|
||||
translator.load(languageFile, function (languageData) {
|
||||
if (callback) {
|
||||
callback(languageData[parsedKey]);
|
||||
@@ -39,6 +40,20 @@
|
||||
});
|
||||
};
|
||||
|
||||
translator.mget = function (keys, callback) {
|
||||
|
||||
var async = require('async');
|
||||
|
||||
function getKey(key, callback) {
|
||||
translator.get(key, function(value) {
|
||||
callback(null, value);
|
||||
});
|
||||
}
|
||||
|
||||
async.map(keys, getKey, callback);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO: Not fully converted to server side yet, ideally server should be able to parse whole templates on demand if necessary
|
||||
* fix: translator.load should determine if server side and immediately return appropriate language file.
|
||||
@@ -65,23 +80,23 @@
|
||||
if (keys.hasOwnProperty(key)) {
|
||||
var variables = keys[key].split(/[,][?\s+]/);
|
||||
|
||||
var parsedKey = keys[key].replace('[[', '').replace(']]', '').split(':'),
|
||||
languageFile = parsedKey[0];
|
||||
var parsedKey = keys[key].replace('[[', '').replace(']]', '').split(':');
|
||||
if (!(parsedKey[0] && parsedKey[1])) continue;
|
||||
|
||||
var languageFile = parsedKey[0];
|
||||
parsedKey = parsedKey[1].split(',')[0];
|
||||
|
||||
if (files.loaded[languageFile]) {
|
||||
data = insertLanguage(data, keys[key], files.loaded[languageFile][parsedKey], variables);
|
||||
} else {
|
||||
loading++;
|
||||
|
||||
(function (languageKey, parsedKey) {
|
||||
(function (languageKey, parsedKey, languageFile, variables) {
|
||||
translator.load(languageFile, function (languageData) {
|
||||
data = insertLanguage(data, languageKey, languageData[parsedKey], variables);
|
||||
loading--;
|
||||
checkComplete();
|
||||
});
|
||||
}(keys[key], parsedKey));
|
||||
}(keys[key], parsedKey, languageFile, variables));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
(function(module) {
|
||||
'use strict';
|
||||
|
||||
var utils, fs;
|
||||
|
||||
try {
|
||||
if ('undefined' === typeof window) {
|
||||
fs = require('fs');
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
|
||||
module.exports = utils = {
|
||||
generateUUID: function() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
@@ -23,20 +24,28 @@
|
||||
main_dir = path.join(__dirname, '..', 'templates');
|
||||
|
||||
fs.readdir(dir, function(err, list) {
|
||||
if (err) return done(err);
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
var pending = list.length;
|
||||
if (!pending) return done(null, results);
|
||||
if (!pending) {
|
||||
return done(null, results);
|
||||
}
|
||||
list.forEach(function(file) {
|
||||
file = dir + '/' + file;
|
||||
fs.stat(file, function(err, stat) {
|
||||
if (stat && stat.isDirectory()) {
|
||||
utils.walk(file, function(err, res) {
|
||||
results = results.concat(res);
|
||||
if (!--pending) done(null, results);
|
||||
if (!--pending) {
|
||||
done(null, results);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
results.push(file.replace(main_dir + '/', '').replace('.tpl', ''));
|
||||
if (!--pending) done(null, results);
|
||||
if (!--pending) {
|
||||
done(null, results);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -49,19 +58,29 @@
|
||||
|
||||
difference = Math.floor(difference / 1000);
|
||||
|
||||
if (difference < 60) return difference + (min ? 's' : ' second') + (difference !== 1 && !min ? 's' : '');
|
||||
if (difference < 60) {
|
||||
return difference + (min ? 's' : ' second') + (difference !== 1 && !min ? 's' : '');
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 60);
|
||||
if (difference < 60) return difference + (min ? 'm' : ' minute') + (difference !== 1 && !min ? 's' : '');
|
||||
if (difference < 60) {
|
||||
return difference + (min ? 'm' : ' minute') + (difference !== 1 && !min ? 's' : '');
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 60);
|
||||
if (difference < 24) return difference + (min ? 'h' : ' hour') + (difference !== 1 && !min ? 's' : '');
|
||||
if (difference < 24) {
|
||||
return difference + (min ? 'h' : ' hour') + (difference !== 1 && !min ? 's' : '');
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 24);
|
||||
if (difference < 30) return difference + (min ? 'd' : ' day') + (difference !== 1 && !min ? 's' : '');
|
||||
if (difference < 30) {
|
||||
return difference + (min ? 'd' : ' day') + (difference !== 1 && !min ? 's' : '');
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 30);
|
||||
if (difference < 12) return difference + (min ? 'mon' : ' month') + (difference !== 1 && !min ? 's' : '');
|
||||
if (difference < 12) {
|
||||
return difference + (min ? 'mon' : ' month') + (difference !== 1 && !min ? 's' : '');
|
||||
}
|
||||
|
||||
difference = Math.floor(difference / 12);
|
||||
return difference + (min ? 'y' : ' year') + (difference !== 1 && !min ? 's' : '');
|
||||
@@ -94,7 +113,7 @@
|
||||
},
|
||||
|
||||
isUserNameValid: function(name) {
|
||||
return (name && name !== "" && (/^[a-zA-Z0-9 _-]+$/.test(name)));
|
||||
return (name && name !== "" && (/^['"\s\-.*0-9\u00BF-\u1FFF\u2C00-\uD7FF\w]+$/.test(name)));
|
||||
},
|
||||
|
||||
isPasswordValid: function(password) {
|
||||
@@ -116,8 +135,29 @@
|
||||
var tags = '',
|
||||
tag;
|
||||
for (var x = 0, numTags = tagsArr.length; x < numTags; x++) {
|
||||
if (tags.length > 0) tags += "\n\t";
|
||||
if (tags.length > 0) {
|
||||
tags += "\n\t";
|
||||
}
|
||||
tag = '<meta';
|
||||
var y;
|
||||
for (y in tagsArr[x]) {
|
||||
tag += ' ' + y + '="' + tagsArr[x][y] + '"';
|
||||
}
|
||||
tag += ' />';
|
||||
|
||||
tags += tag;
|
||||
}
|
||||
|
||||
return tags;
|
||||
},
|
||||
|
||||
buildLinkTags: function(tagsArr) {
|
||||
var tags = '',
|
||||
tag;
|
||||
for (var x = 0, numTags = tagsArr.length; x < numTags; x++) {
|
||||
if (tags.length > 0) tags += "\n\t";
|
||||
tag = '<link';
|
||||
var y;
|
||||
for (y in tagsArr[x]) {
|
||||
tag += ' ' + y + '="' + tagsArr[x][y] + '"';
|
||||
}
|
||||
@@ -140,7 +180,9 @@
|
||||
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
|
||||
document.title = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
|
||||
notificationIcon = notificationIcon || document.querySelector('.notifications a i');
|
||||
if (numNotifications > 0 && notificationIcon) notificationIcon.className = 'icon-circle active';
|
||||
if (numNotifications > 0 && notificationIcon) {
|
||||
notificationIcon.className = 'icon-circle active';
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.getJSON(RELATIVE_PATH + '/api/unread/total', function(data) {
|
||||
@@ -150,11 +192,11 @@
|
||||
if (data.count > 0) {
|
||||
badge
|
||||
.removeClass('badge-inverse')
|
||||
.addClass('badge-important')
|
||||
.addClass('badge-important');
|
||||
} else {
|
||||
badge
|
||||
.removeClass('badge-important')
|
||||
.addClass('badge-inverse')
|
||||
.addClass('badge-inverse');
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -162,8 +204,19 @@
|
||||
isRelativeUrl: function(url) {
|
||||
var firstChar = url.slice(0, 1);
|
||||
return (firstChar === '.' || firstChar === '/');
|
||||
},
|
||||
|
||||
makeNumberHumanReadable: function(num) {
|
||||
num = parseInt(num, 10);
|
||||
if (num > 999999) {
|
||||
return (num / 1000000).toFixed(1) + 'm';
|
||||
}
|
||||
else if(num > 999) {
|
||||
return (num / 1000).toFixed(1) + 'k';
|
||||
}
|
||||
return num;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (!String.prototype.trim) {
|
||||
@@ -172,25 +225,6 @@
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.ltrim) {
|
||||
String.prototype.ltrim = function() {
|
||||
return this.replace(/^\s+/, '');
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.rtrim) {
|
||||
String.prototype.rtrim = function() {
|
||||
return this.replace(/\s+$/, '');
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.fulltrim) {
|
||||
String.prototype.fulltrim = function() {
|
||||
return this.replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g, '').replace(/\s+/g, ' ');
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if ('undefined' !== typeof window) {
|
||||
window.utils = module.exports;
|
||||
}
|
||||
@@ -199,4 +233,4 @@
|
||||
module: {
|
||||
exports: {}
|
||||
}
|
||||
} : module)
|
||||
} : module);
|
||||
@@ -36,7 +36,7 @@
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">website</span>
|
||||
<span><a href="{website}">{website}</a></span>
|
||||
<span><a href="{website}">{websiteName}</a></span>
|
||||
<br/>
|
||||
|
||||
<span class="account-bio-label">location</span>
|
||||
@@ -98,6 +98,3 @@
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
<input type="hidden" template-variable="theirid" value="{theirid}" />
|
||||
<input type="hidden" template-type="boolean" template-variable="isFollowing" value="{isFollowing}" />
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/account.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
@@ -31,41 +31,6 @@
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="upload-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Upload Picture" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Upload Picture</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="uploadForm" action="{relative_path}/user/uploadpicture" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="userPhoto">Upload a picture</label>
|
||||
<input type="file" id="userPhotoInput" name="userPhoto">
|
||||
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
|
||||
</div>
|
||||
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
||||
</form>
|
||||
|
||||
<div id="upload-progress-box" class="progress progress-striped">
|
||||
<div id="upload-progress-bar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0">
|
||||
<span class="sr-only"> success</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="alert-status" class="alert alert-info hide"></div>
|
||||
<div id="alert-success" class="alert alert-success hide"></div>
|
||||
<div id="alert-error" class="alert alert-danger hide"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div class="account-username-box" data-userslug="{userslug}">
|
||||
<span class="account-username">
|
||||
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||
@@ -177,6 +142,3 @@
|
||||
|
||||
<input type="hidden" template-variable="gravatarpicture" value="{gravatarpicture}" />
|
||||
<input type="hidden" template-variable="uploadedpicture" value="{uploadedpicture}" />
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountedit.js"></script>
|
||||
|
||||
@@ -26,6 +26,3 @@
|
||||
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountsettings.js"></script>
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
<div class="categories">
|
||||
<h1>Categories</h1>
|
||||
|
||||
<hr />
|
||||
|
||||
<ul class="nav nav-pills">
|
||||
<li class='active'><a href='/admin/categories/active'>Active</a></li>
|
||||
<li class=''><a href='/admin/categories/disabled'>Disabled</a></li>
|
||||
@@ -13,21 +14,17 @@
|
||||
<div class="row admin-categories">
|
||||
<ul class="col-md-12" id="entry-container">
|
||||
<!-- BEGIN categories -->
|
||||
<li data-cid="{categories.cid}" class="entry-row {categories.blockclass}">
|
||||
<li data-cid="{categories.cid}" class="entry-row" style="background: {categories.bgColor}; color: {categories.color};">
|
||||
<form class="form-inline">
|
||||
<div class="icon">
|
||||
<i data-name="icon" value="{categories.icon}" class="{categories.icon} icon-2x"></i>
|
||||
</div>
|
||||
<input placeholder="Category Name" data-name="name" value="{categories.name}" class="form-control category_name"></input>
|
||||
<select class="form-control blockclass" data-name="blockclass" data-value="{categories.blockclass}">
|
||||
<option value="category-purple">category-purple</option>
|
||||
<option value="category-darkblue">category-darkblue</option>
|
||||
<option value="category-blue">category-blue</option>
|
||||
<option value="category-darkgreen">category-darkgreen</option>
|
||||
<option value="category-orange">category-orange</option>
|
||||
</select>
|
||||
<input placeholder="#000" data-name="bgColor" value="{categories.bgColor}" class="form-control category_bgColor" />
|
||||
<input placeholder="#000" data-name="color" value="{categories.color}" class="form-control category_color" />
|
||||
<input data-name="description" placeholder="Category Description" value="{categories.description}" class="form-control category_description description"></input>
|
||||
<button type="submit" class="btn btn-default" data-disabled="{categories.disabled}">Disable</button>
|
||||
<input type="hidden" data-name="order" data-value="{categories.order}"></input>
|
||||
<button type="submit" class="btn btn-default disable-btn" data-disabled="{categories.disabled}">Disable</button>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
@@ -101,5 +98,4 @@
|
||||
<div class="col-md-3"><i class="icon-adn"></i></div><div class="col-md-3"><i class="icon-android"></i></div><div class="col-md-3"><i class="icon-apple"></i></div><div class="col-md-3"><i class="icon-bitbucket"></i></div><div class="col-md-3"><i class="icon-bitbucket-sign"></i></div><div class="col-md-3"><i class="icon-bitcoin"></i></div><div class="col-md-3"><i class="icon-btc"></i></div><div class="col-md-3"><i class="icon-css3"></i></div><div class="col-md-3"><i class="icon-dribbble"></i></div><div class="col-md-3"><i class="icon-dropbox"></i></div><div class="col-md-3"><i class="icon-facebook"></i></div><div class="col-md-3"><i class="icon-facebook-sign"></i></div><div class="col-md-3"><i class="icon-flickr"></i></div><div class="col-md-3"><i class="icon-foursquare"></i></div><div class="col-md-3"><i class="icon-github"></i></div><div class="col-md-3"><i class="icon-github-alt"></i></div><div class="col-md-3"><i class="icon-github-sign"></i></div><div class="col-md-3"><i class="icon-gittip"></i></div><div class="col-md-3"><i class="icon-google-plus"></i></div><div class="col-md-3"><i class="icon-google-plus-sign"></i></div><div class="col-md-3"><i class="icon-html5"></i></div><div class="col-md-3"><i class="icon-instagram"></i></div><div class="col-md-3"><i class="icon-linkedin"></i></div><div class="col-md-3"><i class="icon-linkedin-sign"></i></div><div class="col-md-3"><i class="icon-linux"></i></div><div class="col-md-3"><i class="icon-maxcdn"></i></div><div class="col-md-3"><i class="icon-pinterest"></i></div><div class="col-md-3"><i class="icon-pinterest-sign"></i></div><div class="col-md-3"><i class="icon-renren"></i></div><div class="col-md-3"><i class="icon-skype"></i></div><div class="col-md-3"><i class="icon-stackexchange"></i></div><div class="col-md-3"><i class="icon-trello"></i></div><div class="col-md-3"><i class="icon-tumblr"></i></div><div class="col-md-3"><i class="icon-tumblr-sign"></i></div><div class="col-md-3"><i class="icon-twitter"></i></div><div class="col-md-3"><i class="icon-twitter-sign"></i></div><div class="col-md-3"><i class="icon-vk"></i></div><div class="col-md-3"><i class="icon-weibo"></i></div><div class="col-md-3"><i class="icon-windows"></i></div><div class="col-md-3"><i class="icon-xing"></i></div><div class="col-md-3"><i class="icon-xing-sign"></i></div><div class="col-md-3"><i class="icon-youtube"></i></div><div class="col-md-3"><i class="icon-youtube-play"></i></div><div class="col-md-3"><i class="icon-youtube-sign"></i></div>
|
||||
<div class="col-md-3"><i class="icon-ambulance"></i></div><div class="col-md-3"><i class="icon-h-sign"></i></div><div class="col-md-3"><i class="icon-hospital"></i></div><div class="col-md-3"><i class="icon-medkit"></i></div><div class="col-md-3"><i class="icon-plus-sign-alt"></i></div><div class="col-md-3"><i class="icon-stethoscope"></i></div><div class="col-md-3"><i class="icon-user-md"></i></div>
|
||||
</div></div></div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/categories.js"></script>
|
||||
</div>
|
||||
@@ -17,10 +17,7 @@
|
||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
var loadDelay = setInterval(function() {
|
||||
if (nodebb_admin) {
|
||||
nodebb_admin.prepare();
|
||||
clearInterval(loadDelay);
|
||||
}
|
||||
}, 500);
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
@@ -2,6 +2,41 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="upload-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Upload Picture" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Upload Picture</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="uploadForm" action="" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="userPhoto">Upload a picture</label>
|
||||
<input type="file" id="userPhotoInput" name="userPhoto">
|
||||
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
|
||||
</div>
|
||||
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
||||
</form>
|
||||
|
||||
<div id="upload-progress-box" class="progress progress-striped">
|
||||
<div id="upload-progress-bar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0">
|
||||
<span class="sr-only"> success</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="alert-status" class="alert alert-info hide"></div>
|
||||
<div id="alert-success" class="alert alert-success hide"></div>
|
||||
<div id="alert-error" class="alert alert-danger hide"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="alert_window"></div>
|
||||
|
||||
<div id="footer" class="container" style="padding-top: 50px; display:none;">
|
||||
@@ -9,7 +44,7 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.getScript(RELATIVE_PATH + '/src/forum/admin/footer.js');
|
||||
require(['forum/admin/footer']);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
var loadDelay = setInterval(function() {
|
||||
if (nodebb_admin) {
|
||||
nodebb_admin.prepare();
|
||||
clearInterval(loadDelay);
|
||||
}
|
||||
}, 500);
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
@@ -12,14 +12,14 @@
|
||||
<p>{groups.description}</p>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default" data-action="members">Members</button>
|
||||
<!-- IF groups.deletable -->
|
||||
<button class="btn btn-danger" data-action="delete">Delete Group</button>
|
||||
<!-- ENDIF groups.deletable -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<ul class="pull-right members">
|
||||
<!-- BEGIN members -->
|
||||
<li data-uid="{groups.members.uid}" title="{groups.members.username}"><img src="{groups.members.picture}" /></li>
|
||||
<!-- END members -->
|
||||
<!-- BEGIN members --><li data-uid="{groups.members.uid}" title="{groups.members.username}"><img src="{groups.members.picture}" /></li><!-- END members -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,5 +96,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/groups.js"></script>
|
||||
@@ -7,37 +7,41 @@
|
||||
var RELATIVE_PATH = "{relative_path}";
|
||||
</script>
|
||||
<link id="base-theme" href="{relative_path}/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
|
||||
<link href="{relative_path}/vendor/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" media="screen">
|
||||
<link rel="stylesheet" href="{relative_path}/vendor/fontawesome/css/font-awesome.min.css">
|
||||
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-git.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/qunit/qunit-git.css">
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/vendor/colorpicker/colorpicker.css">
|
||||
<script type="text/javascript" src="{relative_path}/socket.io/socket.io.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/app.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/templates.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/translator.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/ajaxify.js"></script>
|
||||
<script src="{relative_path}/vendor/jquery/js/jquery.timeago.js"></script>
|
||||
<script src="{relative_path}/vendor/jquery/js/jquery.form.js"></script>
|
||||
<script src="{relative_path}/vendor/requirejs/require.js"></script>
|
||||
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
|
||||
<script src="{relative_path}/vendor/colorpicker/colorpicker.js"></script>
|
||||
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: "{relative_path}/src/modules",
|
||||
waitSeconds: 3
|
||||
waitSeconds: 3,
|
||||
paths: {
|
||||
"forum": '../forum'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
|
||||
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
||||
<script src="{relative_path}/src/utils.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/admin.css" />
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/theme.css" />
|
||||
</head>
|
||||
|
||||
<body class="admin">
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar navbar-inverse navbar-fixed-top header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
@@ -49,62 +53,97 @@
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a href="/" target="_blank"><i class="icon-book"></i> Forum</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/index"><i class="icon-home"></i> Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings"><i class="icon-cogs"></i> Settings</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" target="_top"><i class="icon-book"></i> Forum</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" id="reconnect"></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav pull-right" id="right-menu">
|
||||
<li><a href="/users" id="user_label"></a></li>
|
||||
|
||||
<ul id="logged-in-menu" class="nav navbar-nav navbar-right">
|
||||
<li id="user_label" class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown">
|
||||
<img src="{userpicture}"/>
|
||||
</a>
|
||||
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
|
||||
<li>
|
||||
<a id="user-profile-link" href="/user/{userslug}" target="_top"><span>Profile</span></a>
|
||||
</li>
|
||||
<li id="logout-link">
|
||||
<a href="#">Log out</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="csrf_token" type="hidden" template-variable="csrf" value="{csrf}" />
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">NodeBB</li>
|
||||
<li class='active'><a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
|
||||
<li class=""><a href="{relative_path}/admin/groups"><i class="icon-group"></i> Groups</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/settings'><i class='icon-cogs'></i> Settings</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/redis'><i class='icon-hdd'></i> Redis</a></li>
|
||||
<li class=''><a href="{relative_path}/admin/motd"><i class="icon-comment"></i> MOTD</a></li>
|
||||
|
||||
<li class='active'>
|
||||
<a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a>
|
||||
</li>
|
||||
<li><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
|
||||
<li><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
|
||||
<li><a href="{relative_path}/admin/groups"><i class="icon-group"></i> Groups</a></li>
|
||||
<li><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
|
||||
<li><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
|
||||
<li><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
|
||||
<li><a href='{relative_path}/admin/settings'><i class='icon-cogs'></i> Settings</a></li>
|
||||
<li><a href='{relative_path}/admin/redis'><i class='icon-hdd'></i> Redis</a></li>
|
||||
<li><a href='{relative_path}/admin/logger'><i class='icon-th'></i> Logger</a></li>
|
||||
<li><a href="{relative_path}/admin/motd"><i class="icon-comment"></i> MOTD</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">Social Authentication</li>
|
||||
<li class=''><a href='{relative_path}/admin/twitter'><i class='icon-twitter-sign'></i> Twitter</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/facebook'><i class='icon-facebook-sign'></i> Facebook</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/gplus'><i class='icon-google-plus-sign'></i> Google+</a></li>
|
||||
<!--<li class="nav-header">Custom Modules</li>-->
|
||||
<!-- <li class=''><a href=''>Search</a></li> -->
|
||||
<li><a href='{relative_path}/admin/twitter'><i class='icon-twitter-sign'></i> Twitter</a></li>
|
||||
<li><a href='{relative_path}/admin/facebook'><i class='icon-facebook-sign'></i> Facebook</a></li>
|
||||
<li><a href='{relative_path}/admin/gplus'><i class='icon-google-plus-sign'></i> Google+</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">Plugins</li>
|
||||
<!-- BEGIN plugins -->
|
||||
<li>
|
||||
<a href='{relative_path}/admin{plugins.route}'><i class="{plugins.icon}"></i> {plugins.name}</a>
|
||||
</li>
|
||||
<!-- END plugins -->
|
||||
</ul>
|
||||
</div>
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">Unit Tests</li>
|
||||
<ul class="nav nav-list">
|
||||
<li class=''><a href='{relative_path}/admin/testing/categories'>Categories</a></li>
|
||||
<!--<li class=''><a href='{relative_path}/admin/testing/topics'>Topics</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/posts'>Posts</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/accounts'>Accounts</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/chat'>Chat</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/notifications'>Notifications</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/friends'>Friends</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/feed'>RSS Feed</a></li>
|
||||
<li class=''><a href='{relative_path}/admin/testing/emails'>Emails</a></li>-->
|
||||
<li><a href='{relative_path}/admin/testing/categories'>Categories</a></li>
|
||||
<!--<li><a href='{relative_path}/admin/testing/topics'>Topics</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/posts'>Posts</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/accounts'>Accounts</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/chat'>Chat</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/notifications'>Notifications</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/friends'>Friends</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/feed'>RSS Feed</a></li>
|
||||
<li><a href='{relative_path}/admin/testing/emails'>Emails</a></li>-->
|
||||
</ul>
|
||||
</ul>
|
||||
</div><!--/.well -->
|
||||
</div><!--/span-->
|
||||
|
||||
<div class="col-md-9" id="content">
|
||||
@@ -18,5 +18,3 @@
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/index.js"></script>
|
||||
46
public/templates/admin/logger.tpl
Normal file
46
public/templates/admin/logger.tpl
Normal file
@@ -0,0 +1,46 @@
|
||||
<h1>Logger</h1>
|
||||
<hr />
|
||||
|
||||
<h3>Logger Settings</h3>
|
||||
<div class="alert alert-warning">
|
||||
|
||||
<p>
|
||||
By enabling the check boxes, you will receive logs to your terminal. If you specify a path, logs will then be saved to a file instead. HTTP logging is useful for collecting statistics about who, when, and what people access on your forum. In addition to logging HTTP requests, we can also log socket.io events. Socket.io logging, in combination with redis-cli monitor, can be very helpful for learning NodeBB's internals.
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
Simply check/uncheck the logging settings to enable or disable logging on the fly. No restart needed.
|
||||
</p>
|
||||
<br/>
|
||||
|
||||
<form>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" data-field="loggerStatus"> <strong>Enable HTTP logging</strong>
|
||||
</label>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" data-field="loggerIOStatus"> <strong>Enable socket.io event logging</strong>
|
||||
</label>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
<label>Path to log file</label>
|
||||
<input class="form-control" type="text" placeholder="/path/to/log/file.log ::: leave blank to log to your terminal" data-field="loggerPath" />
|
||||
<br />
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
@@ -24,10 +24,7 @@
|
||||
<button class="btn btn-lg btn-primary" id="save" checked>Save</button>
|
||||
|
||||
<script>
|
||||
var loadDelay = setInterval(function() {
|
||||
if (nodebb_admin) {
|
||||
nodebb_admin.prepare();
|
||||
clearInterval(loadDelay);
|
||||
}
|
||||
}, 500);
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
@@ -21,5 +21,3 @@
|
||||
Full documentation regarding plugin authoring can be found in the <a target="_blank" href="https://github.com/designcreateplay/NodeBB/wiki/Writing-Plugins-for-NodeBB">NodeBB Wiki</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/plugins.js"></script>
|
||||
@@ -8,6 +8,11 @@
|
||||
<input class="form-control" type="text" placeholder="Your Community Name" data-field="title" /><br />
|
||||
<label>Site Description</label>
|
||||
<input type="text" class="form-control" placeholder="A short description about your community" data-field="description" /><br />
|
||||
<label>Site Keywords</label>
|
||||
<input type="text" class="form-control" placeholder="Keywords describing your community, comma-seperated" data-field="keywords" /><br />
|
||||
<label>Site Logo</label>
|
||||
<input id="logoUrl" type="text" class="form-control" placeholder="Path to a logo to display on forum header" data-field="brand:logo" /><br />
|
||||
<input id="uploadLogoBtn" type="button" class="btn btn-default" value="Upload"></input> <br />
|
||||
<label>Imgur Client ID</label>
|
||||
<input type="text" class="form-control" placeholder="Imgur ClientID for image uploads" data-field="imgurClientID" /><br />
|
||||
<label>Maximum User Image Size</label>
|
||||
@@ -19,10 +24,8 @@
|
||||
<h3>Privilege Thresholds</h3>
|
||||
<div class="alert alert-warning">
|
||||
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
|
||||
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000"><br />
|
||||
<strong>Moderate Users</strong><br /> <input type="text" class="form-control" value="10000"><br />
|
||||
<strong>Create Pinned Topics</strong><br /> <input type="text" class="form-control" value="100000"><br />
|
||||
|
||||
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_topic"><br />
|
||||
<strong>Manage Content</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_content"><br />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -70,17 +73,23 @@
|
||||
<strong>Post Delay</strong><br /> <input type="text" class="form-control" value="10000" data-field="postDelay"><br />
|
||||
<strong>Minimum Title Length</strong><br /> <input type="text" class="form-control" value="3" data-field="minimumTitleLength"><br />
|
||||
<strong>Minimum Post Length</strong><br /> <input type="text" class="form-control" value="8" data-field="minimumPostLength"><br />
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="allowGuestPosting"> <strong>Allow guests to post without logging in</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
var loadDelay = setInterval(function() {
|
||||
if (nodebb_admin) {
|
||||
nodebb_admin.prepare();
|
||||
clearInterval(loadDelay);
|
||||
}
|
||||
}, 500);
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
@@ -20,7 +20,7 @@ jQuery(document).ready(function () {
|
||||
slug = 'category/' + category.slug;
|
||||
|
||||
asyncTest( "Loading Category '" + category.name + "' located at " + slug, function() {
|
||||
jQuery.get(config.api_url + slug, function(data) {
|
||||
jQuery.get(RELATIVE_PATH + '/api/' + slug, function(data) {
|
||||
ok( data.category_name, JSON.stringify(data) ); //todo: check this against data.categories
|
||||
start();
|
||||
});
|
||||
|
||||
@@ -23,4 +23,10 @@
|
||||
<button class="btn btn-warning" id="revert_theme">Revert</button> This will remove any custom theme applied to your NodeBB, and restore the base theme.
|
||||
</p>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/themes.js"></script>
|
||||
<script>
|
||||
var bootswatchListener = function(data) {
|
||||
require(['forum/admin/themes'], function(t) {
|
||||
t.render(data);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -1,6 +1,7 @@
|
||||
<h1>Topics</h1>
|
||||
<hr />
|
||||
|
||||
|
||||
<ul class="topics">
|
||||
<!-- BEGIN topics -->
|
||||
<li data-tid="{topics.tid}" data-locked="{topics.locked}" data-pinned="{topics.pinned}" data-deleted="{topics.deleted}">
|
||||
@@ -11,7 +12,7 @@
|
||||
</div>
|
||||
<a target="_blank" href="{relative_path}/topic/{topics.slug}">{topics.title}</a>
|
||||
<ul>
|
||||
<li><i class="icon-time"></i> Posted {topics.relativeTime} ago by {topics.username}</li>
|
||||
<li><i class="icon-time"></i> Posted <span class="timeago" title="{topics.relativeTime}"></span> by {topics.username}</li>
|
||||
<li><i class="icon-comments"></i> {topics.postcount} post(s)</li>
|
||||
</ul>
|
||||
<div class="clear"></div>
|
||||
@@ -19,8 +20,14 @@
|
||||
<!-- END topics -->
|
||||
</ul>
|
||||
|
||||
<!-- IF notopics -->
|
||||
<div class="alert alert-warning" id="category-no-topics">
|
||||
<strong>There are no topics.</strong>
|
||||
</div>
|
||||
<!-- ELSE -->
|
||||
<div class="text-center">
|
||||
<button id="topics_loadmore" class="btn btn-primary btn-lg">Load More Topics</button>
|
||||
</div>
|
||||
<!-- ENDIF notopics -->
|
||||
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/topics.js"></script>
|
||||
@@ -17,10 +17,7 @@
|
||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
var loadDelay = setInterval(function() {
|
||||
if (nodebb_admin) {
|
||||
nodebb_admin.prepare();
|
||||
clearInterval(loadDelay);
|
||||
}
|
||||
}, 500);
|
||||
require(['forum/admin/settings'], function(Settings) {
|
||||
Settings.prepare();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<a href="/user/{users.userslug}">{users.username}</a>
|
||||
<br/>
|
||||
<div title="reputation">
|
||||
<span id='reputation'>{users.reputation}</span>
|
||||
<i class='icon-star'></i>
|
||||
<span id='reputation'>{users.reputation}</span>
|
||||
</div>
|
||||
<div title="post count">
|
||||
<span id='postcount'>{users.postcount}</span>
|
||||
<i class='icon-pencil'></i>
|
||||
<span id='postcount'>{users.postcount}</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="btn btn-default ban-btn">Ban</a>
|
||||
@@ -42,6 +42,3 @@
|
||||
<button id="load-more-users-btn" class="btn btn-primary">Load More</button>
|
||||
</div>
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/users.js"></script>
|
||||
|
||||
@@ -26,37 +26,59 @@
|
||||
|
||||
<div class="category row">
|
||||
<div class="{topic_row_size}">
|
||||
<ul id="topics-container">
|
||||
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList">
|
||||
<meta itemprop="itemListOrder" content="descending">
|
||||
<!-- BEGIN topics -->
|
||||
|
||||
<li class="category-item {topics.deleted-class}">
|
||||
<li class="category-item {topics.deleted-class}" itemprop="itemListElement">
|
||||
<div class="row">
|
||||
<div class="col-md-12 topic-row">
|
||||
<div class="latest-post visible-lg visible-md">
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
<div class="pull-right">
|
||||
<img class="img-rounded" style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
||||
<p>{topics.teaser_text}</p>
|
||||
<p class="meta">
|
||||
<strong>{topics.teaser_username}</strong> posted <span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<a href="../../topic/{topics.slug}">
|
||||
<div>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||
<small>
|
||||
<a href="../../topic/{topics.slug}" itemprop="url">
|
||||
<h3>
|
||||
<meta itemprop="name" content="{topics.title}">
|
||||
|
||||
<span class="topic-title">
|
||||
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||
Posted <span class="timeago" title="{topics.relativeTime}"></span> by
|
||||
<strong>{topics.username}</strong>.
|
||||
{topics.title}
|
||||
</span>
|
||||
</h3>
|
||||
</a>
|
||||
<small>
|
||||
<span class="topic-stats">
|
||||
posts
|
||||
<strong>{topics.postcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span class="topic-stats">
|
||||
views
|
||||
<strong>{topics.viewcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span>
|
||||
<a href="/user/{topics.userslug}">
|
||||
<img class="teaser-pic" src="{topics.picture}" title="{topics.username}"/>
|
||||
</a>
|
||||
posted <span class="timeago" title="{topics.relativeTime}"></span>
|
||||
</span>
|
||||
|
||||
<span class="pull-right hidden-xs">
|
||||
<!-- IF topics.unreplied -->
|
||||
No one has replied
|
||||
<!-- ELSE -->
|
||||
<a href="/user/{topics.teaser_userslug}">
|
||||
<img class="teaser-pic" src="{topics.teaser_userpicture}" title="{topics.teaser_username}"/>
|
||||
</a>
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
replied
|
||||
</a>
|
||||
<span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
<!-- ENDIF topics.unreplied -->
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- END topics -->
|
||||
</ul>
|
||||
</div>
|
||||
@@ -74,9 +96,9 @@
|
||||
<div class="block-header">
|
||||
[[category:sidebar.active_participants]]
|
||||
</div>
|
||||
<div class="block-content">
|
||||
<div class="block-content active-users">
|
||||
<!-- BEGIN active_users -->
|
||||
<a href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded" /></a>
|
||||
<a data-uid="{active_users.uid}" href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded user-img" /></a>
|
||||
<!-- END active_users -->
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,6 +112,16 @@
|
||||
<!-- END moderators -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- BEGIN sidebars -->
|
||||
<div class="sidebar-block img-thumbnail {sidebars.block_class}">
|
||||
<div class="block-header">
|
||||
{sidebars.header}
|
||||
</div>
|
||||
<div class="block-content">
|
||||
{sidebars.content}
|
||||
</div>
|
||||
</div>
|
||||
<!-- END sidebars -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,5 +129,3 @@
|
||||
<input type="hidden" template-variable="twitter-intent-url" value="{twitter-intent-url}" />
|
||||
<input type="hidden" template-variable="facebook-share-url" value="{facebook-share-url}" />
|
||||
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/category.js"></script>
|
||||
@@ -1,42 +1,34 @@
|
||||
{
|
||||
"custom_mapping": {
|
||||
"admin/testing/categories.*": "admin/testing/categories",
|
||||
"admin/topics.*": "admin/topics",
|
||||
"admin/categories.*": "admin/categories",
|
||||
"admin/users.*": "admin/users",
|
||||
"admin/redis.*": "admin/redis",
|
||||
"admin/index.*": "admin/index",
|
||||
"admin/themes.*": "admin/themes",
|
||||
"admin/plugins.*": "admin/plugins",
|
||||
"^admin/testing/categories.*": "admin/testing/categories",
|
||||
"^admin/topics.*": "admin/topics",
|
||||
"^admin/categories.*": "admin/categories",
|
||||
"^admin/users.*": "admin/users",
|
||||
"^admin/redis.*": "admin/redis",
|
||||
"^admin/index.*": "admin/index",
|
||||
"^admin/themes.*": "admin/themes",
|
||||
"^admin/plugins/?$": "admin/plugins",
|
||||
"^admin/settings.*": "admin/settings",
|
||||
"admin/twitter.*": "admin/twitter",
|
||||
"admin/facebook.*": "admin/facebook",
|
||||
"admin/gplus.*": "admin/gplus",
|
||||
"admin/motd/?$": "admin/motd",
|
||||
"admin/groups/?$": "admin/groups",
|
||||
"install/?$": "install/mail",
|
||||
"install/mail/?": "install/mail",
|
||||
"install/social/?": "install/social",
|
||||
"install/privileges/?": "install/privileges",
|
||||
"users/sort-posts": "users",
|
||||
"users/latest": "users",
|
||||
"users/sort-reputation": "users",
|
||||
"users/search": "users",
|
||||
"user.*edit": "accountedit",
|
||||
"user.*following": "following",
|
||||
"user.*followers": "followers",
|
||||
"user.*settings": "accountsettings",
|
||||
"user.*favourites": "favourites",
|
||||
"user/.*": "account",
|
||||
"^admin/twitter.*": "admin/twitter",
|
||||
"^admin/facebook.*": "admin/facebook",
|
||||
"^admin/logger.*": "admin/logger",
|
||||
"^admin/gplus.*": "admin/gplus",
|
||||
"^admin/motd/?$": "admin/motd",
|
||||
"^admin/groups/?$": "admin/groups",
|
||||
"^users/sort-posts": "users",
|
||||
"^users/latest": "users",
|
||||
"^users/sort-reputation": "users",
|
||||
"^users/search": "users",
|
||||
"^user.*edit": "accountedit",
|
||||
"^user.*following": "following",
|
||||
"^user.*followers": "followers",
|
||||
"^user.*settings": "accountsettings",
|
||||
"^user.*favourites": "favourites",
|
||||
"^user/.*": "account",
|
||||
|
||||
"recent": "recent",
|
||||
"unread": "unread",
|
||||
"popular": "category",
|
||||
"active": "category",
|
||||
"search": "search",
|
||||
"reset/.*": "reset_code",
|
||||
"reset": "reset"
|
||||
"^recent/.*": "recent",
|
||||
|
||||
"reset/.*": "reset_code"
|
||||
},
|
||||
"force_refresh": {
|
||||
"logout": true
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<div class="well favourites">
|
||||
<div class="account-username-box" data-userslug="{userslug}">
|
||||
<span class="account-username">
|
||||
<a href="/user/{userslug}">{username}</a>
|
||||
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||
<a href="/user/{userslug}/favourites">favourites</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +13,8 @@
|
||||
<!-- BEGIN posts -->
|
||||
<div class="topic-row img-thumbnail clearfix" topic-url="topic/{posts.tid}/#{posts.pid}">
|
||||
<span><strong>{posts.username}</strong> : </span>
|
||||
<span>{posts.content}</span>
|
||||
<span>{posts.category_name} >> {posts.title}</span>
|
||||
<div>{posts.content}</div>
|
||||
<div>
|
||||
<span class="pull-right timeago" title="{posts.relativeTime}"></span>
|
||||
</div>
|
||||
@@ -22,6 +24,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/favourites.js"></script>
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
<img src="{followers.picture}" class="img-thumbnail"/>
|
||||
</a>
|
||||
<br/>
|
||||
<div class="user-info">
|
||||
<a href="/user/{followers.userslug}">{followers.username}</a>
|
||||
<br/>
|
||||
<div title="reputation">
|
||||
<div title="reputation" class="reputation">
|
||||
<span class='formatted-number'>{followers.reputation}</span>
|
||||
<i class='icon-star'></i>
|
||||
</div>
|
||||
<div title="post count">
|
||||
<div title="post count" class="post-count">
|
||||
<span class='formatted-number'>{followers.postcount}</span>
|
||||
<i class='icon-pencil'></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END followers -->
|
||||
</div>
|
||||
<div id="no-followers-notice" class="alert alert-warning hide">This user doesn't have any followers :(</div>
|
||||
@@ -34,6 +36,3 @@
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
<input type="hidden" template-variable="theirid" value="{theirid}" />
|
||||
<input type="hidden" template-variable="followersCount" value="{followersCount}" />
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/followers.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
@@ -15,18 +15,20 @@
|
||||
<img src="{following.picture}" class="img-thumbnail"/>
|
||||
</a>
|
||||
<br/>
|
||||
<div class="user-info">
|
||||
<a href="/user/{following.userslug}">{following.username}</a>
|
||||
<br/>
|
||||
<div title="reputation">
|
||||
<div title="reputation" class="reputation">
|
||||
<span class='formatted-number'>{following.reputation}</span>
|
||||
<i class='icon-star'></i>
|
||||
</div>
|
||||
<div title="post count">
|
||||
<div title="post count" class="post-count">
|
||||
<span class='formatted-number'>{following.postcount}</span>
|
||||
<i class='icon-pencil'></i>
|
||||
</div>
|
||||
<a id="unfollow-btn" href="#" class="btn btn-default unfollow-btn" followingUid="{following.uid}" data-username="{following.username}">Unfollow</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- END following -->
|
||||
</div>
|
||||
<div id="no-following-notice" class="alert alert-warning hide">This user isn't following anyone :(</div>
|
||||
@@ -35,6 +37,3 @@
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
<input type="hidden" template-variable="theirid" value="{theirid}" />
|
||||
<input type="hidden" template-variable="followingCount" value="{followingCount}" />
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/following.js"></script>
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
</div><!--END container -->
|
||||
|
||||
<div id="chat-modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
||||
<div id="chat-modal" class="modal chat-modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true" data-backdrop="none">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -21,39 +21,51 @@
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="upload-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Upload Picture" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Upload Picture</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="uploadForm" action="" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="userPhoto">Upload a picture</label>
|
||||
<input type="file" id="userPhotoInput" name="userPhoto">
|
||||
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
|
||||
</div>
|
||||
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
||||
</form>
|
||||
|
||||
<div id="upload-progress-box" class="progress progress-striped">
|
||||
<div id="upload-progress-bar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0">
|
||||
<span class="sr-only"> success</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="alert-status" class="alert alert-info hide"></div>
|
||||
<div id="alert-success" class="alert alert-success hide"></div>
|
||||
<div id="alert-error" class="alert alert-danger hide"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="alert_window"></div>
|
||||
|
||||
|
||||
<footer id="footer" class="container footer">
|
||||
<div class="row footer-stats">
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_online"></span><br /><small>[[footer:stats.online]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_users"></span><br /><small>[[footer:stats.users]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_topics"></span><br /><small>[[footer:stats.topics]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_posts"></span><br /><small>[[footer:stats.posts]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{footerHTML}
|
||||
<div class="copyright">Copyright © 2013 <a target="_blank" href="http://www.nodebb.org">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
$.getScript(RELATIVE_PATH + '/src/forum/footer.js');
|
||||
require(['forum/footer']);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
{meta_tags}
|
||||
<link href="{cssSrc}" rel="stylesheet" media="screen">
|
||||
<link rel="stylesheet" href="{relative_path}/vendor/fontawesome/css/font-awesome.min.css">
|
||||
{link_tags}
|
||||
<!-- BEGIN pluginCSS -->
|
||||
<link rel="stylesheet" href="{pluginCSS.path}">
|
||||
<!-- END pluginCSS -->
|
||||
<script>
|
||||
var RELATIVE_PATH = "{relative_path}";
|
||||
</script>
|
||||
@@ -15,11 +19,14 @@
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: "{relative_path}/src/modules",
|
||||
waitSeconds: 3
|
||||
waitSeconds: 3,
|
||||
paths: {
|
||||
"forum": '../forum'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/theme.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -31,10 +38,15 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<div>
|
||||
<a href="/">
|
||||
<img class="{brand:logo:display} forum-logo" src="{brand:logo}" />
|
||||
</a>
|
||||
<a href="/">
|
||||
<h1 class="navbar-brand forum-title">{title}</h1>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar-collapse collapse navbar-ex1-collapse">
|
||||
<ul id="main-nav" class="nav navbar-nav">
|
||||
@@ -47,17 +59,26 @@
|
||||
<li>
|
||||
<a href="/users">[[global:header.users]]</a>
|
||||
</li>
|
||||
<li class="{adminDisplay}">
|
||||
<a href="/admin"><i class="icon-cogs"></i> [[global:header.admin]]</a>
|
||||
</li>
|
||||
<li class="visible-xs">
|
||||
<a href="/search">[[global:header.search]]</a>
|
||||
</li>
|
||||
<li class="visible-xs">
|
||||
<a href="/search">Search</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/"></a>
|
||||
<!-- BEGIN navigation -->
|
||||
<li class="{navigation.class}">
|
||||
<a href="{navigation.route}">{navigation.text}</a>
|
||||
</li>
|
||||
<!-- END navigation -->
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="logged-in-menu" class="nav navbar-nav navbar-right hide">
|
||||
<li>
|
||||
<a href="#" id="reconnect"></a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<form id="search-form" class="navbar-form navbar-right hidden-xs" role="search" method="GET" action="">
|
||||
<div class="hide" id="search-fields">
|
||||
<div class="form-group">
|
||||
@@ -67,10 +88,6 @@
|
||||
</div>
|
||||
<button id="search-button" type="button" class="btn btn-link"><i class="icon-search"></i></button>
|
||||
</form>
|
||||
|
||||
<ul id="logged-in-menu" class="nav navbar-nav navbar-right hide">
|
||||
<li>
|
||||
<a href="#" id="reconnect"></a>
|
||||
</li>
|
||||
|
||||
<li id="notifications-list" class="notifications dropdown text-center hidden-xs">
|
||||
@@ -82,25 +99,40 @@
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a id="user_label" href="">
|
||||
<li id="user_label" class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown">
|
||||
<img src=""/>
|
||||
<span></span>
|
||||
</a>
|
||||
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
|
||||
<li>
|
||||
<a id="user-profile-link" href=""><span>Profile</span></a>
|
||||
</li>
|
||||
|
||||
<li id="logout-link">
|
||||
<a href="#">Log out</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul id="logged-out-menu" class="nav navbar-nav navbar-right">
|
||||
<li id="register-link">
|
||||
<li class="visible-lg visible-md visible-sm">
|
||||
<a href="/register">Register</a>
|
||||
</li>
|
||||
<li id="login-link">
|
||||
<li class="visible-lg visible-md visible-sm">
|
||||
<a href="/login">Login</a>
|
||||
</li>
|
||||
<li class="visible-xs">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="loggedout_dropdown"><i class="icon-signin"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="loggedout_dropdown">
|
||||
<li>
|
||||
<a href="/register">Register</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/login">Login</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="pagination-block">
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<div class="jumbotron {motd_class}">
|
||||
<div class="motd{motd_class}">
|
||||
{motd}
|
||||
</div>
|
||||
|
||||
<div class="row home">
|
||||
<div class="row home" itemscope itemtype="http://www.schema.org/ItemList">
|
||||
<!-- BEGIN categories -->
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<a href="category/{categories.slug}">
|
||||
<a href="category/{categories.slug}" itemprop="url">
|
||||
<meta itemprop="name" content="{categories.name}">
|
||||
<h4><span class="badge {categories.badgeclass}">{categories.topic_count} </span> {categories.name}</h4>
|
||||
<div class="icon {categories.blockclass}">
|
||||
<div class="icon" style="background: {categories.bgColor}; color: {categories.color};">
|
||||
<div id="category-{categories.cid}" class="category-slider-{categories.post_count}">
|
||||
<div class="category-box"><i class="{categories.icon} icon-4x"></i></div>
|
||||
<div class="category-box">{categories.description}</div>
|
||||
<div class="category-box" itemprop="description">{categories.description}</div>
|
||||
<!-- BEGIN posts -->
|
||||
<div class="category-box">
|
||||
<div class="post-preview">
|
||||
@@ -26,3 +27,26 @@
|
||||
</div>
|
||||
<!-- END categories -->
|
||||
</div>
|
||||
|
||||
<div class="row footer-stats">
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_online"></span><br /><small>[[footer:stats.online]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_users"></span><br /><small>[[footer:stats.users]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_topics"></span><br /><small>[[footer:stats.topics]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="stats-card well">
|
||||
<h2><span id="stats_posts"></span><br /><small>[[footer:stats.posts]]</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
<link rel="stylesheet" href="/vendor/fontawesome/css/font-awesome.min.css">
|
||||
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
|
||||
<script type="text/javascript" src="/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js"></script>
|
||||
<script type="text/javascript" src="/vendor/jquery/js/jquery.form.js"></script>
|
||||
<script type="text/javascript" src="/vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
|
||||
<script type="text/javascript" src="/src/app.js"></script>
|
||||
<script type="text/javascript" src="/src/templates.js"></script>
|
||||
<script type="text/javascript" src="/src/ajaxify.js"></script>
|
||||
<script type="text/javascript" src="/src/jquery.form.js"></script>
|
||||
<script type="text/javascript" src="/src/utils.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css" />
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<h1>User Privilege Thresholds</h1>
|
||||
|
||||
<form class="form-inline">
|
||||
@@ -15,13 +14,13 @@
|
||||
<label>Manage Content</label> <input type="number" class="input-mini" value="1000" placeholder="1000" data-field="privileges:manage_content" />
|
||||
</p>
|
||||
<p>
|
||||
Users with reach the "Manage Content" threshold are able to edit/delete other users' posts.
|
||||
Users who reach the "Manage Content" threshold are able to edit/delete other users' posts.
|
||||
</p>
|
||||
<p>
|
||||
<label>Manage Topics</label> <input type="number" class="input-mini" value="2000" placeholder="2000" data-field="privileges:manage_topic" />
|
||||
</p>
|
||||
<p>
|
||||
Users with reach the "Manage Topics" threshold are able to edit, lock, pin, close, and delete topics.
|
||||
Users who reach the "Manage Topics" threshold are able to edit, lock, pin, close, and delete topics.
|
||||
</p>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-primary" id="login" type="submit">[[login:login]]</button> <a href="/reset">[[login:forgot_password]]</a>
|
||||
<button class="btn btn-primary" id="login" type="submit">[[login:login]]</button> <a id="reset-link" class="hide" href="/reset">[[login:forgot_password]]</a>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="_csrf" value="{token}" id="csrf-token" />
|
||||
@@ -60,5 +60,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/login.js"></script>
|
||||
14
public/templates/notifications.tpl
Normal file
14
public/templates/notifications.tpl
Normal file
@@ -0,0 +1,14 @@
|
||||
<h2>[[notifications:title]]</h2>
|
||||
|
||||
<button type="button" class="btn btn-default" id="mark-all-notifs-read">Mark All as Read</button>
|
||||
|
||||
<ul class="notifications-list">
|
||||
<!-- BEGIN notifications -->
|
||||
<li data-nid="{notifications.nid}" class="{notifications.readClass}">
|
||||
<a href="{notifications.path}">{notifications.text}</a>
|
||||
<p class="timestamp">
|
||||
<span class="timeago" title="{notifications.datetimeISO}"></span>
|
||||
</p>
|
||||
</li>
|
||||
<!-- END notifications -->
|
||||
</ul>
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
<div class="well">
|
||||
<h3>
|
||||
You are now leaving NodeBB.
|
||||
You are now leaving {title}.
|
||||
</h3>
|
||||
<p>
|
||||
<a href="{url}" rel="nofollow" class="btn btn-primary btn-lg">Continue to {url}</a>
|
||||
<a id="return-btn" href="#" class="btn btn-lg btn-warning">Return to NodeBB</a>
|
||||
<a id="return-btn" href="#" class="btn btn-lg btn-warning">Return to {title}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="/">Home</a></li>
|
||||
<li class="active">{category_name}</li>
|
||||
<div id="category_active_users"></div>
|
||||
<li class="active">Recent <a href="./recent.rss"><i class="icon-rss-sign"></i></a></li>
|
||||
</ol>
|
||||
|
||||
<ul class="nav nav-pills">
|
||||
<li class=''><a href='/recent/day'>[[recent:day]]</a></li>
|
||||
<li class=''><a href='/recent/week'>[[recent:week]]</a></li>
|
||||
<li class=''><a href='/recent/month'>[[recent:month]]</a></li>
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<a href="/recent">
|
||||
<div class="alert hide" id="new-topics-alert"></div>
|
||||
<div class="alert alert-warning hide" id="new-topics-alert"></div>
|
||||
</a>
|
||||
|
||||
<div class="alert alert-warning hide {no_topics_message}" id="category-no-topics">
|
||||
@@ -13,41 +20,57 @@
|
||||
</div>
|
||||
|
||||
<div class="category row">
|
||||
<div class="{topic_row_size}">
|
||||
<div class="col-md-12">
|
||||
<ul id="topics-container">
|
||||
<!-- BEGIN topics -->
|
||||
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
||||
<li class="category-item {topics.deleted-class}">
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-xs-12 topic-row img-thumbnail">
|
||||
<div class="latest-post visible-lg visible-md">
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
<div class="pull-right">
|
||||
<img class="img-rounded" style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
||||
<p>{topics.teaser_text}</p>
|
||||
<p class="meta">
|
||||
<strong>{topics.teaser_username}</strong> posted <span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<a href="../../topic/{topics.slug}">
|
||||
<div>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||
<small>
|
||||
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||
Posted <span class="timeago" title="{topics.relativeTime}"></span> by
|
||||
<strong>{topics.username}</strong>.
|
||||
</small>
|
||||
</div>
|
||||
<h3><span class="topic-title"><strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong> {topics.title}</span></h3>
|
||||
</a>
|
||||
<small>
|
||||
<span class="topic-stats">
|
||||
posts
|
||||
<strong>{topics.postcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span class="topic-stats">
|
||||
views
|
||||
<strong>{topics.viewcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span>
|
||||
<a href="/user/{topics.userslug}">
|
||||
<img class="teaser-pic" src="{topics.picture}" title="{topics.username}"/>
|
||||
</a>
|
||||
posted in
|
||||
<a href="../../category/{topics.categorySlug}">
|
||||
<i class="{topics.categoryIcon}"></i> {topics.categoryName}
|
||||
</a>
|
||||
<span class="timeago" title="{topics.relativeTime}"></span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="pull-right hidden-xs">
|
||||
<!-- IF topics.unreplied -->
|
||||
No one has replied
|
||||
<!-- ELSE -->
|
||||
<a href="/user/{topics.teaser_userslug}">
|
||||
<img class="teaser-pic" src="{topics.teaser_userpicture}" title="{topics.teaser_username}"/>
|
||||
</a>
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
replied
|
||||
</a>
|
||||
<span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
<!-- ENDIF topics.unreplied -->
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</a>
|
||||
<!-- END topics -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/recent.js"></script>
|
||||
|
||||
@@ -80,5 +80,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/register.js"></script>
|
||||
@@ -26,5 +26,3 @@
|
||||
<button class="btn btn-primary btn-block btn-lg" id="reset" type="submit">Reset Password</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/reset.js"></script>
|
||||
@@ -34,6 +34,3 @@
|
||||
</form>
|
||||
</div>
|
||||
<input type="hidden" template-variable="reset_code" value="{reset_code}" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/reset_code.js"></script>
|
||||
@@ -53,5 +53,3 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/search.js"></script>
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
<div class="topic">
|
||||
<input type="hidden" template-variable="expose_tools" value="{expose_tools}" />
|
||||
<input type="hidden" template-variable="topic_id" value="{topic_id}" />
|
||||
<input type="hidden" template-variable="locked" value="{locked}" />
|
||||
<input type="hidden" template-variable="deleted" value="{deleted}" />
|
||||
<input type="hidden" template-variable="pinned" value="{pinned}" />
|
||||
<input type="hidden" template-variable="topic_name" value="{topic_name}" />
|
||||
<input type="hidden" template-variable="postcount" value="{postcount}" />
|
||||
<input type="hidden" template-variable="twitter-intent-url" value="{twitter-intent-url}" />
|
||||
<input type="hidden" template-variable="facebook-share-url" value="{facebook-share-url}" />
|
||||
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
|
||||
|
||||
<div class="topic row">
|
||||
<ol class="breadcrumb">
|
||||
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
|
||||
@@ -9,26 +20,30 @@
|
||||
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||
<span itemprop="title">{topic_name} <a target="_blank" href="../{topic_id}.rss"><i class="icon-rss-sign"></i></a></span>
|
||||
</li>
|
||||
<div id="thread_active_users" class="active-users pull-right hidden-xs"></div>
|
||||
|
||||
</ol>
|
||||
|
||||
<ul id="post-container" class="container" data-tid="{topic_id}">
|
||||
<!-- BEGIN main_posts -->
|
||||
|
||||
<li class="row post-row main-post infiniteloaded" data-pid="{main_posts.pid}" data-uid="{main_posts.uid}" data-username="{main_posts.username}" data-deleted="{main_posts.deleted}" itemscope itemtype="http://schema.org/Article">
|
||||
<a id="post_anchor_{main_posts.pid}" name="{main_posts.pid}"></a>
|
||||
<li class="row post-row main-post" data-pid="{main_posts.pid}" data-uid="{main_posts.uid}" data-username="{main_posts.username}" data-deleted="{main_posts.deleted}">
|
||||
<div class="col-md-12">
|
||||
<div class="post-block">
|
||||
<meta itemprop="datePublished" content="{main_posts.relativeTime}">
|
||||
<meta itemprop="dateModified" content="{main_posts.relativeEditTime}">
|
||||
<meta itemprop="url" content="/topic/{slug}/">
|
||||
<a class="avatar" href="/user/{main_posts.userslug}">
|
||||
<img src="{main_posts.picture}" align="left" class="img-thumbnail" width=150 height=150 /><br />
|
||||
<img itemprop="image" src="{main_posts.picture}" align="left" class="img-thumbnail" width=150 height=150 /><br />
|
||||
</a>
|
||||
<h3>
|
||||
<p id="topic_title_{main_posts.pid}" class="topic-title">{topic_name}</p>
|
||||
<p id="topic_title_{main_posts.pid}" class="topic-title" itemprop="name">{topic_name}</p>
|
||||
</h3>
|
||||
|
||||
<div class="topic-buttons">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" type="button" title="[[topic:posted_by]] {main_posts.username}">
|
||||
<span class="username-field" href="/user/{main_posts.userslug}">{main_posts.username} </span>
|
||||
<span class="username-field" href="/user/{main_posts.userslug}" itemprop="author" itemscope itemtype="http://schema.org/Person">{main_posts.username} </span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@@ -49,20 +64,29 @@
|
||||
<button class="btn btn-sm btn-primary btn post_reply" type="button">[[topic:reply]] <i class="icon-reply"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="btn-group pull-right post-tools">
|
||||
<div class="pull-right">
|
||||
<div class="btn-group post-tools">
|
||||
<button class="btn btn-sm btn-default link" type="button" title="[[topic:link]]"><i class="icon-link"></i></button>
|
||||
<button class="btn btn-sm btn-default facebook-share" type="button" title=""><i class="icon-facebook"></i></button>
|
||||
<button class="btn btn-sm btn-default twitter-share" type="button" title=""><i class="icon-twitter"></i></button>
|
||||
<button class="btn btn-sm btn-default google-share" type="button" title=""><i class="icon-google-plus"></i></button>
|
||||
</div>
|
||||
<div class="btn-group post-tools">
|
||||
<button class="btn btn-sm btn-default edit {main_posts.display_moderator_tools}" type="button" title="[[topic:edit]]"><i class="icon-pencil"></i></button>
|
||||
<button class="btn btn-sm btn-default delete {main_posts.display_moderator_tools}" type="button" title="[[topic:delete]]"><i class="icon-trash"></i></button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="post_{main_posts.pid}_link" value="" class="pull-right" style="display:none;"></input>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content_{main_posts.pid}" class="post-content">{main_posts.content}</div>
|
||||
<div id="content_{main_posts.pid}" class="post-content" itemprop="articleBody">{main_posts.content}</div>
|
||||
<div class="post-signature">{main_posts.signature}</div>
|
||||
<div class="post-info">
|
||||
<span class="pull-left">
|
||||
{main_posts.additional_profile_info}
|
||||
</span>
|
||||
<span class="pull-right">
|
||||
posted <span class="relativeTimeAgo timeago" title="{main_posts.relativeTime}"></span>
|
||||
<span class="{main_posts.edited-class}">| last edited by <strong><a href="/user/{main_posts.editorslug}">{main_posts.editorname}</a></strong></span>
|
||||
@@ -75,21 +99,52 @@
|
||||
</li>
|
||||
<!-- END main_posts -->
|
||||
|
||||
<li class="well">
|
||||
<div class="inline-block">
|
||||
<small class="topic-stats">
|
||||
<span>posts</span>
|
||||
<strong><span id="topic-post-count" class="formatted-number">{postcount}</span></strong> |
|
||||
<span>views</span>
|
||||
<strong><span class="formatted-number">{viewcount}</span></strong> |
|
||||
<span>browsing</span>
|
||||
</small>
|
||||
<div class="thread_active_users active-users inline-block"></div>
|
||||
</div>
|
||||
<div class="topic-main-buttons pull-right inline-block">
|
||||
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
|
||||
<div class="btn-group thread-tools hide">
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" class="pin_thread"><i class="icon-pushpin"></i> [[topic:thread_tools.pin]]</a></li>
|
||||
<li><a href="#" class="lock_thread"><i class="icon-lock"></i> [[topic:thread_tools.lock]]</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#" class="move_thread"><i class="icon-move"></i> [[topic:thread_tools.move]]</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#" class="delete_thread"><span class="text-error"><i class="icon-trash"></i> [[topic:thread_tools.delete]]</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</li>
|
||||
|
||||
<!-- BEGIN posts -->
|
||||
|
||||
<li class="row post-row sub-posts infiniteloaded" data-pid="{posts.pid}" data-uid="{posts.uid}" data-username="{posts.username}" data-deleted="{posts.deleted}" itemscope itemtype="http://schema.org/Comment">
|
||||
<a id="post_anchor_{posts.pid}" name="{posts.pid}"></a>
|
||||
<li class="row post-row sub-posts" data-pid="{posts.pid}" data-uid="{posts.uid}" data-username="{posts.username}" data-deleted="{posts.deleted}">
|
||||
<meta itemprop="datePublished" content="{posts.relativeTime}">
|
||||
<meta itemprop="dateModified" content="{posts.relativeEditTime}">
|
||||
<div class="col-md-1 profile-image-block hidden-xs hidden-sm">
|
||||
<a href="/user/{posts.userslug}">
|
||||
<img src="{posts.picture}" align="left" class="img-thumbnail" />
|
||||
</a>
|
||||
<img src="{posts.picture}" align="left" class="img-thumbnail" itemprop="image" />
|
||||
<span class="label label-danger {posts.show_banned}">[[topic:banned]]</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-11">
|
||||
<div class="post-block">
|
||||
<div class="topic-buttons">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" type="button" title="Posted by {posts.username}">
|
||||
<span class="username-field" href="/user/{posts.userslug}">{posts.username} </span>
|
||||
<span class="username-field" href="/user/{posts.userslug}" itemprop="author">{posts.username} </span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
|
||||
@@ -119,9 +174,12 @@
|
||||
<input id="post_{posts.pid}_link" value="" class="pull-right" style="display:none;"></input>
|
||||
</div>
|
||||
|
||||
<div id="content_{posts.pid}" class="post-content">{posts.content}</div>
|
||||
<div id="content_{posts.pid}" class="post-content" itemprop="text">{posts.content}</div>
|
||||
<div class="post-signature">{posts.signature}</div>
|
||||
<div class="post-info">
|
||||
<span class="pull-left">
|
||||
{posts.additional_profile_info}
|
||||
</span>
|
||||
<span class="pull-right">
|
||||
posted <span class="relativeTimeAgo timeago" title="{posts.relativeTime}"></span>
|
||||
<span class="{posts.edited-class}">| last edited by <strong><a href="/user/{posts.editorslug}">{posts.editorname}</a></strong></span>
|
||||
@@ -135,26 +193,26 @@
|
||||
<!-- END posts -->
|
||||
</ul>
|
||||
|
||||
<div id="loading-indicator" style="text-align:center;" class="hide" done="0">
|
||||
<i class="icon-spinner icon-spin icon-large"></i>
|
||||
<div class="well col-md-11 col-xs-12 pull-right hide">
|
||||
<div class="topic-main-buttons pull-right inline-block hide">
|
||||
<div class="loading-indicator" done="0" style="display:none;">
|
||||
Loading More Posts <i class="icon-refresh icon-spin"></i>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="topic-main-buttons">
|
||||
<button id="post_reply" class="btn btn-primary btn-lg post_reply" type="button">[[topic:reply]]</button>
|
||||
<div class="btn-group pull-right" id="thread-tools" style="visibility: hidden;">
|
||||
<button class="btn btn-default btn-lg dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
|
||||
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
|
||||
<div class="btn-group thread-tools hide">
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" id="pin_thread"><i class="icon-pushpin"></i> [[topic:thread_tools.pin]]</a></li>
|
||||
<li><a href="#" id="lock_thread"><i class="icon-lock"></i> [[topic:thread_tools.lock]]</a></li>
|
||||
<li><a href="#" class="pin_thread"><i class="icon-pushpin"></i> [[topic:thread_tools.pin]]</a></li>
|
||||
<li><a href="#" class="lock_thread"><i class="icon-lock"></i> [[topic:thread_tools.lock]]</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#" id="move_thread"><i class="icon-move"></i> [[topic:thread_tools.move]]</a></li>
|
||||
<li><a href="#" class="move_thread"><i class="icon-move"></i> [[topic:thread_tools.move]]</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#" id="delete_thread"><span class="text-error"><i class="icon-trash"></i> [[topic:thread_tools.delete]]</span></a></li>
|
||||
<li><a href="#" class="delete_thread"><span class="text-error"><i class="icon-trash"></i> [[topic:thread_tools.delete]]</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-author-overlay">
|
||||
<div class="row">
|
||||
@@ -167,39 +225,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="move_thread_modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
||||
<div id="move_thread_modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Move Topic" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Move Thread</h3>
|
||||
<h3>Move Topic</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p id="categories-loading"><i class="icon-spin icon-refresh"></i> [[topic:load_categories]]</p>
|
||||
<ul class="category-list"></ul>
|
||||
<p>
|
||||
[[topic:disabled_categories_note]]
|
||||
</p>
|
||||
<div id="move-confirm" style="display: none;">
|
||||
<hr />
|
||||
<div class="alert">This topic will be moved to the category <strong><span id="confirm-category-name"></span></strong></div>
|
||||
<div class="alert alert-info">This topic will be moved to the category <strong><span id="confirm-category-name"></span></strong></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" id="move_thread_cancel">[[global:buttons.close]]</a>
|
||||
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>[[topic:confirm_move]]</a>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" id="move_thread_cancel">[[global:buttons.close]]</button>
|
||||
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>[[topic:confirm_move]]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<input type="hidden" template-variable="expose_tools" value="{expose_tools}" />
|
||||
<input type="hidden" template-variable="topic_id" value="{topic_id}" />
|
||||
<input type="hidden" template-variable="locked" value="{locked}" />
|
||||
<input type="hidden" template-variable="deleted" value="{deleted}" />
|
||||
<input type="hidden" template-variable="pinned" value="{pinned}" />
|
||||
<input type="hidden" template-variable="topic_name" value="{topic_name}" />
|
||||
<input type="hidden" template-variable="postcount" value="{postcount}" />
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/topic.js"></script>
|
||||
@@ -5,54 +5,69 @@
|
||||
<div id="category_active_users"></div>
|
||||
</ol>
|
||||
|
||||
<a href="/unread">
|
||||
<div class="alert hide" id="new-topics-alert"></div>
|
||||
</a>
|
||||
|
||||
<div class="alert alert-warning {no_topics_message}" id="category-no-topics">
|
||||
<strong>[[unread:no_unread_topics]]</strong>
|
||||
</div>
|
||||
|
||||
<button id="mark-allread-btn" class="btn btn-primary {show_markallread_button}">[[unread:mark_all_read]]</button>
|
||||
|
||||
<a href="/unread">
|
||||
<div class="alert alert-warning hide" id="new-topics-alert"></div>
|
||||
</a>
|
||||
|
||||
<div class="category row">
|
||||
<div class="{topic_row_size}">
|
||||
<ul id="topics-container" data-next-start="{nextStart}">
|
||||
<!-- BEGIN topics -->
|
||||
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
||||
<li class="category-item {topics.deleted-class}">
|
||||
<div class="row">
|
||||
<div class="col-md-12 topic-row img-thumbnail">
|
||||
<div class="latest-post visible-lg visible-md">
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
<div class="pull-right">
|
||||
<img class="img-rounded" style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
||||
<p>{topics.teaser_text}</p>
|
||||
<p class="meta">
|
||||
<strong>{topics.teaser_username}</strong> posted <span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-12 topic-row">
|
||||
<a href="../../topic/{topics.slug}">
|
||||
<div>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||
<small>
|
||||
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||
Posted <span class="timeago" title="{topics.relativeTime}"></span> by
|
||||
<strong>{topics.username}</strong>.
|
||||
</small>
|
||||
</div>
|
||||
<h3><span class="topic-title"><strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong> {topics.title}</span></h3>
|
||||
</a>
|
||||
<small>
|
||||
<span class="topic-stats">
|
||||
posts
|
||||
<strong>{topics.postcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span class="topic-stats">
|
||||
views
|
||||
<strong>{topics.viewcount}</strong>
|
||||
</span>
|
||||
|
|
||||
<span>
|
||||
<a href="/user/{topics.userslug}">
|
||||
<img class="img-rounded teaser-pic" src="{topics.picture}" title="{topics.username}"/>
|
||||
</a>
|
||||
posted in
|
||||
<a href="../../category/{topics.categorySlug}">
|
||||
<i class="{topics.categoryIcon}"></i> {topics.categoryName}
|
||||
</a>
|
||||
<span class="timeago" title="{topics.relativeTime}"></span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="pull-right hidden-xs">
|
||||
<!-- IF topics.unreplied -->
|
||||
No one has replied
|
||||
<!-- ELSE -->
|
||||
<a href="/user/{topics.teaser_userslug}">
|
||||
<img class="teaser-pic" src="{topics.teaser_userpicture}" title="{topics.teaser_username}"/>
|
||||
</a>
|
||||
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||
replied
|
||||
</a>
|
||||
<span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||
<!-- ENDIF topics.unreplied -->
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</a>
|
||||
<!-- END topics -->
|
||||
</ul>
|
||||
<button id="load-more-btn" class="btn btn-primary hide">[[unread:load_more]]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/unread.js"></script>
|
||||
@@ -13,14 +13,14 @@
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="search-user" type="text" placeholder="[[users:enter_username]]"/>
|
||||
<span class="input-group-addon">
|
||||
<span id="user-notfound-notify"><i class="icon icon-circle-blank"></i></span>
|
||||
<span id="user-notfound-notify"><i class="icon icon-search"></i></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="users-container" class="users-container">
|
||||
<!-- BEGIN users -->
|
||||
<div class="users-box">
|
||||
<li class="users-box registered-user">
|
||||
<a href="/user/{users.userslug}">
|
||||
<img src="{users.picture}" class="img-thumbnail"/>
|
||||
</a>
|
||||
@@ -29,21 +29,31 @@
|
||||
<a href="/user/{users.userslug}">{users.username}</a>
|
||||
<br/>
|
||||
<div title="reputation" class="reputation">
|
||||
<span class='formatted-number'>{users.reputation}</span>
|
||||
<i class='icon-star'></i>
|
||||
<span class='formatted-number'>{users.reputation}</span>
|
||||
</div>
|
||||
<div title="post count" class="post-count">
|
||||
<span class='formatted-number'>{users.postcount}</span>
|
||||
<i class='icon-pencil'></i>
|
||||
<span class='formatted-number'>{users.postcount}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<!-- END users -->
|
||||
<li class="users-box {show_anon} anon-user">
|
||||
<a href="#">
|
||||
<img src="" class="img-thumbnail"/>
|
||||
</a>
|
||||
<br/>
|
||||
<div class="user-info">
|
||||
<span id="online_anon_count">{anonymousUserCount}</span>
|
||||
<br/>
|
||||
<a href="#">Anonymous</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="text-center {loadmore_display}">
|
||||
<button id="load-more-users-btn" class="btn btn-primary">[[users:load_more]]</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/users.js"></script>
|
||||
@@ -1 +0,0 @@
|
||||
@import "../vanilla/account";
|
||||
@@ -1 +0,0 @@
|
||||
@import "../vanilla/admin";
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
@import "../vanilla/category";
|
||||
@@ -1,18 +0,0 @@
|
||||
@import "../vanilla/mixins";
|
||||
@import "animations";
|
||||
|
||||
@import "style";
|
||||
@import "topic";
|
||||
@import "category";
|
||||
@import "noscript";
|
||||
@import "home";
|
||||
@import "header";
|
||||
@import "account";
|
||||
@import "search";
|
||||
@import "unread";
|
||||
@import "admin";
|
||||
@import "users";
|
||||
@import "outgoing";
|
||||
@import "footer";
|
||||
|
||||
@import "../vanilla/modules.less";
|
||||
@@ -1,9 +0,0 @@
|
||||
@import "../vanilla/footer";
|
||||
|
||||
.footer {
|
||||
color: #555;
|
||||
|
||||
a {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
@import "../vanilla/header";
|
||||
|
||||
.header {
|
||||
//glowing animation for active state
|
||||
.dropdown-toggle {
|
||||
i {
|
||||
@-webkit-keyframes glow
|
||||
{
|
||||
from {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
50% {text-shadow: 0 0 10px #aaf, 0 0 10px #aaf, 0 0 10px #aaf;}
|
||||
to {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
}
|
||||
@keyframes glow
|
||||
{
|
||||
from {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
50% {text-shadow: 0 0 10px #aaf, 0 0 10px #aaf, 0 0 10px #aaf;}
|
||||
to {text-shadow: 0 0 5px #aaf, 0 0 5px #aaf, 0 0 5px #aaf;}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #558;
|
||||
text-shadow: 0 0 1em #aaf, 0 0 1em #aaf, 0 0 1em #aaf;
|
||||
-webkit-animation:glow 1.5s infinite linear;
|
||||
animation:glow 1.5s infinite linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
@import "../vanilla/home";
|
||||
|
||||
|
||||
.home {
|
||||
h4 {
|
||||
color: #555;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import "../vanilla/noscript";
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user