Create and list clans

Replace mock data with some real functionality.
This commit is contained in:
Matt Lott 2015-04-01 11:56:48 -07:00
parent 32b48a3c4c
commit 482b66b8a4
12 changed files with 257 additions and 111 deletions

7
app/models/Clan.coffee Normal file
View file

@ -0,0 +1,7 @@
CocoModel = require './CocoModel'
schema = require 'schemas/models/clan.schema'
module.exports = class Clan extends CocoModel
@className: 'Clan'
@schema: schema
urlRoot: '/db/clan'

View file

@ -0,0 +1,23 @@
c = require './../schemas'
ClanSchema = c.object {title: 'Clan', required: ['name', 'type']}
c.extendNamedProperties ClanSchema # name first
_.extend ClanSchema.properties,
name: c.shortString()
type: {type: 'string', 'enum': ['public']}
ownerID: c.objectId()
ownerName: c.shortString()
members: c.array {title: 'Members'},
c.object {required: ['id', 'name', 'level']},
id: c.objectId()
name: c.shortString()
level: {type: 'integer'}
c.extendBasicProperties ClanSchema, 'Clan'
# Do we need these?
# c.extendSearchableProperties ClanSchema
# c.extendPermissionsProperties ClanSchema
module.exports = ClanSchema

View file

