Add mod voting feature
This commit is contained in:
+2
-2
@@ -188,7 +188,7 @@ module.exports = (grunt)->
|
|||||||
tasks: ['sass']
|
tasks: ['sass']
|
||||||
test:
|
test:
|
||||||
files: ['./src/**/*.coffee', './src/**/*.js', './test/**/*.coffee']
|
files: ['./src/**/*.coffee', './src/**/*.js', './test/**/*.coffee']
|
||||||
tasks: ['script:clear', 'test']
|
tasks: ['test']
|
||||||
|
|
||||||
# Compound Tasks ###################################################################################################
|
# Compound Tasks ###################################################################################################
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ module.exports = (grunt)->
|
|||||||
['prepublish', 'script:publish', 'clean', 'build']
|
['prepublish', 'script:publish', 'clean', 'build']
|
||||||
|
|
||||||
grunt.registerTask 'start', 'build the project and start a local HTTP server',
|
grunt.registerTask 'start', 'build the project and start a local HTTP server',
|
||||||
['build', 'script:start']
|
['script:start']
|
||||||
|
|
||||||
grunt.registerTask 'test', 'run unit tests',
|
grunt.registerTask 'test', 'run unit tests',
|
||||||
['mochaTest']
|
['mochaTest']
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 723 B |
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
grunt watch &
|
||||||
|
|
||||||
pushd './build/' &>/dev/null
|
pushd './build/' &>/dev/null
|
||||||
clear
|
clear
|
||||||
nodemon ./server.coffee $*
|
nodemon ./server.coffee $*
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ switch global.hostName
|
|||||||
when 'prerender.crafting-guide.com'
|
when 'prerender.crafting-guide.com'
|
||||||
global.env = 'prerender'
|
global.env = 'prerender'
|
||||||
logger.level = Logger.FATAL
|
logger.level = Logger.FATAL
|
||||||
apiBaseUrl = 'http://local.crafting-guide.com:4347'
|
apiBaseUrl = 'http://prerender.crafting-guide.com:4347'
|
||||||
when 'local.crafting-guide.com', 'localhost'
|
when 'local.crafting-guide.com', 'localhost'
|
||||||
global.env = 'local'
|
global.env = 'local'
|
||||||
logger.level = Logger.DEBUG
|
logger.level = Logger.DEBUG
|
||||||
apiBaseUrl = 'http://local.crafting-guide.com:4347'
|
apiBaseUrl = "http://#{global.hostName}:4347"
|
||||||
when 'staging.crafting-guide.com'
|
when 'staging.crafting-guide.com'
|
||||||
global.env = 'staging'
|
global.env = 'staging'
|
||||||
logger.level = Logger.VERBOSE
|
logger.level = Logger.VERBOSE
|
||||||
@@ -70,7 +70,7 @@ client.onStatusChanged = (client, oldStatus, newStatus)->
|
|||||||
client.trigger 'change:status', client, oldStatus, newStatus
|
client.trigger 'change:status', client, oldStatus, newStatus
|
||||||
client.trigger 'change', client
|
client.trigger 'change', client
|
||||||
|
|
||||||
client.checkStatus()
|
client.startMonitoringStatus()
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,4 @@
|
|||||||
|
|
||||||
.right
|
.right
|
||||||
.tile_container
|
.tile_container
|
||||||
.view__suggest_mod_panel
|
section.view__mod_ballot
|
||||||
|
|||||||
@@ -5,22 +5,38 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
ModTileController = require './mod_tile/mod_tile_controller'
|
ModBallotController = require './mod_ballot/mod_ballot_controller'
|
||||||
PageController = require '../page_controller'
|
ModTileController = require './mod_tile/mod_tile_controller'
|
||||||
SuggestModPanelController = require './suggest_mod_panel/suggest_mod_panel_controller'
|
PageController = require '../page_controller'
|
||||||
|
{CraftingGuideClient} = require 'crafting-guide-common'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
module.exports = class BrowsePageController extends PageController
|
module.exports = class BrowsePageController extends PageController
|
||||||
|
|
||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
|
if not options.client then throw new Error 'options.client is required'
|
||||||
if not options.modPack then throw new Error 'options.modPack is required'
|
if not options.modPack then throw new Error 'options.modPack is required'
|
||||||
options.templateName = 'browse_page'
|
options.templateName = 'browse_page'
|
||||||
super options
|
super options
|
||||||
|
|
||||||
|
@_client = options.client
|
||||||
@_modPack = options.modPack
|
@_modPack = options.modPack
|
||||||
@_tileControllers = []
|
@_tileControllers = []
|
||||||
|
|
||||||
|
@_client.on c.event.change, => @tryRefresh()
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
|
||||||
|
user:
|
||||||
|
get: -> @_user
|
||||||
|
|
||||||
|
set: (newUser)->
|
||||||
|
@_user = newUser
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
# PageController Overrides #####################################################################
|
# PageController Overrides #####################################################################
|
||||||
|
|
||||||
getMetaDescription: ->
|
getMetaDescription: ->
|
||||||
@@ -32,12 +48,14 @@ module.exports = class BrowsePageController extends PageController
|
|||||||
# BaseController Overrides #####################################################################
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
onDidRender: ->
|
onDidRender: ->
|
||||||
@_suggestController = @addChild SuggestModPanelController, '.view__suggest_mod_panel'
|
@_modBallotController = @addChild ModBallotController, '.view__mod_ballot', client:@_client, user:@_user
|
||||||
|
|
||||||
@$tileContainer = @$('.tile_container')
|
@$tileContainer = @$('.tile_container')
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
|
@_modBallotController.user = @user
|
||||||
@_refreshModTiles()
|
@_refreshModTiles()
|
||||||
|
@_refreshBallot()
|
||||||
super
|
super
|
||||||
|
|
||||||
# Backbone.View Overrides ######################################################################
|
# Backbone.View Overrides ######################################################################
|
||||||
@@ -48,6 +66,12 @@ module.exports = class BrowsePageController extends PageController
|
|||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_refreshBallot: ->
|
||||||
|
if @_client.status is CraftingGuideClient.Status.Down
|
||||||
|
@_modBallotController.hide()
|
||||||
|
else
|
||||||
|
@_modBallotController.show()
|
||||||
|
|
||||||
_refreshModTiles: ->
|
_refreshModTiles: ->
|
||||||
index = 0
|
index = 0
|
||||||
mods = @_modPack.getAllMods()
|
mods = @_modPack.getAllMods()
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//-
|
||||||
|
//- Crafting Guide - mod_ballot.jade
|
||||||
|
//-
|
||||||
|
//- Copyright © 2014-2016 by Redwood Labs
|
||||||
|
//- All rights reserved.
|
||||||
|
//-
|
||||||
|
|
||||||
|
.view__mod_ballot
|
||||||
|
.status.initial
|
||||||
|
h2 Are we missing a mod you like?<br>Vote for your favorites!
|
||||||
|
.button.vote-now: .bezel: p Vote Now!
|
||||||
|
|
||||||
|
.status.loading
|
||||||
|
.status-message
|
||||||
|
|
||||||
|
.status.loaded
|
||||||
|
h2 Are we missing a mod you like?<br>Vote for your favorites!
|
||||||
|
.instructions.
|
||||||
|
You can cast up to 3 votes. Change them any time. You get a vote back when a mod is added.
|
||||||
|
.instructions.remaining.
|
||||||
|
You have <span class="remaining-count">0</span> votes remaining.
|
||||||
|
|
||||||
|
.ballot-list
|
||||||
|
|
||||||
|
.view__suggest_mod_panel
|
||||||
|
|
||||||
|
.status.error
|
||||||
|
.status-message
|
||||||
|
.button.reload: .bezel: p Try Again
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// Crafting Guide - mod_ballot.scss
|
||||||
|
//
|
||||||
|
// Copyright © 2014-2016 by Redwood Labs
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
$ballot-move-duration: 0.2s;
|
||||||
|
|
||||||
|
.view__mod_ballot {
|
||||||
|
@include floating-panel;
|
||||||
|
|
||||||
|
display : flex;
|
||||||
|
padding : $size-margin-medium;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
display : flex;
|
||||||
|
flex-direction : column;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-bottom: $size-margin-large;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.initial {
|
||||||
|
padding: 0 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loaded {
|
||||||
|
padding: 0 15%;
|
||||||
|
|
||||||
|
& > .instructions {
|
||||||
|
margin-bottom: $size-margin-small;
|
||||||
|
|
||||||
|
font-family: $font-family-text;
|
||||||
|
font-size: $font-size-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remaining {
|
||||||
|
margin-top: $size-margin-medium;
|
||||||
|
font-size: $font-size-large;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ballot-list {
|
||||||
|
position: relative;
|
||||||
|
margin-top: $size-margin-large;
|
||||||
|
|
||||||
|
.view__mod_ballot_line {
|
||||||
|
position: absolute;
|
||||||
|
margin-bottom: $size-margin-small;
|
||||||
|
transition: top $ballot-move-duration ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.view__suggest_mod_panel {
|
||||||
|
margin-top: $size-margin-xlarge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.status-message {
|
||||||
|
margin-bottom: $size-margin-large;
|
||||||
|
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-medium;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
width: $size-minecraft-block * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
#
|
||||||
|
# Crafting Guide - mod_ballot_controller.coffee
|
||||||
|
#
|
||||||
|
# Copyright © 2014-2016 by Redwood Labs
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
BaseController = require '../../base_controller'
|
||||||
|
ModBallotLineController = require './mod_ballot_line/mod_ballot_line_controller'
|
||||||
|
SuggestModPanelController = require './suggest_mod_panel/suggest_mod_panel_controller'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class ModBallotController extends BaseController
|
||||||
|
|
||||||
|
@::LOAD_ERROR = 'Sorry! Something went wrong loading the mod list. Please try again.'
|
||||||
|
|
||||||
|
@::MAX_VOTES = 3
|
||||||
|
|
||||||
|
@::STATUS =
|
||||||
|
ERROR: 'error'
|
||||||
|
INITIAL: 'initial'
|
||||||
|
LOADED: 'loaded'
|
||||||
|
LOADING: 'loading'
|
||||||
|
LOGGED_OUT: 'logged-out'
|
||||||
|
|
||||||
|
@::VOTE_ERROR = 'Sorry! Something went wrong casting your vote. Please try again.'
|
||||||
|
|
||||||
|
constructor: (options={})->
|
||||||
|
if not options.client then throw new Error "options.client is required"
|
||||||
|
options.model = ballot:null, votes:null
|
||||||
|
options.templateName = 'browse_page/mod_ballot'
|
||||||
|
super options
|
||||||
|
|
||||||
|
@_client = options.client
|
||||||
|
@_lineControllers = {}
|
||||||
|
@_status = @STATUS.INITIAL
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
|
||||||
|
isVotingAllowed:
|
||||||
|
get: ->
|
||||||
|
voteCount = @model.votes?.length or 0
|
||||||
|
return voteCount < @MAX_VOTES
|
||||||
|
|
||||||
|
user:
|
||||||
|
get: -> @_user
|
||||||
|
|
||||||
|
set: (newUser)->
|
||||||
|
@_user = newUser
|
||||||
|
|
||||||
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
|
onReloadClicked: ->
|
||||||
|
tracker.trackEvent c.tracking.category.modVote, 'reload'
|
||||||
|
@_reloadData()
|
||||||
|
return false
|
||||||
|
|
||||||
|
onVoteButtonClicked: (controller)->
|
||||||
|
modId = controller.model.ballotLine.modId
|
||||||
|
|
||||||
|
if controller.model.vote?
|
||||||
|
tracker.trackEvent c.tracking.category.modVote, 'cancel-vote', @_findModName modId
|
||||||
|
@_cancelVote modId
|
||||||
|
else
|
||||||
|
tracker.trackEvent c.tracking.category.modVote, 'cast-vote', @_findModName modId
|
||||||
|
@_castVote modId
|
||||||
|
|
||||||
|
onVoteNowClicked: ->
|
||||||
|
tracker.trackEvent c.tracking.category.modVote, 'vote-now'
|
||||||
|
|
||||||
|
if not @user?
|
||||||
|
global.site.login()
|
||||||
|
else
|
||||||
|
@_reloadData()
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
|
onDidRender: ->
|
||||||
|
@_suggestPanelController = @addChild SuggestModPanelController, '.view__suggest_mod_panel'
|
||||||
|
|
||||||
|
@$ballotList = @$('.ballot-list')
|
||||||
|
@$remainingCount = @$('.remaining-count')
|
||||||
|
@$remainingMessage = @$('.remaining')
|
||||||
|
@$statusMessage = @$('.status-message')
|
||||||
|
@$statusSections = @$('.status')
|
||||||
|
super
|
||||||
|
|
||||||
|
refresh: ->
|
||||||
|
@_refreshLines()
|
||||||
|
@_refreshRemaining()
|
||||||
|
@_refreshStatus()
|
||||||
|
super
|
||||||
|
|
||||||
|
# Backbone.View Methods ########################################################################
|
||||||
|
|
||||||
|
events: ->
|
||||||
|
_.extend super,
|
||||||
|
'click .button.reload': 'onReloadClicked'
|
||||||
|
'click .button.vote-now': 'onVoteNowClicked'
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_cancelVote: (modId)->
|
||||||
|
controller = @_lineControllers[modId]
|
||||||
|
vote = @_findVote modId
|
||||||
|
|
||||||
|
controller.isWaiting = true
|
||||||
|
controller.tryRefresh()
|
||||||
|
|
||||||
|
@_client.cancelVote modVoteId:vote.id
|
||||||
|
.then =>
|
||||||
|
@model.votes = _(@model.votes).without vote
|
||||||
|
controller.model.vote = null
|
||||||
|
controller.model.ballotLine.voteCount -= 1
|
||||||
|
.catch =>
|
||||||
|
@_changeStatus @STATUS.ERROR, @VOTE_ERROR
|
||||||
|
.finally =>
|
||||||
|
controller.isWaiting = false
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
_castVote: (modId)->
|
||||||
|
controller = @_lineControllers[modId]
|
||||||
|
vote = @_findVote modId
|
||||||
|
|
||||||
|
controller.isWaiting = true
|
||||||
|
controller.tryRefresh()
|
||||||
|
|
||||||
|
@_client.castVote modId:modId, userId:@user.id
|
||||||
|
.then (response)=>
|
||||||
|
vote = response.json
|
||||||
|
@model.votes.push vote
|
||||||
|
controller.model.vote = vote
|
||||||
|
controller.model.ballotLine.voteCount += 1
|
||||||
|
.catch (error)=>
|
||||||
|
logger.error -> "vote could not be cast: #{error}"
|
||||||
|
@_changeStatus @STATUS.ERROR, @VOTE_ERROR
|
||||||
|
.finally =>
|
||||||
|
controller.isWaiting = false
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
_computeLines: ->
|
||||||
|
return [] unless @model.ballot?.lines?
|
||||||
|
|
||||||
|
@model.ballot.lines.sort (a, b)->
|
||||||
|
if a.voteCount != b.voteCount
|
||||||
|
return if a.voteCount > b.voteCount then -1 else +1
|
||||||
|
if a.name != b.name
|
||||||
|
return if a.name < b.name then -1 else +1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return @model.ballot.lines
|
||||||
|
|
||||||
|
_changeStatus: (status, message='')->
|
||||||
|
@_status = status
|
||||||
|
@_message = message
|
||||||
|
|
||||||
|
_findVote: (modId)->
|
||||||
|
return null unless @model.votes?
|
||||||
|
|
||||||
|
for vote in @model.votes
|
||||||
|
return vote if vote.modId is modId
|
||||||
|
return null
|
||||||
|
|
||||||
|
_findModName: (modId)->
|
||||||
|
return '' unless @model.ballot?
|
||||||
|
|
||||||
|
for line in @model.ballot.lines
|
||||||
|
return line.name if line.modId is modId
|
||||||
|
return ''
|
||||||
|
|
||||||
|
_refreshLines: ->
|
||||||
|
extraControllers = _.clone @_lineControllers
|
||||||
|
lines = @_computeLines()
|
||||||
|
|
||||||
|
for line, index in lines
|
||||||
|
controller = @_lineControllers[line.modId]
|
||||||
|
delete extraControllers[line.modId]
|
||||||
|
|
||||||
|
model = {ballotLine:line, vote:@_findVote(line.modId)}
|
||||||
|
if not controller?
|
||||||
|
controller = new ModBallotLineController
|
||||||
|
model: model
|
||||||
|
onVoteButtonClicked: (controller)=> @onVoteButtonClicked controller
|
||||||
|
controller.render()
|
||||||
|
@$ballotList.append controller.$el
|
||||||
|
@_lineControllers[line.modId] = controller
|
||||||
|
else
|
||||||
|
controller.model = model
|
||||||
|
|
||||||
|
controller.isVotingAllowed = @isVotingAllowed
|
||||||
|
|
||||||
|
for modId, controller of extraControllers
|
||||||
|
delete @_lineControllers[modId]
|
||||||
|
controller.remove()
|
||||||
|
|
||||||
|
_.delay (=> @_refreshLineLayout()), 100
|
||||||
|
|
||||||
|
_refreshLineLayout: ->
|
||||||
|
lines = @_computeLines()
|
||||||
|
offset = @$ballotList.offset()
|
||||||
|
|
||||||
|
for line in lines
|
||||||
|
controller = @_lineControllers[line.modId]
|
||||||
|
continue unless controller?
|
||||||
|
|
||||||
|
if controller.$el.height() is 0
|
||||||
|
# keep trying until the elements have been created and laid out by the browser
|
||||||
|
_.delay (=> @_refreshLineLayout()), 100
|
||||||
|
return
|
||||||
|
|
||||||
|
controller.$el.offset offset
|
||||||
|
offset.top += controller.$el.outerHeight(true)
|
||||||
|
|
||||||
|
@$ballotList.height offset.top - @$ballotList.offset().top
|
||||||
|
|
||||||
|
_refreshRemaining: ->
|
||||||
|
if @model.votes?
|
||||||
|
@$remainingCount.html @MAX_VOTES - @model.votes.length
|
||||||
|
@show @$remainingMessage
|
||||||
|
else
|
||||||
|
@hide @$remainingMessage
|
||||||
|
|
||||||
|
_refreshStatus: ->
|
||||||
|
@hide @$('.status')
|
||||||
|
@show @$(".status.#{@_status}")
|
||||||
|
@$statusMessage.html @_message
|
||||||
|
|
||||||
|
_reloadBallot: ->
|
||||||
|
return @_loadingBallot if @_loadingBallot?
|
||||||
|
|
||||||
|
@model.ballot = null
|
||||||
|
@_changeStatus @STATUS.LOADING, "Loading ballot data..."
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
@_loadingBallot = @_client.getModBallot()
|
||||||
|
.then (response)=>
|
||||||
|
@model.ballot = response.json
|
||||||
|
if not @user? or @model.votes? then @_changeStatus @STATUS.LOADED
|
||||||
|
@tryRefresh()
|
||||||
|
.catch (error)=>
|
||||||
|
@_changeStatus @STATUS.ERROR, @LOAD_ERROR
|
||||||
|
.finally =>
|
||||||
|
@_loadingBallot = null
|
||||||
|
|
||||||
|
_reloadData: ->
|
||||||
|
@_reloadVotes()
|
||||||
|
@_reloadBallot()
|
||||||
|
|
||||||
|
_reloadVotes: ->
|
||||||
|
return @_loadingVotes if @_loadingVotes?
|
||||||
|
return unless @user?
|
||||||
|
|
||||||
|
@model.votes = null
|
||||||
|
@_changeStatus @STATUS.LOADING, "Loading ballot data..."
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
@_loadingVotes = @_client.getModVotes()
|
||||||
|
.then (response)=>
|
||||||
|
@model.votes = response.json
|
||||||
|
if @model.ballot? then @_changeStatus @STATUS.LOADED
|
||||||
|
@tryRefresh()
|
||||||
|
.catch (error)=>
|
||||||
|
@_changeStatus @STATUS.ERROR, @LOAD_ERROR
|
||||||
|
.finally =>
|
||||||
|
@_loadingVotes = null
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//-
|
||||||
|
//- Crafting Guide - mod_ballot_line.jade
|
||||||
|
//-
|
||||||
|
//- Copyright © 2014-2016 by Redwood Labs
|
||||||
|
//- All rights reserved.
|
||||||
|
//-
|
||||||
|
|
||||||
|
.view__mod_ballot_line
|
||||||
|
.vote-count
|
||||||
|
img(src='/images/unknown.png')
|
||||||
|
.name
|
||||||
|
.button.vote: .bezel: p ✓
|
||||||
|
.wait
|
||||||
|
img(src='/images/wait-small.gif')
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Crafting Guide - mod_ballot_line.scss
|
||||||
|
//
|
||||||
|
// Copyright © 2014-2016 by Redwood Labs
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
.view__mod_ballot_line {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display : flex;
|
||||||
|
align-items : center;
|
||||||
|
|
||||||
|
.vote-count {
|
||||||
|
flex : 0 0 $size-minecraft-block;
|
||||||
|
margin-right : $size-margin-medium;
|
||||||
|
|
||||||
|
font-family : $font-family-text;
|
||||||
|
font-size : $font-size-large;
|
||||||
|
text-align : right;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > img {
|
||||||
|
margin-right : $size-margin-medium;
|
||||||
|
|
||||||
|
flex : 0 0 auto;
|
||||||
|
height : $size-minecraft-block;
|
||||||
|
width : $size-minecraft-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
margin-right : $size-margin-medium;
|
||||||
|
|
||||||
|
flex : 1 1 auto;
|
||||||
|
font-family : $font-family-text;
|
||||||
|
font-size : $font-size-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
flex : 0 0 auto;
|
||||||
|
width : $size-minecraft-block * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wait {
|
||||||
|
flex : 0 0 auto;
|
||||||
|
height : $size-button-height;
|
||||||
|
width : $size-minecraft-block * 1.5;
|
||||||
|
|
||||||
|
display : flex;
|
||||||
|
align-items : center;
|
||||||
|
justify-content : center;
|
||||||
|
}
|
||||||
|
}
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
#
|
||||||
|
# Crafting Guide - mod_ballot_line_controller.coffee
|
||||||
|
#
|
||||||
|
# Copyright © 2014-2016 by Redwood Labs
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
BaseController = require '../../../base_controller'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class ModBallotLineController extends BaseController
|
||||||
|
|
||||||
|
constructor: (options={})->
|
||||||
|
options.templateName = 'browse_page/mod_ballot/mod_ballot_line'
|
||||||
|
super options
|
||||||
|
|
||||||
|
@_onVoteButtonClicked = options.onVoteButtonClicked or (controller)-> # do nothing
|
||||||
|
|
||||||
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
|
onButtonClicked: ->
|
||||||
|
return if @$button.hasClass 'disabled'
|
||||||
|
|
||||||
|
@_onVoteButtonClicked this
|
||||||
|
return false
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
|
||||||
|
isVotingAllowed:
|
||||||
|
get: -> @_isVotingAllowed
|
||||||
|
|
||||||
|
set: (isVotingAllowed)->
|
||||||
|
@_isVotingAllowed = !! isVotingAllowed
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
isWaiting:
|
||||||
|
get: -> @_isWaiting
|
||||||
|
|
||||||
|
set: (isWaiting)->
|
||||||
|
@_isWaiting = !! isWaiting
|
||||||
|
@tryRefresh()
|
||||||
|
|
||||||
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
|
onDidRender: ->
|
||||||
|
@$button = @$('.button')
|
||||||
|
@$image = @$('img')
|
||||||
|
@$name = @$('.name')
|
||||||
|
@$voteCount = @$('.vote-count')
|
||||||
|
@$wait = @$('.wait')
|
||||||
|
super
|
||||||
|
|
||||||
|
refresh: ->
|
||||||
|
@$name.html @model.ballotLine?.name or ''
|
||||||
|
@$voteCount.html @model.ballotLine?.voteCount or ''
|
||||||
|
@_refreshVoteButton()
|
||||||
|
super
|
||||||
|
|
||||||
|
# Backbone.View Overrides ######################################################################
|
||||||
|
|
||||||
|
events: ->
|
||||||
|
return _.extend super,
|
||||||
|
'click .button': 'onButtonClicked'
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_refreshVoteButton: ->
|
||||||
|
if @isWaiting
|
||||||
|
@$wait.removeClass 'hidden'
|
||||||
|
@$button.addClass 'hidden'
|
||||||
|
else
|
||||||
|
@$wait.addClass 'hidden'
|
||||||
|
@$button.removeClass 'hidden'
|
||||||
|
|
||||||
|
if @model.vote?
|
||||||
|
@$button.addClass 'active'
|
||||||
|
else
|
||||||
|
@$button.removeClass 'active'
|
||||||
|
|
||||||
|
if @isVotingAllowed
|
||||||
|
@$button.removeClass 'disabled'
|
||||||
|
else
|
||||||
|
@$button.addClass 'disabled'
|
||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
.view__suggest_mod_panel
|
.view__suggest_mod_panel
|
||||||
.initial
|
.initial
|
||||||
.instructions Are we missing a mod you like? Tell us!
|
.instructions Still don't see the mod you want?<br>Tell us about it!
|
||||||
|
|
||||||
.entry-form
|
.entry-form
|
||||||
input.name(placeholder="enter the mod name")
|
input.name(placeholder="enter the mod name")
|
||||||
+1
-40
@@ -6,30 +6,24 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
.view__suggest_mod_panel {
|
.view__suggest_mod_panel {
|
||||||
@include floating-panel;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
padding: $size-margin-large;
|
|
||||||
|
|
||||||
.instructions {
|
.instructions {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-xlarge;
|
font-size: $font-size-xlarge;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.initial {
|
.initial {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.instructions {
|
.instructions {
|
||||||
margin-bottom: $size-margin-large;
|
margin-bottom: $size-margin-large;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-form {
|
.entry-form {
|
||||||
width: $size-minecraft-block * 15;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
@@ -68,36 +62,3 @@
|
|||||||
margin: $size-margin-xlarge 0;
|
margin: $size-margin-xlarge 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include screen-size(mobile) {
|
|
||||||
|
|
||||||
.view__suggest_mod_panel {
|
|
||||||
.instructions {
|
|
||||||
}
|
|
||||||
|
|
||||||
.initial {
|
|
||||||
.instructions {
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-form {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
input {
|
|
||||||
&.invalid {
|
|
||||||
}
|
|
||||||
|
|
||||||
&.valid {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
.button {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.error, .sending, .success {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+13
-3
@@ -5,15 +5,15 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
BaseController = require '../../base_controller'
|
BaseController = require '../../../base_controller'
|
||||||
EmailClient = require '../../../models/site/email_client'
|
EmailClient = require '../../../../models/site/email_client'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
module.exports = class SuggestModPanelController extends BaseController
|
module.exports = class SuggestModPanelController extends BaseController
|
||||||
|
|
||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
options.templateName = 'browse_page/suggest_mod_panel'
|
options.templateName = 'browse_page/mod_ballot/suggest_mod_panel'
|
||||||
super options
|
super options
|
||||||
|
|
||||||
@_emailClient = new EmailClient
|
@_emailClient = new EmailClient
|
||||||
@@ -38,6 +38,10 @@ module.exports = class SuggestModPanelController extends BaseController
|
|||||||
return '' unless @rendered
|
return '' unless @rendered
|
||||||
return @$urlField.val()
|
return @$urlField.val()
|
||||||
|
|
||||||
|
user:
|
||||||
|
get: -> @_user
|
||||||
|
set: (user)-> @_user = user
|
||||||
|
|
||||||
# Event Methods ################################################################################
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
onButtonClicked: (event)->
|
onButtonClicked: (event)->
|
||||||
@@ -96,6 +100,12 @@ module.exports = class SuggestModPanelController extends BaseController
|
|||||||
@hide $panel for $panel in [@$initialPanel, @$sendingPanel, @$successPanel, @$errorPanel]
|
@hide $panel for $panel in [@$initialPanel, @$sendingPanel, @$successPanel, @$errorPanel]
|
||||||
@show $selectedPanel
|
@show $selectedPanel
|
||||||
|
|
||||||
|
data =
|
||||||
|
name: @name
|
||||||
|
url: @url
|
||||||
|
user: @user?.name
|
||||||
|
email: @user?.email
|
||||||
|
|
||||||
showPanel @$sendingPanel
|
showPanel @$sendingPanel
|
||||||
w(@_emailClient.send 'mod-suggestion', name:@name, url:@url)
|
w(@_emailClient.send 'mod-suggestion', name:@name, url:@url)
|
||||||
.then =>
|
.then =>
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
p.
|
p.
|
||||||
All changes you make on the site get submitted directly to our GitHub repo, and then published
|
All changes you make on the site get submitted directly to our GitHub repo, and then published
|
||||||
through the same automated deployment process as changes made by anyone else. That way, anyone
|
through the same automated deployment process as changes made by anyone else. That way, anyone
|
||||||
can contribute easily: whether developer or end user.
|
can contribute easily: whether programmer or player.
|
||||||
p.
|
p.
|
||||||
To log in, we redirect you to GitHub's site, and once you're signed in, they'll send you back
|
To log in, we redirect you to GitHub's site. Once you're signed in over there, they'll send you
|
||||||
here. We never see your credentials, and only get the minimum set of permissions necessary to
|
back here. We never see your credentials, and only get the minimum set of permissions necessary
|
||||||
submit changes to the Crafting Guide repo on your behalf.
|
to submit changes to the Crafting Guide repo on your behalf.
|
||||||
p.
|
p.
|
||||||
GitHub offers free accounts, so even if you don't already have one, you've got nothing to lose!
|
GitHub offers free accounts, so even if you don't already have one, you've got nothing to lose!
|
||||||
|
|
||||||
@@ -75,6 +75,6 @@
|
|||||||
.left
|
.left
|
||||||
h1 Sorry!
|
h1 Sorry!
|
||||||
p.
|
p.
|
||||||
Our interactive editing service is down right now, but you can always submit a pull request over at the
|
Our interactive services are down right now, but you can always submit an issue or pull request over at
|
||||||
<a href="https://github.com/andrewminer/crafting-guide">Crafting Guide GitHub Repository</a>. We'll
|
the <a href="https://github.com/andrewminer/crafting-guide">Crafting Guide GitHub Repository</a>. We'll
|
||||||
have the editing service back up soon!
|
have things back to normal soon!
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ tracking.category.craftWant = 'craft-want'
|
|||||||
tracking.category.feedback = 'feedback'
|
tracking.category.feedback = 'feedback'
|
||||||
tracking.category.markdown = 'markdown'
|
tracking.category.markdown = 'markdown'
|
||||||
tracking.category.modPack = 'mod-pack'
|
tracking.category.modPack = 'mod-pack'
|
||||||
|
tracking.category.modVote = 'mod-vote'
|
||||||
tracking.category.multiblock = 'multiblock'
|
tracking.category.multiblock = 'multiblock'
|
||||||
tracking.category.navigate = 'navigate'
|
tracking.category.navigate = 'navigate'
|
||||||
tracking.category.search = 'search'
|
tracking.category.search = 'search'
|
||||||
|
|||||||
Reference in New Issue
Block a user