Strange user behavior, model not updating correctly
This commit is contained in:
7
app.js
7
app.js
@ -267,13 +267,13 @@ app.all('/account', passportConf.isAuthenticated);
|
|||||||
app.get('/account/api', userController.getAccountAngular);
|
app.get('/account/api', userController.getAccountAngular);
|
||||||
app.get('/playground', bonfireController.index);
|
app.get('/playground', bonfireController.index);
|
||||||
app.get(
|
app.get(
|
||||||
'/bonfires/:bonfireNumber',
|
'/bonfires/:bonfireName',
|
||||||
bonfireController.returnIndividualBonfire
|
bonfireController.returnIndividualBonfire
|
||||||
);
|
);
|
||||||
app.get('/bonfire', function(req, res) {
|
app.get('/bonfire', function(req, res) {
|
||||||
res.redirect(301, '/playground');
|
res.redirect(301, '/playground');
|
||||||
});
|
});
|
||||||
app.get('/bonfires', bonfireController.returnBonfire);
|
app.get('/bonfires', bonfireController.returnNextBonfire);
|
||||||
app.get('/bonfire/generator', bonfireController.returnGenerator);
|
app.get('/bonfire/generator', bonfireController.returnGenerator);
|
||||||
app.post('/bonfire/generator', bonfireController.generateChallenge);
|
app.post('/bonfire/generator', bonfireController.generateChallenge);
|
||||||
app.get('/bonfire/public-generator', bonfireController.publicGenerator);
|
app.get('/bonfire/public-generator', bonfireController.publicGenerator);
|
||||||
@ -311,8 +311,6 @@ app.post('/completed-challenge', function (req, res) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post('/completed-bonfire/', function (req, res) {
|
app.post('/completed-bonfire/', function (req, res) {
|
||||||
debug(req.body, 'In post method'
|
|
||||||
); // TODO: remove debug statement
|
|
||||||
req.user.bonfiresHash[parseInt(req.body.bonfireNumber)] =
|
req.user.bonfiresHash[parseInt(req.body.bonfireNumber)] =
|
||||||
Math.round(+new Date() / 1000);
|
Math.round(+new Date() / 1000);
|
||||||
var timestamp = req.user.bonfiresHash;
|
var timestamp = req.user.bonfiresHash;
|
||||||
@ -364,6 +362,7 @@ app.post('/completed-bonfire/', function (req, res) {
|
|||||||
};
|
};
|
||||||
req.user.save();
|
req.user.save();
|
||||||
}
|
}
|
||||||
|
bonfireController.returnNextBonfire(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,26 +8,26 @@ var _ = require('lodash'),
|
|||||||
* Bonfire controller
|
* Bonfire controller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var highestBonfireNumber = 2;
|
var highestBonfireNumber = resources.numberOfBonfires();
|
||||||
|
|
||||||
exports.index = function(req, res) {
|
exports.index = function(req, res) {
|
||||||
res.render('bonfire/bonfire.jade', {
|
res.render('bonfire/show.jade', {
|
||||||
title: 'Learn to code with Bonfire',
|
|
||||||
completedWith: null,
|
completedWith: null,
|
||||||
title: null,
|
title: 'Bonfire Playground',
|
||||||
difficulty: null,
|
name: 'Bonfire Playground',
|
||||||
brief: null,
|
difficulty: 0,
|
||||||
details: null,
|
brief: 'Feel free to play around!',
|
||||||
tests: null,
|
details: '',
|
||||||
challengeSeed: null,
|
tests: [],
|
||||||
challengeEntryPoint: null,
|
challengeSeed: '',
|
||||||
|
challengeEntryPoint: '',
|
||||||
cc: req.user ? req.user.bonfiresHash : undefined,
|
cc: req.user ? req.user.bonfiresHash : undefined,
|
||||||
points: req.user ? req.user.points : undefined,
|
points: req.user ? req.user.points : undefined,
|
||||||
verb: resources.randomVerb(),
|
verb: resources.randomVerb(),
|
||||||
phrase: resources.randomPhrase(),
|
phrase: resources.randomPhrase(),
|
||||||
compliment: resources.randomCompliment(),
|
compliments: resources.randomCompliment(),
|
||||||
bonfires: [],
|
bonfires: [],
|
||||||
bonfireHash: "test"
|
bonfireHash: 'test'
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,11 +39,12 @@ exports.index = function(req, res) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.returnBonfire = function(req, res, next) {
|
exports.returnNextBonfire = function(req, res, next) {
|
||||||
|
var bonfireNumber;
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
req.user = new User();
|
req.user = new User();
|
||||||
|
//return res.redirect('/bonfires/meet-bonfire');
|
||||||
}
|
}
|
||||||
var bonfireNumber = parseInt(req.params.bonfireNumber) || 0;
|
|
||||||
// This code is in bad need of refactoring
|
// This code is in bad need of refactoring
|
||||||
var bonfiresToFind = req.user ? req.user.bonfiresHash : [];
|
var bonfiresToFind = req.user ? req.user.bonfiresHash : [];
|
||||||
var bonfiresArray = _.map(bonfiresToFind, function(value, index) {
|
var bonfiresArray = _.map(bonfiresToFind, function(value, index) {
|
||||||
@ -51,48 +52,65 @@ exports.returnBonfire = function(req, res, next) {
|
|||||||
});
|
});
|
||||||
// Get rid of the first entry, which will be a useless function that causes an error.
|
// Get rid of the first entry, which will be a useless function that causes an error.
|
||||||
bonfiresArray.shift();
|
bonfiresArray.shift();
|
||||||
unsolvedBonfires = [];
|
var unsolvedBonfires = [];
|
||||||
for (i = 0; i < bonfiresArray.length; i++) {
|
for (i = 0; i < bonfiresArray.length; i++) {
|
||||||
if (bonfiresArray[i][1]["completedDate"] === 0) {
|
if (bonfiresArray[i][1]["completedDate"] === 0) {
|
||||||
unsolvedBonfires.push(bonfiresArray[i][0])
|
unsolvedBonfires.push(bonfiresArray[i][0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//.where('likes').in(['vaporizing', 'talking'])
|
|
||||||
var displayedBonfires = Bonfire.find({}).where('_id').in(unsolvedBonfires).sort({ difficulty: 1 });
|
var displayedBonfires = Bonfire.find({}).where('_id').in(unsolvedBonfires).sort({ difficulty: 1 });
|
||||||
displayedBonfires.exec(function(err, bonfire) {
|
displayedBonfires.exec(function(err, bonfire) {
|
||||||
if (err) {
|
if (err) {
|
||||||
next(err);
|
next(err);
|
||||||
}
|
}
|
||||||
res.render('bonfire/show', {
|
debug('Finding next bonfire for user', bonfire);
|
||||||
completedWith: null,
|
nameString = bonfire[0].name.toLowerCase().replace(/\s/g, '-');
|
||||||
title: bonfire[bonfireNumber].name,
|
return res.redirect('/bonfires/' + nameString);
|
||||||
name: bonfire[bonfireNumber].name,
|
//res.render('bonfire/show', {
|
||||||
difficulty: +bonfire[bonfireNumber].difficulty,
|
// completedWith: null,
|
||||||
brief: bonfire[bonfireNumber].description[0],
|
// title: bonfire[bonfireNumber].name,
|
||||||
details: bonfire[bonfireNumber].description.slice(1),
|
// name: bonfire[bonfireNumber].name,
|
||||||
tests: bonfire[bonfireNumber].tests,
|
// difficulty: +bonfire[bonfireNumber].difficulty,
|
||||||
challengeSeed: bonfire[bonfireNumber].challengeSeed,
|
// brief: bonfire[bonfireNumber].description[0],
|
||||||
challengeEntryPoint: bonfire[bonfireNumber].challengeEntryPoint,
|
// details: bonfire[bonfireNumber].description.slice(1),
|
||||||
cc: req.user ? req.user.bonfiresHash : undefined,
|
// tests: bonfire[bonfireNumber].tests,
|
||||||
points: req.user ? req.user.points : undefined,
|
// challengeSeed: bonfire[bonfireNumber].challengeSeed,
|
||||||
verb: resources.randomVerb(),
|
// challengeEntryPoint: bonfire[bonfireNumber].challengeEntryPoint,
|
||||||
phrase: resources.randomPhrase(),
|
// cc: req.user ? req.user.bonfiresHash : undefined,
|
||||||
compliments: resources.randomCompliment(),
|
// points: req.user ? req.user.points : undefined,
|
||||||
bonfires: bonfire,
|
// verb: resources.randomVerb(),
|
||||||
bonfireHash: bonfire[bonfireNumber]._id
|
// phrase: resources.randomPhrase(),
|
||||||
});
|
// compliments: resources.randomCompliment(),
|
||||||
|
// bonfires: bonfire,
|
||||||
|
// bonfireHash: bonfire[bonfireNumber]._id
|
||||||
|
//});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.returnIndividualBonfire = function(req, res, next) {
|
exports.returnIndividualBonfire = function(req, res, next) {
|
||||||
var bonfireNumber = parseInt(req.params.bonfireNumber) || 0;
|
var bonfireName = req.params.bonfireName;
|
||||||
|
debug('Getting this as argument for bonfireName', bonfireName);
|
||||||
|
//if (!/[a-z\-]+/i.test(bonfireName)) {
|
||||||
|
// bonfireName = 'meet bonfire';
|
||||||
|
//}
|
||||||
|
|
||||||
if (bonfireNumber > highestBonfireNumber) { bonfireNumber = 0; }
|
bonfireName = bonfireName.replace(/\-/g, ' ');
|
||||||
Bonfire.find({}, null, { sort: { difficulty: 1 } }, function(err, bonfire) {
|
debug('Checking sanity of name of bonfire after replacing "-" characters', bonfireName);
|
||||||
|
var bonfireNumber = 0;
|
||||||
|
|
||||||
|
Bonfire.find({"name" : new RegExp(bonfireName, 'i')}, function(err, bonfire) {
|
||||||
if (err) {
|
if (err) {
|
||||||
next(err);
|
next(err);
|
||||||
}
|
}
|
||||||
|
if (bonfire.length < 1) {
|
||||||
|
debug('Full Bonfire', bonfire);
|
||||||
|
req.flash('errors', {
|
||||||
|
msg: "404: We couldn't find a bonfire with that name. Please double check the name."
|
||||||
|
});
|
||||||
|
return res.redirect('/bonfires/meet-bonfire')
|
||||||
|
}
|
||||||
res.render('bonfire/show', {
|
res.render('bonfire/show', {
|
||||||
completedWith: null,
|
completedWith: null,
|
||||||
title: bonfire[bonfireNumber].name,
|
title: bonfire[bonfireNumber].name,
|
||||||
@ -137,8 +155,8 @@ exports.returnGenerator = function(req, res) {
|
|||||||
|
|
||||||
function randomString() {
|
function randomString() {
|
||||||
var chars = "0123456789abcdef";
|
var chars = "0123456789abcdef";
|
||||||
var string_length = 24;
|
var string_length = 23;
|
||||||
var randomstring = '';
|
var randomstring = 'a';
|
||||||
for (var i=0; i<string_length; i++) {
|
for (var i=0; i<string_length; i++) {
|
||||||
var rnum = Math.floor(Math.random() * chars.length);
|
var rnum = Math.floor(Math.random() * chars.length);
|
||||||
randomstring += chars.substring(rnum,rnum+1);
|
randomstring += chars.substring(rnum,rnum+1);
|
||||||
|
@ -4,6 +4,7 @@ var User = require('../models/User'),
|
|||||||
steps = resources.steps,
|
steps = resources.steps,
|
||||||
secrets = require('./../config/secrets'),
|
secrets = require('./../config/secrets'),
|
||||||
Challenge = require('./../models/Challenge'),
|
Challenge = require('./../models/Challenge'),
|
||||||
|
bonfires = require('../seed_data/bonfires.json');
|
||||||
Client = require('node-rest-client').Client,
|
Client = require('node-rest-client').Client,
|
||||||
client = new Client();
|
client = new Client();
|
||||||
|
|
||||||
@ -182,6 +183,10 @@ module.exports = {
|
|||||||
randomCompliment: function() {
|
randomCompliment: function() {
|
||||||
var compliments = resources.compliments;
|
var compliments = resources.compliments;
|
||||||
return compliments[Math.floor(Math.random() * compliments.length)];
|
return compliments[Math.floor(Math.random() * compliments.length)];
|
||||||
|
},
|
||||||
|
|
||||||
|
numberOfBonfires: function() {
|
||||||
|
return bonfires.length - 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -354,6 +354,60 @@ var userSchema = new mongoose.Schema({
|
|||||||
resetPasswordToken: String,
|
resetPasswordToken: String,
|
||||||
resetPasswordExpires: Date,
|
resetPasswordExpires: Date,
|
||||||
bonfiresHash: {
|
bonfiresHash: {
|
||||||
|
ab6137d4e35944e21037b769: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
|
a3566b1109230028080c9345: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
|
a26cbbe9ad8655a977e1ceb5: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
|
a302f7aae1aa3152a5b413bc: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
|
a202eed8fc186c8434cb6d61: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
|
aff0395860f5d3034dc0bfc9: {
|
||||||
|
hash: String,
|
||||||
|
completedWith: String,
|
||||||
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
|
},
|
||||||
aaa48de84e1ecc7c742e1124: {
|
aaa48de84e1ecc7c742e1124: {
|
||||||
hash: String,
|
hash: String,
|
||||||
completedWith: String,
|
completedWith: String,
|
||||||
@ -363,7 +417,7 @@ var userSchema = new mongoose.Schema({
|
|||||||
},
|
},
|
||||||
solution: String
|
solution: String
|
||||||
},
|
},
|
||||||
ff0395860f5d3034dc0bfc94: {
|
ad7123c8c441eddfaeb5bdef: {
|
||||||
hash: String,
|
hash: String,
|
||||||
completedWith: String,
|
completedWith: String,
|
||||||
completedDate: {
|
completedDate: {
|
||||||
|
@ -25,8 +25,7 @@ editor.setSize("100%", "auto");
|
|||||||
// Default value for editor if one isn't provided in (i.e. a challenge)
|
// Default value for editor if one isn't provided in (i.e. a challenge)
|
||||||
var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' +
|
var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' +
|
||||||
'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' +
|
'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' +
|
||||||
'Note that you can also write tests using Chai.js\n' +
|
'Note that you can also write tests using Chai.js by using the keywords assert and expect */\n\n' +
|
||||||
' by using the keywords assert and expect */\n\n' +
|
|
||||||
'function test() {\n' +
|
'function test() {\n' +
|
||||||
' assert(2 !== 3, "2 is not equal to 3");\n' +
|
' assert(2 !== 3, "2 is not equal to 3");\n' +
|
||||||
' return [1,2,3].map(function(elem) {\n' +
|
' return [1,2,3].map(function(elem) {\n' +
|
||||||
@ -37,8 +36,7 @@ var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByt
|
|||||||
'assert.deepEqual(test(), [1,4,9]);\n\n' +
|
'assert.deepEqual(test(), [1,4,9]);\n\n' +
|
||||||
'var foo = test();\n' +
|
'var foo = test();\n' +
|
||||||
'foo.should.be.a("array");\n\n' +
|
'foo.should.be.a("array");\n\n' +
|
||||||
'test();\n' +
|
'test();\n';
|
||||||
'function test(str) {\r\n return str;\r\n}';
|
|
||||||
|
|
||||||
var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), {
|
var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), {
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"_id" : "7123c8c441eddfaeb5bdef0d",
|
"_id" : "ad7123c8c441eddfaeb5bdef",
|
||||||
"name": "Meet Bonfire",
|
"name": "Meet Bonfire",
|
||||||
"difficulty": "0",
|
"difficulty": "0",
|
||||||
"description": [
|
"description": [
|
||||||
@ -40,7 +40,7 @@
|
|||||||
"challengeEntryPoint": "palindrome(\"eye\");"
|
"challengeEntryPoint": "palindrome(\"eye\");"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id" : "ff0395860f5d3034dc0bfc94",
|
"_id" : "aff0395860f5d3034dc0bfc9",
|
||||||
"name": "Validate US Telephone Numbers",
|
"name": "Validate US Telephone Numbers",
|
||||||
"difficulty": "3",
|
"difficulty": "3",
|
||||||
"description": [
|
"description": [
|
||||||
@ -77,7 +77,7 @@
|
|||||||
"challengeEntryPoint": "telephoneCheck(\"555-555-5555\");"
|
"challengeEntryPoint": "telephoneCheck(\"555-555-5555\");"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "202eed8fc186c8434cb6d618",
|
"_id": "a202eed8fc186c8434cb6d61",
|
||||||
"name": "Reverse a String",
|
"name": "Reverse a String",
|
||||||
"difficulty": "1",
|
"difficulty": "1",
|
||||||
"tests": [
|
"tests": [
|
||||||
@ -95,7 +95,7 @@
|
|||||||
"challengeSeed": "function reverseString(str) {\n return str;\r\n}"
|
"challengeSeed": "function reverseString(str) {\n return str;\r\n}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "302f7aae1aa3152a5b413bca",
|
"_id": "a302f7aae1aa3152a5b413bc",
|
||||||
"name": "Factorialize a Number",
|
"name": "Factorialize a Number",
|
||||||
"tests": [
|
"tests": [
|
||||||
"expect(factorialize(5)).to.be.a(\"Number\");",
|
"expect(factorialize(5)).to.be.a(\"Number\");",
|
||||||
@ -132,7 +132,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "3566b1109230028080c9345d",
|
"_id": "a3566b1109230028080c9345",
|
||||||
"name": "Sum All Numbers in a Range",
|
"name": "Sum All Numbers in a Range",
|
||||||
"difficulty": "2",
|
"difficulty": "2",
|
||||||
"description": [
|
"description": [
|
||||||
@ -150,7 +150,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "fb6137d4e35944e21037b769",
|
"_id": "ab6137d4e35944e21037b769",
|
||||||
"name": "Title Case a Sentence",
|
"name": "Title Case a Sentence",
|
||||||
"difficulty": "1",
|
"difficulty": "1",
|
||||||
"description": [
|
"description": [
|
||||||
|
@ -23,43 +23,43 @@ block content
|
|||||||
.col-xs-12.col-sm-12.col-md-3
|
.col-xs-12.col-sm-12.col-md-3
|
||||||
#testCreatePanel
|
#testCreatePanel
|
||||||
h2.text-center #{name}
|
h2.text-center #{name}
|
||||||
Difficulty
|
Difficulty
|
||||||
if (difficulty == "0")
|
if (difficulty == "0")
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
if (difficulty == "1")
|
if (difficulty == "1")
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
if (difficulty == "2")
|
if (difficulty == "2")
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
if (difficulty == "3")
|
if (difficulty == "3")
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
if (difficulty == "4")
|
if (difficulty == "4")
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame-outline
|
i.ion-ios-flame-outline
|
||||||
if (difficulty == "5")
|
if (difficulty == "5")
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
i.ion-ios-flame
|
i.ion-ios-flame
|
||||||
.well
|
.well
|
||||||
.row.text-center
|
.row.text-center
|
||||||
row.text-center
|
row.text-center
|
||||||
|
Reference in New Issue
Block a user