@ -2,41 +2,36 @@ extends /templates/base
block content
ol.breadcrumb
li
a(href="/")
span.glyphicon.glyphicon-home
li
a(href="/clans") Clans
li.active= clan.title
h1= clan.title
h1= clan.get('name')
span.spr.spl.small (owner
a(href="/user/#{clan.get('ownerID')}")= clan.get('ownerName')
| )
div
span Owner:
a(href="/user/#{clan.ownerID}")= clan.owner
div Members: #{clan.memberCount}
if clan.owner === 'mrsmith'
div
if isOwner
button.btn.btn-sm.btn-warning Delete Clan
else if isMember
button.btn.btn-sm.btn-warning Leave Clan
else
button.btn.btn-sm.btn-success Join Clan
h3 Clan Members
table.table.table-striped.table-condensed
thead
tr
th Name
th Level
th
tbody
each member in members
if clan.get('members')
h3 Clan Members (#{clan.get('members').length})
table.table.table-striped.table-condensed
thead
tr
td
a(href="/user/#{member.id}")= member.name
td= member.level
if member.name !== clan.owner && clan.owner === 'mrsmith'
td
button.btn.btn-sm.btn-warning Remove Member
else
th Name
th Level
th
tbody
each member in clan.get('members')
tr
td
a(href="/user/#{member.id}")= member.name
td= member.level
if member.id !== clan.get('ownerID')
td
button.btn.btn-sm.btn-warning Remove Member
else
td
button.btn.btn-sm Load More
button.btn.btn-sm Load More

View file

@ -2,16 +2,10 @@ extends /templates/base
block content
ol.breadcrumb
li
a(href="/")
span.glyphicon.glyphicon-home
li.active Clans
div
button.btn.btn-sm.btn-success Create New Clan
button.btn.btn-sm.btn-success.create-clan-btn Create New Clan
span.spr.spl
input(type='text' placeholder='New clan name')
input.create-clan-name(type='text' placeholder='New clan name')
br
div(role='tabpanel')
@ -31,21 +25,23 @@ block content
th Owner
th
tbody
each clan in publicClans
tr
td
if clan.owner === 'mrsmith'
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.title
else
a(href="/clans/#{clan.id}")= clan.title
td= clan.memberCount
td
a(href="/user/#{clan.ownerID}")= clan.owner
td
if !clan.member
button.btn.btn-sm.btn-success Join Clan
else if clan.owner !== 'mrsmith'
button.btn.btn-sm.btn-warning Leave Clan
if publicClans.length
each clan in publicClans
tr
td
if clan.get('ownerID') === me.id
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.get('name')
else
a(href="/clans/#{clan.id}")= clan.get('name')
td= clan.get('members').length
td
a(href="/user/#{clan.ownerID}")= clan.get('ownerName')
td
if myClanIDs.indexOf(clan.id) < 0
button.btn.btn-sm.btn-success Join Clan
else if clan.get('ownerID') !== me.id
button.btn.btn-sm.btn-warning Leave Clan
button.btn.btn-sm Load More
.tab-pane#my-clans(role='tabpanel')
@ -57,18 +53,16 @@ block content
th Owner
th
tbody
each clan in myClans
tr
td
if clan.owner === 'mrsmith'
a(href="/clans/#{clan.id}", style='font-weight:bold')= clan.title
else
a(href="/clans/#{clan.id}")= clan.title
td= clan.memberCount
td
a(href="/user/#{clan.ownerID}")= clan.owner
td
if clan.owner !== 'mrsmith'
button.btn.btn-sm.btn-warning Leave Clan
if myClans.length
each clan in myClans
tr
td
a(href="/clans/#{clan.id}")= clan.get('name')
td= clan.get('members').length
td
a(href="/user/#{clan.ownerID}")= clan.get('ownerName')
td
if clan.get('ownerID') !== me.id
button.btn.btn-sm.btn-warning Leave Clan
button.btn.btn-sm Load More

View file

@ -1,5 +1,6 @@
RootView = require 'views/core/RootView'
template = require 'templates/clans/clan-details'
Clan = require 'models/Clan'
module.exports = class ClanDetailsView extends RootView
id: 'clan-details-view'
@ -7,24 +8,12 @@ module.exports = class ClanDetailsView extends RootView
constructor: (options, @clanID) ->
super options
@initMockData()
@clan = new Clan _id: @clanID
@supermodel.loadModel @clan, 'clan', cache: false
getRenderData: =>
context = super()
context.clan = @clan
context.members = @members
context.isOwner = @clan.get('ownerID') is me.id
context.isMember = _.find(@clan.get('members'), (m) -> m.id is me.id) ? false
context
initMockData: ->
@clan =
title: 'Slay more munchkins'
owner: 'mrsmith'
memberCount: 8
ownerID: me.get('_id')
@members = [
{id: me.get('_id'), name: 'mrsmith', level: 24}
{id: me.get('_id'), name: 'Superman', level: 2}
{id: me.get('_id'), name: 'batman', level: 1}
{id: me.get('_id'), name: 'Bruce', level: 4}
]

View file

@ -1,41 +1,40 @@
app = require 'core/application'
RootView = require 'views/core/RootView'
template = require 'templates/clans/clans'
CocoCollection = require 'collections/CocoCollection'
Clan = require 'models/Clan'
module.exports = class MainAdminView extends RootView
id: 'clans-view'
template: template
events:
'click .clan-title': 'onClickClanTitle'
'click .create-clan-btn': 'onClickCreateClan'
constructor: (options) ->
super options
@initMockData()
@publicClans = new CocoCollection([], { url: '/db/clan', model: Clan, comparator:'_id' })
@supermodel.loadCollection(@publicClans, 'public_clans', {cache: false})
getRenderData: ->
context = super()
context.myClans = @myClans
context.publicClans = @publicClans
context.publicClans = @publicClans.models
context.myClans = @publicClans.where({ownerID: me.get('_id')})
context.myClanIDs = _.map context.myClans, (c) -> c.id
context
onClickClanTitle: (e) ->
if clanID = $(e.target).data('id')
app.router.navigate "/clans/#{clanID}"
onClickCreateClan: (e) ->
if name = $('.create-clan-name').val()
# TODO: async creating message
clan = new Clan()
clan.set 'type', 'public'
clan.set 'name', name
clan.save {},
error: (model, response, options) =>
console.error 'Error saving clan', response
success: (model, response, options) =>
app.router.navigate "/clans/#{model.id}"
window.location.reload()
else
console.error "No clan ID found for public clan row."
initMockData: ->
@myClans = [
{id: 1, title: 'FC Dallas', owner: 'soccerfan', memberCount: 4, member: true, ownerID: me.get('_id')}
{id: 2, title: 'Mr. Smith 4th period', owner: 'mrsmith', memberCount: 23, member: true, ownerID: me.get('_id')}
{id: 3, title: 'Test Title 21', owner: 'matt', memberCount: 12, member: true, ownerID: me.get('_id')}
{id: 4, title: 'Slay more munchkins', owner: 'mrsmith', memberCount: 8, member: true, ownerID: me.get('_id')}
]
@publicClans = [
{id: 1, title: 'FC Dallas', owner: 'soccerfan', memberCount: 4, member: true, ownerID: me.get('_id')}
{id: 2, title: 'Mr. Smith 4th period', owner: 'mrsmith', memberCount: 23, member: true, ownerID: me.get('_id')}
{id: 5, title: 'tourney tanks', owner: 'jkl324', memberCount: 7, member: false, ownerID: me.get('_id')}
{id: 6, title: 'Pythonistas', owner: 'bob219', memberCount: 50, member: false, ownerID: me.get('_id')}
]
# TODO: Invalid name message
console.log 'Invalid name'

21
server/clans/Clan.coffee Normal file
View file

@ -0,0 +1,21 @@
mongoose = require 'mongoose'
log = require 'winston'
config = require '../../server_config'
plugins = require '../plugins/plugins'
jsonSchema = require '../../app/schemas/models/clan.schema'
ClanSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
ClanSchema.statics.privateProperties = []
ClanSchema.statics.editableProperties = [
'type'
'name'
'members'
]
ClanSchema.plugin plugins.NamedPlugin
ClanSchema.plugin plugins.SearchablePlugin, {searchable: ['name']}
ClanSchema.statics.jsonSchema = jsonSchema
module.exports = Clan = mongoose.model 'clan', ClanSchema, 'clans'

View file

@ -0,0 +1,31 @@
async = require 'async'
mongoose = require 'mongoose'
Handler = require '../commons/Handler'
Clan = require './Clan'
ClanHandler = class ClanHandler extends Handler
modelClass: Clan
jsonSchema: require '../../app/schemas/models/Clan.schema'
allowedMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
hasAccess: (req) ->
return true if req.method in ['GET']
return true if req.user? and not req.user.isAnonymous()
false
hasAccessToDocument: (req, document, method=null) ->
method = (method or req.method).toLowerCase()
return true if req.user?.isAdmin()
return true if method is 'get'
false
makeNewInstance: (req) ->
instance = super(req)
instance.set 'ownerID', req.user._id
instance.set 'ownerName', req.user.name
instance.set 'members', [
{id: req.user._id, name: req.user.name, level: req.user.level()}
]
instance
module.exports = new ClanHandler()

View file

@ -6,6 +6,7 @@ module.exports.handlers =
# 'analytics_users_active': 'analytics/analytics_users_active_handler'
'article': 'articles/article_handler'
'campaign': 'campaigns/campaign_handler'
'clan': 'clans/clan_handler'
'level': 'levels/level_handler'
'level_component': 'levels/components/level_component_handler'
'level_feedback': 'levels/feedbacks/level_feedback_handler'
@ -22,9 +23,9 @@ module.exports.handlers =
'achievement': 'achievements/achievement_handler'
'earned_achievement': 'achievements/earned_achievement_handler'
'poll': 'polls/poll_handler'
'user_polls_record': 'polls/user_polls_record_handler'
'prepaid': 'prepaids/prepaid_handler'
'subscription': 'payments/subscription_handler'
'user_polls_record': 'polls/user_polls_record_handler'
module.exports.routes =
[

View file

@ -27,6 +27,7 @@ models_path = [
'../../server/analytics/AnalyticsUsersActive'
'../../server/articles/Article'
'../../server/campaigns/Campaign'
'../../server/clans/Clan'
'../../server/levels/Level'
'../../server/levels/components/LevelComponent'
'../../server/levels/systems/LevelSystem'
@ -182,6 +183,10 @@ GLOBAL.loginUser = (user, done) ->
form.append('username', user.get('email'))
form.append('password', user.get('name'))
GLOBAL.logoutUser = (done) ->
request.post getURL('/auth/logout'), ->
done()
GLOBAL.dropGridFS = (done) ->
if mongoose.connection.readyState is 2
mongoose.connection.once 'open', ->

View file

@ -0,0 +1,81 @@
config = require '../../../server_config'
require '../common'
utils = require '../../../app/core/utils' # Must come after require /common
mongoose = require 'mongoose'
describe 'Clans', ->
stripe = require('stripe')(config.stripe.secretKey)
clanURL = getURL('/db/clan')
createClan = (type, name, done) ->
requestBody =
type: type
name: name
request.post {uri: clanURL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.type).toEqual(type)
expect(body.name).toEqual(name)
Clan.findById body._id, (err, clan) ->
expect(clan.get('type')).toEqual(type)
expect(clan.get('name')).toEqual(name)
done(clan)
it 'Clear database users and clans', (done) ->
clearModels [User, Clan], (err) ->
throw err if err
done()
it 'Create clan', (done) ->
loginNewUser (user1) ->
createClan 'public', 'myclan1', (clan) ->
done()
it 'Anonymous create clan 401', (done) ->
logoutUser ->
requestBody =
type: 'public'
name: 'myclan1'
request.post {uri: clanURL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(401)
done()
it 'Create clan missing type 422', (done) ->
loginNewUser (user1) ->
requestBody =
name: 'myclan1'
request.post {uri: clanURL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
done()
it 'Create clan missing name 422', (done) ->
loginNewUser (user1) ->
requestBody =
type: 'public'
request.post {uri: clanURL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
done()
it 'Get clans', (done) ->
loginNewUser (user1) ->
createClan 'public', 'myclan2', ->
createClan 'public', 'myclan3', ->
request.get {uri: clanURL }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.length).toBeGreaterThan(1)
done()
it 'Get clans anonymous', (done) ->
loginNewUser (user1) ->
createClan 'public', 'myclan4', ->
createClan 'public', 'myclan5', ->
logoutUser ->
request.get {uri: clanURL }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.length).toBeGreaterThan(1)
done()

View file

@ -46,7 +46,7 @@ describe '/db/payment', ->
paymentCreated = body?._id
expect(res.statusCode).toBe 201
User.findOne({name:'Joe'}).exec(err, (err, user) ->
expect(user.get('purchased').gems).toBe(5000)
expect(user.get('purchased')?.gems).toBe(5000)
done()
)
@ -56,7 +56,7 @@ describe '/db/payment', ->
expect(body._id is paymentCreated).toBe(true)
expect(res.statusCode).toBe 200
User.findOne({name:'Joe'}).exec(err, (err, user) ->
expect(user.get('purchased').gems).toBe(5000)
expect(user.get('purchased')?.gems).toBe(5000)
done()
)
@ -72,7 +72,7 @@ describe '/db/payment', ->
expect(body._id is paymentCreated).toBe(false)
expect(res.statusCode).toBe 201
User.findOne({name:'Joe'}).exec(err, (err, user) ->
expect(user.get('purchased').gems).toBe(16000)
expect(user.get('purchased')?.gems).toBe(16000)
done()
)