Add nascent version of the mod detail page

* Create a nascent version of the mod detail page
* Make the slug mandatory for Mod instead of name, and load the name
  from the data file
* Make the Feedback view universal on all pages
* Refactor the use of mod pack to have a single global object at the
  router level which is shared between pages. Further, make this one
  object load itself immediately and have it automatically load any
  activated mod version
* Refactor the use of Storage related to mod pack versions into the
  router as well.
* Add trace logging back in for events, but allow individual classes
  to suppress it (as opposed to actually supressing the events)
* Fix a bug in ModVersion.eachItem where it would suggest so-called
  items which are merely registered slugs without associated items
This commit is contained in:
Andrew Miner
2015-01-20 10:55:38 -08:00
parent d33723b3c2
commit 164c0d4892
25 changed files with 151 additions and 26 deletions
+5
View File
@@ -22,6 +22,11 @@ app.get '/item(/*)?', (request, response)->
response.set 'Content-Type', 'text/html'
response.sendFile 'index.html', root:ROOT
app.get '/mod(/*)?', (request, response)->
console.log ">>> index.html (for #{request.path})"
response.set 'Content-Type', 'text/html'
response.sendFile 'index.html', root:ROOT
app.get '*', (request, response)->
extension = path.extname(request.path)
contentType = {
+1
View File
@@ -1,5 +1,6 @@
schema: 1
name: Applied Energistics 2
author: AlgorithmX2
description: A technical mod which adds an advanced, computer-based storage system
url: http://www.mod-buildcraft.com
+2 -1
View File
@@ -1,6 +1,7 @@
schema: 1
author: Spacetoad
name: Buildcraft
author: SpaceToad
description: A technical mod which adds power generation, mining, and building systems
url: http://www.mod-buildcraft.com
+1
View File
@@ -1,5 +1,6 @@
schema: 1
name: Industrial Craft (classic)
author: Alblaka
description: A technical mod adding multi-tiered power systems, mining and ore processing, and powered armor
url: http://http://wiki.industrial-craft.net/
+1
View File
@@ -1,5 +1,6 @@
schema: 1
name: Minecraft
author: Mojang
description: The basic game by itself
url: http://www.minecraft.net
+1
View File
@@ -1,5 +1,6 @@
schema: 1
name: Thermal Expansion
author: Team CoFH
description: A technical mod which adds ore processing, item transportion, fluid handling, and many new ores.
url: http://teamcofh.com/thermal-expansion/
-3
View File
@@ -10,9 +10,6 @@ extends ./layouts/basic
append styles
link(rel="stylesheet", type="text/css", href="/css/jquery-ui.css")
prepend body
.view__feedback
block content
.page
+1
View File
@@ -19,6 +19,7 @@ html
body
block body
.view__feedback
.view__screen
.content
include ../includes/_header.jade
+1 -1
View File
@@ -6,7 +6,7 @@ All rights reserved.
###
# Minecraft must be first
exports.DefaultMods = [ 'Minecraft', 'Applied Energistics 2', 'Buildcraft', 'IC2 Classic' ]
exports.DefaultMods = [ 'minecraft', 'applied_energistics_2', 'buildcraft', 'ic2_classic' ]
exports.Duration = Duration = {}
Duration.snap = 100
@@ -87,7 +87,7 @@ module.exports = class BaseController extends Backbone.View
logger.error "Default render called for #{@constructor.name} without a template"
return this
logger.verbose "#{this} rendering with data: #{data}"
logger.verbose "#{this} rendering with data: #{util.inspect(data)}"
@onWillRender()
$oldEl = @$el
$newEl = Backbone.$(@_template(data))
@@ -20,7 +20,7 @@ Storage = require '../models/storage'
module.exports = class ItemPageController extends BaseController
constructor: (options={})->
options.model ?= new ItemPage
options.model ?= new ItemPage modPack:options.modPack
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.storage ?= new Storage storage:window.localStorage
options.templateName = 'item_page'
@@ -36,12 +36,6 @@ module.exports = class ModController extends BaseController
# BaseController Overrides #####################################################################
onWillRender: ->
@model.fetch()
if @_storage? then @_storage.register "mod:#{@model.slug}", @model, 'activeVersion'
@model.on Event.change + ':activeModVersion', (mod, modVersion)=>
if modVersion? then modVersion.fetch()
onDidRender: ->
@$enabled = @$('td:nth-child(1) input')
@$name = @$('td:nth-child(2) p')
@@ -33,10 +33,6 @@ module.exports = class ModPackController extends BaseController
# BaseController Overrides #####################################################################
onWillRender: ->
for name in DefaultMods
@model.addMod new Mod name:name
onDidRender: ->
@$table = @$('table')
@$toolbar = @$('.toolbar')
@@ -0,0 +1,55 @@
###
Crafting Guide - mod_page_controller.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
BaseController = require './base_controller'
{Duration} = require '../constants'
ModPack = require '../models/mod_pack'
RecipeController = require './recipe_controller'
########################################################################################################################
module.exports = class ModPageController extends BaseController
constructor: (options={})->
if not options.modPack? then throw new Error 'options.modPack is required'
options.templateName = 'mod_page'
super options
@_modPack = options.modPack
@_recipeControllers = []
# BaseController Overrides #####################################################################
onDidRender: ->
@$title = @$('h1')
@$recipes = @$('.recipes')
super
refresh: ->
@$title.html if @model? then @model.name else ''
controllerIndex = 0
if @model?.activeModVersion?.isLoaded
@$recipes.show duration:Duration.fast
@model.eachItem (item)=>
controller = @_recipeControllers[controllerIndex]
if not controller?
controller = new RecipeController modPack:@_modPack
controller.render()
@_recipeControllers.push controller
@$recipes.append controller.$el
controller.model = item.getPrimaryRecipe()
controllerIndex += 1
else
@$recipes.hide duration:Duration.fast
while @_recipeControllers.length > controllerIndex
controller = @_recipeControllers.pop()
controller.$el.slideUp duration:Duration.fast, complete:-> @remove()
super
+31 -1
View File
@@ -5,10 +5,15 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
{DefaultMods} = require './constants'
{Duration} = require './constants'
{Event} = require './constants'
ItemPageController = require './controllers/item_page_controller'
Mod = require './models/mod'
ModPack = require './models/mod_pack'
ModPageController = require './controllers/mod_page_controller'
{Opacity} = require './constants'
Storage = require './models/storage'
UrlParams = require './url_params'
########################################################################################################################
@@ -21,6 +26,24 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
@_lastReported = null
super options
@modPack = new ModPack
@storage = new Storage storage:window.localStorage
@_defaultOptions = modPack:@modPack, storage:@storage
# Public Methods ###############################################################################
loadDefaultModPack: ->
makeResponder = (m)-> return ->
m.activeModVersion.fetch() if m.activeModVersion?
for slug in DefaultMods
mod = new Mod slug:slug
mod.on Event.change + ':activeModVersion', makeResponder mod
@storage.register "mod:#{mod.slug}", mod, 'activeVersion'
mod.fetch()
@modPack.addMod mod
# Backbone.Router Overrides ####################################################################
navigate: ->
@@ -30,6 +53,7 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
routes:
'': 'root'
'item(/:name)': 'item'
'mod/:slug': 'mod'
# Route Methods ################################################################################
@@ -38,10 +62,16 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
@item params.recipeName, params.count
item: (name, quantity=1)->
@_pageControllers.item ?= new ItemPageController
@_pageControllers.item ?= new ItemPageController @_defaultOptions
@_pageControllers.item.model.params = name:name, quantity:quantity
@_setPage 'item'
mod: (slug)->
@_pageControllers.mod ?= new ModPageController @_defaultOptions
logger.debug "setting up mod page wiht mod: #{@modPack.getMod slug} for slug: #{slug}"
@_pageControllers.mod.model = @modPack.getMod slug
@_setPage 'mod'
# Private Methods ##############################################################################
_recordPageView: ->
+8 -3
View File
@@ -13,14 +13,13 @@ FeedbackController = require './controllers/feedback_controller'
Logger = require './logger'
CraftingGuideRouter = require './crafting_guide_router'
########################################################################################################################
if typeof(global) is 'undefined'
window.global = window
global = window.global
global.logger = new Logger
global.router = new CraftingGuideRouter
global.util = require 'util'
global.views = views
switch window.location.hostname
when 'localhost'
@@ -33,8 +32,14 @@ switch window.location.hostname
global.env = 'production'
logger.level = Logger.INFO
global.router = new CraftingGuideRouter
global.util = require 'util'
global.views = views
global.feedbackController = new FeedbackController el:'.view__feedback'
feedbackController.render()
global.router.loadDefaultModPack()
logger.info "CraftingGuide is ready"
Backbone.history.start pushState:true
+7
View File
@@ -13,6 +13,7 @@ All rights reserved.
module.exports = class BaseModel extends Backbone.Model
constructor: (attributes={}, options={})->
options.logEvents ?= true
super attributes, options
makeGetter = (name)-> return -> @get name
@@ -21,6 +22,7 @@ module.exports = class BaseModel extends Backbone.Model
continue if name is 'id'
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
@logEvents = options.logEvents or false
@state = ModelState.unloaded
@on 'request', => @state = ModelState.loading
@@ -77,6 +79,11 @@ module.exports = class BaseModel extends Backbone.Model
sync: (method, model)->
throw new Error "#{@constructor.name}.#{@cid} is not permitted to #{method}"
trigger: (name, model, args...)->
if @logEvents
logger.trace "#{@constructor.name}.#{@cid} triggered event #{name} with args: #{args}"
super
# Object Overrides #############################################################################
toString: ->
+2 -1
View File
@@ -19,6 +19,7 @@ module.exports = class Item extends BaseModel
attributes.isGatherable ?= false
attributes.slug ?= _.slugify attributes.name
options.logEvents ?= false
super attributes, options
@_recipes = []
@@ -57,7 +58,7 @@ module.exports = class Item extends BaseModel
if _.slugify(@name) isnt @slug
result.push ', slug:'; result.push @slug
if @recipes.length > 0
if @_recipes.length > 0
result.push ', recipes:«'
result.push @_recipes.length
result.push ' items»'
+2 -2
View File
@@ -15,11 +15,11 @@ BaseModel = require './base_model'
module.exports = class Mod extends BaseModel
constructor: (attributes={}, options={})->
if not attributes.name? then throw new Error 'attributes.name is required'
if not attributes.slug? then throw new Error 'attributes.slug is required'
attributes.author ?= ''
attributes.description ?= ''
attributes.name ?= ''
attributes.primaryUrl ?= null
attributes.slug ?= _.slugify attributes.name
super attributes, options
@_activeModVersion = null
+6
View File
@@ -78,6 +78,7 @@ module.exports = class ModPack extends BaseModel
# Property Methods #############################################################################
addMod: (mod)->
if not mod? then throw new Error 'mod is required'
return if @_mods.indexOf(mod) isnt -1
@_mods.push mod
@@ -94,6 +95,11 @@ module.exports = class ModPack extends BaseModel
for mod in @_mods
callback mod
getMod: (slug)->
for mod in @_mods
return mod if mod.slug is slug
return null
getMods: ->
return @_mods[..]
+2
View File
@@ -46,6 +46,8 @@ module.exports = class ModVersion extends BaseModel
eachItem: (callback)->
for slug in @_slugs
item = @_items[slug]
continue unless item?
callback @_items[slug], slug
return this
@@ -37,6 +37,11 @@ module.exports = class ModParserV2 extends CommandParserVersionBase
@_rawData.description = description
_command_name: (name)->
if @_rawData.name? then throw new Error 'duplicate declaration of "name"'
if name.length is 0 then throw new Error '"name" cannot be empty'
@_rawData.name = name
_command_url: (url='')->
if @_rawData.url? then throw new Error 'duplicate declaration of "url"'
if url.length is 0 then throw new Error 'url cannot be empty'
@@ -52,11 +57,13 @@ module.exports = class ModParserV2 extends CommandParserVersionBase
# Object Building Methods ######################################################################
_buildMod: (rawData, model)->
if not rawData.name? then throw new Error 'the "name" declaration is required'
if not rawData.url? then throw new Error 'the "url" declaration is required'
if not rawData.versions? then throw new Error 'at least one "version" declaration is required'
model.author = rawData.author if rawData.author?
model.description = rawData.description if rawData.description?
model.name = rawData.name
model.primaryUrl = rawData.url
for version in rawData.versions
+1
View File
@@ -27,6 +27,7 @@ module.exports = class Recipe extends BaseModel
attributes.pattern = @_parsePattern attributes.pattern
attributes.slug ?= attributes.output[0].slug
attributes.tools ?= []
options.logEvents ?= false
super attributes, options
# Public Methods ###############################################################################
+3 -2
View File
@@ -11,10 +11,11 @@ BaseModel = require './base_model'
module.exports = class Stack extends BaseModel
constructor: (attributes={})->
constructor: (attributes={}, options={})->
if not attributes.slug? then throw new Error 'attributes.slug is required'
attributes.quantity ?= 1
super attributes
options.logEvents ?= false
super attributes, options
# Object Overrides #############################################################################
+12
View File
@@ -0,0 +1,12 @@
//-
//- Crafting Guide - mod_page.jade
//-
//- Copyright (c) 2015 by Redwood Labs
//- All rights reserved.
//-
.view__mod_page
h1
.recipes
h2 Recipes