From 5dd9742da846e8db863a951f1502d0edf5a3f90b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 18:02:13 -0500 Subject: forms for editing plans --- server/lib/views/staff.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 49f492b..c3739e9 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -4,6 +4,8 @@ var User = require('../schemas/User'), Project = require('../schemas/Project'), Media = require('../schemas/Media'), Collaborator = require('../schemas/Collaborator'), + Plan = require('../schemas/Plan'), + Subscription = require('../schemas/Subscription'), config = require('../../../config'), middleware = require('../middleware'), util = require('../util'), @@ -540,6 +542,26 @@ var staff = module.exports = { res.render('staff/media/show_404') } }, + }, + + plans: { + index: function(req, res){ + res.locals.fields = ( + "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit" + ).split(" ") + + res.locals.permissions = "basic_editor pro_editor solids collaborators no_logo".split(" ") + + res.render('staff/plans/index') + }, + new: function(req, res){ + res.render('staff/plans/new') + }, + edit: function(req, res){ + res.render('staff/plans/edit') + }, } } -- cgit v1.2.3-70-g09d2 From 190a145cf1433fde570df1ac9784d4c5cea77d3d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 18:28:46 -0500 Subject: everything but saving --- server/lib/middleware.js | 2 +- server/lib/views/staff.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 4848ab0..797d677 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -75,7 +75,7 @@ var middleware = { } next() }) - } + } else { req.project = null next() diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index c3739e9..ce676ed 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -120,6 +120,31 @@ var staff = module.exports = { next() }) }, + + ensurePlans: function(req, res, next){ + Plan.exec(function (err, plans) { + res.locals.plans = plans.map(staff.helpers.plan) + next() + }) + }, + ensurePlan: function (req, res, next) { + if (req.params.slug) { + Plan.findOne({ slug: req.params.slug }, function(err, plan){ + if (err || ! plan) { + console.error(err) + req.plan = null + } + else { + req.plan = plan + } + next() + }) + } + else { + req.plan = null + next() + } + }, ensureRecentProjects: function(req, res, next){ var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } @@ -424,7 +449,43 @@ var staff = module.exports = { staff.media.show ); + + // + // plans + app.get('/staff/plans/', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + staff.middleware.ensurePlans, + + staff.plans.index + ); + app.get('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.new + ); + app.post('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.create + ); + app.get('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.edit + ); + app.post('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.update + ); }, paginate: function(req, res){ @@ -557,11 +618,18 @@ var staff = module.exports = { res.render('staff/plans/index') }, new: function(req, res){ + res.locals.plan = new Plan () res.render('staff/plans/new') }, edit: function(req, res){ res.render('staff/plans/edit') }, + create: function(req, res){ + res.redirect("/staff/plans/") + }, + update: function(req, res){ + res.redirect("/staff/plans/") + }, } } -- cgit v1.2.3-70-g09d2 From 664099f91ae3ed2d667d331b19c2e41dec60124c Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 06:43:31 -0500 Subject: fix up plans form --- public/assets/stylesheets/app.css | 6 +- public/assets/stylesheets/staff.css | 16 ++++ server/lib/views/staff.js | 70 ++++++++++++---- server/repl.js | 2 + views/staff/_nav.ejs | 1 + views/staff/index.ejs | 6 +- views/staff/plans/_form.ejs | 160 ++++++++++++++++++++++-------------- views/staff/plans/edit.ejs | 2 +- views/staff/plans/index.ejs | 11 ++- views/staff/plans/new.ejs | 4 +- 10 files changed, 186 insertions(+), 92 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0463e26..9e86ac3 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -2478,7 +2478,7 @@ form li { form label { float:left; } -form input[type="text"],form input[type="password"] { +form input[type="text"],form input[type="password"],form input[type="number"] { border: 1px solid; font-size: 20px; padding: 5px; @@ -3048,8 +3048,8 @@ a[data-role="forgot-password"] { form li { font-size: 16px; } - form input[type="text"], form input[type="password"] { - font-size: 15px; + form input[type="text"],form input[type="password"],form input[type="number"] { + font-size: 15px; } .page h1 { font-size: 26px; diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index de31571..e5cafa2 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -71,6 +71,22 @@ hr { color: #00f; border-bottom: 1px solid; } +.staff form { + max-width: none; + width: 600px; + padding: 20px; +} +.staff form label { + float: none; +} +.staff form p { + width: 350px; + margin: 5px 0; + color: #444; +} +.staff form div li { + width: 180px; +} #iframe-embed, #iframe-embed tr, #iframe-embed td { width: 79vw; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index ce676ed..6639137 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -18,6 +18,10 @@ var staff = module.exports = { fields: { user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", project: "_id name slug user_id privacy created_at updated_at", + plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", + plans_permissions: "basic_editor pro_editor solids collaborators no_logo", }, defaults: { @@ -122,8 +126,8 @@ var staff = module.exports = { }, ensurePlans: function(req, res, next){ - Plan.exec(function (err, plans) { - res.locals.plans = plans.map(staff.helpers.plan) + Plan.find(function (err, plans) { + res.locals.plans = (plans || []).map(staff.helpers.plan) next() }) }, @@ -132,17 +136,16 @@ var staff = module.exports = { Plan.findOne({ slug: req.params.slug }, function(err, plan){ if (err || ! plan) { console.error(err) - req.plan = null + res.redirect("/staff/plans/") } else { req.plan = plan + next() } - next() }) } else { - req.plan = null - next() + res.redirect("/staff/plans/") } }, @@ -326,7 +329,14 @@ var staff = module.exports = { media.user = {} media.shortUrl = media.url.replace(/^http.:\/\//,"") return media - } + }, + + plan: function(plan){ + plan = plan.toObject() + plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") + plan.user = {} + return plan + }, }, route: function(app){ @@ -452,7 +462,8 @@ var staff = module.exports = { // // plans - app.get('/staff/plans/', + + app.get('/staff/plans', middleware.ensureAuthenticated, middleware.ensureIsStaff, @@ -484,6 +495,8 @@ var staff = module.exports = { middleware.ensureAuthenticated, middleware.ensureIsStaff, + staff.middleware.ensurePlan, + staff.plans.update ); }, @@ -607,14 +620,8 @@ var staff = module.exports = { plans: { index: function(req, res){ - res.locals.fields = ( - "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + - "pro_layout_monthly_price pro_layout_yearly_price " + - "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit" - ).split(" ") - - res.locals.permissions = "basic_editor pro_editor solids collaborators no_logo".split(" ") - + res.locals.fields = staff.fields.plans.split(" ") + res.locals.permissions = staff.fields.plans_permissions.split(" ") res.render('staff/plans/index') }, new: function(req, res){ @@ -625,10 +632,37 @@ var staff = module.exports = { res.render('staff/plans/edit') }, create: function(req, res){ - res.redirect("/staff/plans/") + var plan = new Plan () + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + permissions.forEach(function(field){ + data[field] = data["permissions_" + field] + }) + + new Plan (data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.redirect("/staff/plans/") + }) }, update: function(req, res){ - res.redirect("/staff/plans/") + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + _.extend(req.plan, data) + permissions.forEach(function(field){ + req.plan[field] = data["permissions_" + field] + }) + + req.plan.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.redirect("/staff/plans/") + }) }, } diff --git a/server/repl.js b/server/repl.js index ba94d45..353d8c5 100644 --- a/server/repl.js +++ b/server/repl.js @@ -9,6 +9,8 @@ mongoose.connect('mongodb://' + DB_HOST + '/vvalls', {}, function(){ "./lib/schemas/Layout", "./lib/schemas/Media", "./lib/schemas/Project", + "./lib/schemas/Plan", + "./lib/schemas/Subscription", ].forEach(function(modName){ // console.log(name, modName) var namez = modName.split("/"), name = namez[namez.length-1]; diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index 2115e9f..db7bedb 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -3,4 +3,5 @@ users projects media + plans \ No newline at end of file diff --git a/views/staff/index.ejs b/views/staff/index.ejs index 5ca7269..1b73641 100644 --- a/views/staff/index.ejs +++ b/views/staff/index.ejs @@ -2,11 +2,7 @@

Staff Area

- + [[ include _nav ]]
diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index b97716f..fc86516 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -1,109 +1,149 @@ + -
+
    + +
  • +

    New Plan

    +
  • + +
  • - -
+
+ -
+
  • - -
  • +
    + -
    +
  • +

    Plan Pricing

    +
  • + +
  • - -
  • +
    + -
    +
  • - -
  • +
    + + +

    + Note: Pricing should be in cents, i.e. a price of $10.00 should be entered as 1000. +

    -
    - - -
    +
  • +

    Additional Template Pricing

    +
  • -
    - - -
    +
  • + +
    +
  • -
    - - -
    +
  • + +
    +
  • -
    - - -
    +
  • + +
    +
  • + +
  • + +
    +
  • -
    - - -
    +
  • +

    Per-Plan Template Limits

    +
  • -
    - - -
    +
  • + +
    +
  • + +
  • + +
    +
  • -
    +
  • +

    Per-Plan Project Limits

    +
  • + +
  • - -
  • +
    + -
    +
  • - -
  • +
    + -
    +
  • - -
  • +
    + +
  • +

    Permissions

    +
  • +
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + + +

    + These permissions should harmonize with the restrictions on layouts set above. +

    + - +
  • + +
  • + diff --git a/views/staff/plans/edit.ejs b/views/staff/plans/edit.ejs index 503c97d..9848873 100644 --- a/views/staff/plans/edit.ejs +++ b/views/staff/plans/edit.ejs @@ -7,7 +7,7 @@
    -[[- include form ]] +[[- include _form ]]
    [[ include ../_footer ]] diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs index aa6c35a..121a2fc 100644 --- a/views/staff/plans/index.ejs +++ b/views/staff/plans/index.ejs @@ -6,6 +6,7 @@
    +[[ if (plans.length) { ]] @@ -30,7 +31,11 @@ [[ plans.forEach(function(plan){ ]] [[ }) ]] @@ -46,8 +51,10 @@ [[ }) ]] [[ }) ]] -
    [[- field.replace(/_/," ") ]] - [[- plan[field] ]] + [[ if (field.indexOf("_price") != -1) { ]] + [[- plan[field] == 0 ? "" : "$" + (plan[field]/100).toFixed(2) ]] + [[ } else { ]] + [[- plan[field] ]] + [[ } ]]
    +
    +[[ } ]] + New Plan
    diff --git a/views/staff/plans/new.ejs b/views/staff/plans/new.ejs index d56a1c3..297d3d6 100644 --- a/views/staff/plans/new.ejs +++ b/views/staff/plans/new.ejs @@ -7,9 +7,7 @@
    -[[- include form ]] +[[- include _form ]]
    [[ include ../_footer ]] - - -- cgit v1.2.3-70-g09d2 From b386c3b88034e4e372f147ffd368c2de1d23a865 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 07:28:43 -0500 Subject: saving plans --- public/assets/stylesheets/staff.css | 2 +- server/lib/views/staff.js | 6 +++++- views/staff/plans/_form.ejs | 10 +++++----- views/staff/plans/index.ejs | 34 +++++++++++++++++++--------------- 4 files changed, 30 insertions(+), 22 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index e5cafa2..fffadbf 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -67,7 +67,7 @@ hr { .staff .body a { border-bottom: 1px dotted; } -.staff .editLinks a { +.staff .editLinks a, .staff a.bluelink { color: #00f; border-bottom: 1px solid; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 6639137..2fdc2c3 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -629,6 +629,7 @@ var staff = module.exports = { res.render('staff/plans/new') }, edit: function(req, res){ + res.locals.plan = req.plan res.render('staff/plans/edit') }, create: function(req, res){ @@ -650,13 +651,16 @@ var staff = module.exports = { }) }, update: function(req, res){ + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + var data = util.cleanQuery(req.body) data.name = util.sanitize(data.name) data.slug = util.sanitize(data.slug.toLowerCase()) _.extend(req.plan, data) permissions.forEach(function(field){ - req.plan[field] = data["permissions_" + field] + req.plan.permissions[field] = data["permissions_" + field].length == 2 }) req.plan.save(function(err, doc){ diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index fc86516..ae5ca5a 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -107,31 +107,31 @@
  • - +
  • - +
  • - +
  • - +
  • - +
  • diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs index 121a2fc..16fcf14 100644 --- a/views/staff/plans/index.ejs +++ b/views/staff/plans/index.ejs @@ -6,31 +6,33 @@
    -[[ if (plans.length) { ]] - - [[ plans.forEach(function(plan){ ]] + [[ plans.forEach(function(plan){ ]] + [[ }) ]] - - - [[ plans.forEach(function(plan){ ]] + + [[ plans.forEach(function(plan){ ]] + [[ }) ]] [[ fields.forEach(function(field){ ]] - + [[ plans.forEach(function(plan){ ]] - [[ }) ]] + + + + [[ permissions.forEach(function(permission){ ]] - + [[ plans.forEach(function(plan){ ]] - [[ }) ]] [[ }) ]]
    - [[- plan.name ]] + + [[- plan.name ]]
    [[- field.replace(/_/," ") ]][[- field.replace(/_/g," ") ]] + [[ if (field.indexOf("_price") != -1) { ]] [[- plan[field] == 0 ? "" : "$" + (plan[field]/100).toFixed(2) ]] [[ } else { ]] @@ -41,20 +43,22 @@
    [[- permission.replace(/_/," ") ]][[- permission.replace(/_/g," ") ]] - [[- plan.permissions[permission] ? "x" : " " ]] + + [[- plan.permissions[permission] ? "x" : " " ]]

    -[[ } ]] - New Plan
    -- cgit v1.2.3-70-g09d2 From 63d8dd85a47c20d3c9bad963d7845d4d5b1c2e2e Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 08:23:35 -0500 Subject: very light styling on brochure page --- server/lib/views/staff.js | 1 + views/about/brochure.ejs | 122 +++++++++++++++++++++++++++++----------------- 2 files changed, 77 insertions(+), 46 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 2fdc2c3..97ecde6 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -128,6 +128,7 @@ var staff = module.exports = { ensurePlans: function(req, res, next){ Plan.find(function (err, plans) { res.locals.plans = (plans || []).map(staff.helpers.plan) + res.locals.plans.sort(function(a,b){ return a.monthly_price }) next() }) }, diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 4ce558a..75e7b60 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -13,58 +13,54 @@
    Want to get more out of VValls? Consider becoming a subscription user. +

    -
    -
    -

    [[- plans.free.name ]]

    -
      -
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan -
    -
    +
    +

    [[- plans.free.name ]]

    +
      +
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan +
    +
    -
    -

    [[- plans.premium.name ]]

    -
      -
    • $[[- plans.premium.monthly_price ]]/mo or $[[- plans.premium.yearly_price ]]/year -
    • [[- plans.premium.stock_project_limit ]] exhibitions included with pre-designed template floor plans -
    • Each new basic floor plan costs $[[- plans.premium.basic_layout_monthly_price ]]/mo - or $[[- plans.premium.basic_layout_yearly_price ]]/year, minimum 3 months -
    • Each new basic floor plan can have up to [[- plans.premium.basic_project_limit ]] exhibitions -
    • VValls logo appears when embedding an exhibition on a web page -
    -
    +
    +

    [[- plans.basic.name ]]

    +
      +
    • $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year +
    • [[- plans.basic.stock_project_limit ]] exhibitions included with pre-designed template floor plans +
    • Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo + or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months +
    • Each new basic floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions +
    • VValls logo appears when embedding an exhibition on a web page +
    +
    -
    -

    [[- plans.pro.name ]]

    -
      -
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year -
    • Comes with [[- plans.premium.pro_layout_limit ]] pro floor plan and [[- plans.premium.pro_project_limit ]] exhibitions -
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo - or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months -
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions -
    • Includes planning for 3D objects in the room -
    • No VValls logo on embed -
    -
    +
    +

    [[- plans.pro.name ]]

    +
      +
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year +
    • Comes with [[- plans.pro.pro_layout_limit ]] pro floor plan and [[- plans.pro.pro_project_limit ]] exhibitions +
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo + or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months +
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions +
    • Includes planning for 3D objects in the room +
    • No VValls logo on embed +
    +
    -
    - Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. -
    - -
    - Basic Floor plan: Rectangle-based design of any dimension. -
    - -
    - Pro Floor plan: Trace an arbitrary floor plan from image. -
    - +
    +
      +
    • Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. +
    • Basic Floor plan: Rectangle-based design of any dimension. +
    • Pro Floor plan: Trace an arbitrary floor plan from image. +
    +
    -
    -

    Custom

    - We offer many types of customizations and white-label options for business and educational uses. - Contact us for more information +
    +

    Custom

    +
  • We offer customized white-label options for business and educational uses. +
  • Contact us for more information. +
  • @@ -77,3 +73,37 @@ [[ include ../partials/scripts ]] + \ No newline at end of file -- cgit v1.2.3-70-g09d2 From afce400c65f362f7dd6307a5670dc3873d74ab79 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Sun, 11 Jan 2015 21:42:45 -0500 Subject: stub in subscriptions admin pages --- server/lib/views/staff.js | 34 +++++++++++++++++++++++++++++++++- views/staff/_nav.ejs | 1 + views/staff/subscriptions/index.ejs | 36 ++++++++++++++++++++++++++++++++++++ views/staff/subscriptions/show.ejs | 12 ++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 views/staff/subscriptions/index.ejs create mode 100644 views/staff/subscriptions/show.ejs (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 97ecde6..4351ef0 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -500,6 +500,27 @@ var staff = module.exports = { staff.plans.update ); + + // + // subscriptions + app.get('/staff/subscriptions', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscriptions, + staff.middleware.ensureSubscriptionsUsers, + + staff.subscriptions.index + ); + app.get('/staff/subscriptions/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscription, + staff.middleware.ensureSubscriptionUser, + + staff.subscriptions.edit + ); }, paginate: function(req, res){ @@ -669,6 +690,17 @@ var staff = module.exports = { res.redirect("/staff/plans/") }) }, - } + }, + + subscriptions: { + index: function(req, res){ + res.locals.subscriptions = req.subscriptions + res.render('staff/plans/index') + }, + show: function(req, res){ + res.locals.subscription = req.subscription + res.render('staff/plans/show') + }, + }, } diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index db7bedb..e79ff69 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -4,4 +4,5 @@ projects media plans + subscriptions \ No newline at end of file diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs new file mode 100644 index 0000000..d1c0588 --- /dev/null +++ b/views/staff/subscriptions/index.ejs @@ -0,0 +1,36 @@ +[[ include ../_header ]] + +

    Users

    + +[[ include ../_nav ]] + +
    + +[[ include ../_pagination ]] + + +[[ subscriptions.forEach(function(subscription){ ]] + + + + + + + +[[ }) ]] +
    +
    +
    + [[- subscription.user.username ]] + + [[- subscription.user.displayName ]] + + [[- subscription.user.last_seen ]] +
    + + +[[ include ../_pagination ]] + +[[ include ../_footer ]] diff --git a/views/staff/subscriptions/show.ejs b/views/staff/subscriptions/show.ejs new file mode 100644 index 0000000..e2839a6 --- /dev/null +++ b/views/staff/subscriptions/show.ejs @@ -0,0 +1,12 @@ +[[ include ../_header ]] +

    User: [[- subscription.user.username ]]

    + +[[ include ../_nav ]] + +
    + +
    +info to show..
    +- link to recurly profile
    +- link to vvalls profile
    +- subscription tier + add-ons
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From a1c9bdecff30d72eeaef54c66c7211966a97d4e4 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 21:57:17 -0500
    Subject: crud
    
    ---
     server/lib/views/staff.js | 69 ++++++++++++++++++++++++++++++++++++++++++++---
     1 file changed, 66 insertions(+), 3 deletions(-)
    
    (limited to 'server/lib/views/staff.js')
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 4351ef0..39a8dca 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -124,7 +124,35 @@ var staff = module.exports = {
             next()
           })
         },
    -    
    +
    +    ensureSubscriptions: function(req, res, next){
    +      var paginationInfo = res.locals.pagination = {}
    +      var criteria = req.criteria || {}
    +      var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 )
    +      var offset = paginationInfo.offset = Number(req.query.offset) || 0
    +      var sort
    +      paginationInfo.sort = req.query.sort
    +      paginationInfo.sortOptions = ["date", "name"]
    +      switch (req.query.sort) {
    +        case 'created':
    +          sort = {'created_at': -1}
    +          break
    +        default:
    +        case 'date':
    +          sort = {'updated_at': -1}
    +          break
    +      }
    +      Subscription.find(criteria)
    +          .select(staff.fields.project)
    +          .sort(sort)
    +          .skip(offset)
    +          .limit(limit)
    +          .exec(function (err, subscriptions) {
    +        res.locals.subscriptions = subscriptions.map(staff.helpers.subscription)
    +        next()
    +      })
    +    },
    +
         ensurePlans: function(req, res, next){
           Plan.find(function (err, plans) {
             res.locals.plans = (plans || []).map(staff.helpers.plan)
    @@ -150,6 +178,24 @@ var staff = module.exports = {
           }
         },
     
    +    ensureSubscription: function (req, res, next) {
    +      if (req.params.id) {
    +        Subscription.findOne({ _id: req.params.id }, function(err, subscription){
    +          if (err || ! subscription) {
    +            console.error(err)
    +            res.redirect("/staff/subscriptions/")
    +          }
    +          else {
    +            req.subscription = subscription
    +            next()
    +          }
    +        })
    +      }
    +      else {
    +        res.redirect("/staff/subscriptions/")
    +      }
    +    },
    +
         ensureRecentProjects: function(req, res, next){
           var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } }
           staff.middleware.ensureProjects(dreq, res, next)
    @@ -160,11 +206,23 @@ var staff = module.exports = {
           staff.middleware.ensureObjectsUsers(res.locals.projects, next)
         },
     
    +    ensureSubscriptionsUsers: function(req, res, next){
    +      if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() }
    +      staff.middleware.ensureObjectsUsers(res.locals.subscriptions, next)
    +    },
    +
         ensureMediaUsers: function(req, res, next){
           if (! res.locals.media || ! res.locals.media.length) { return next() }
           staff.middleware.ensureObjectsUsers(res.locals.media, next)
         },
     
    +    ensureSubscriptionUser: function(req, res, next){
    +      if (! res.locals.subscription) { return next() }
    +      staff.middleware.ensureObjectsUsers([ res.locals.subscription ], function(){
    +        next()
    +      })
    +    },
    +
         ensureMediaUser: function(req, res, next){
           if (! res.locals.media) { return next() }
           staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){
    @@ -338,6 +396,13 @@ var staff = module.exports = {
           plan.user = {}
           return plan
     	  },
    +
    +	  subscription: function(subscription){
    +      subscription = subscription.toObject()
    +      subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a")
    +      subscription.user = {}
    +      return subscription
    +	  },
     	},
     
     	route: function(app){
    @@ -694,11 +759,9 @@ var staff = module.exports = {
       
       subscriptions: {
         index: function(req, res){
    -      res.locals.subscriptions = req.subscriptions
           res.render('staff/plans/index')
         },
         show: function(req, res){
    -      res.locals.subscription = req.subscription
           res.render('staff/plans/show')
         },
       },
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From ffdee0615c775466053daff3ce4afd1d11c83e33 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 22:37:07 -0500
    Subject: pagination
    
    ---
     server/lib/views/staff.js | 7 +++++--
     1 file changed, 5 insertions(+), 2 deletions(-)
    
    (limited to 'server/lib/views/staff.js')
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 39a8dca..64cfe77 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -759,10 +759,13 @@ var staff = module.exports = {
       
       subscriptions: {
         index: function(req, res){
    -      res.render('staff/plans/index')
    +      res.locals.pagination.count = res.locals.subscriptions.length
    +      res.locals.pagination.max = res.locals.subscriptionCount
    +      staff.paginate(req, res)
    +      res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/plans/show')
    +      res.render('staff/subscriptions/show')
         },
       },
     
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 77c4c8d066611ad651af8df7290fb3e54d074081 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 23:37:49 -0500
    Subject: fix
    
    ---
     server/lib/views/staff.js | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    (limited to 'server/lib/views/staff.js')
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 64cfe77..d4abf1f 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -584,7 +584,7 @@ var staff = module.exports = {
           staff.middleware.ensureSubscription,
           staff.middleware.ensureSubscriptionUser,
     
    -      staff.subscriptions.edit
    +      staff.subscriptions.show
         );
       },
       
    @@ -765,7 +765,7 @@ var staff = module.exports = {
           res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/subscriptions/show')
    +      res.render('staff/subscriptions /show')
         },
       },
     
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From dcfbf734436fad76f5ca2e1cecadf4051118d56f Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Mon, 12 Jan 2015 12:24:57 -0500
    Subject: stubbing webhook
    
    ---
     server/index.js                  |  2 ++
     server/lib/views/staff.js        |  2 +-
     server/lib/views/subscription.js | 21 ++++++---------------
     3 files changed, 9 insertions(+), 16 deletions(-)
    
    (limited to 'server/lib/views/staff.js')
    
    diff --git a/server/index.js b/server/index.js
    index 9a9323c..a14eaab 100644
    --- a/server/index.js
    +++ b/server/index.js
    @@ -70,6 +70,8 @@ site.setup = function(){
     	app.all('*', middleware.ensureLocals);
     	app.all('*', middleware.ensureIP);
     
    +  app.get('/subscribe/webhook', views.subscription.webhook);
    +
     	server = http.createServer(app)
     	server.listen(app.get('port'), function () {
     		console.log('Express server listening on port ' + app.get('port'));
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index d4abf1f..74dd7cd 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -765,7 +765,7 @@ var staff = module.exports = {
           res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/subscriptions /show')
    +      res.render('staff/subscriptions/show')
         },
       },
     
    diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js
    index ba54bb4..e29e40d 100644
    --- a/server/lib/views/subscription.js
    +++ b/server/lib/views/subscription.js
    @@ -32,19 +32,10 @@ var subscription = module.exports = {
           return project
     	  },
     	},
    -
    -	route: function(app){
    -    app.get('/staff',
    -      middleware.ensureAuthenticated,
    -      middleware.ensureIsStaff,
    -      
    -      staff.middleware.ensureRecentUsers,
    -      staff.middleware.ensureUsersCount,
    -      staff.middleware.ensureProjectsCount,
    -      staff.middleware.ensureMediaCount,
    -
    -      staff.index
    -    );
    -  },
    -
    +	
    +  // need a route for the webhook,
    +  // then calls to get appropriate info from the recurly api
    +	webhook: function(req, res){
    +    res.status(200).end()
    +	},
     }
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 5adac681bdb43b8b709795fa501689fb9ae8a4e1 Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Wed, 28 Jan 2015 19:18:27 -0500
    Subject: many methods
    
    ---
     package.json                        |   1 +
     server/lib/api/subscription.js      | 124 ++++++++++++++++++++++++++++++++----
     server/lib/middleware.js            |   2 +-
     server/lib/schemas/Subscription.js  |   6 +-
     server/lib/views/staff.js           |   2 +-
     server/lib/webhook/webhook.js       |   2 +-
     views/about/brochure.ejs            |  15 +++--
     views/partials/header.ejs           |   1 +
     views/staff/_users.ejs              |   1 +
     views/staff/plans/_form.ejs         |   5 ++
     views/staff/subscriptions/index.ejs |   2 +-
     views/staff/users/show.ejs          |   1 +
     12 files changed, 135 insertions(+), 27 deletions(-)
    
    (limited to 'server/lib/views/staff.js')
    
    diff --git a/package.json b/package.json
    index 8afb96e..e89fcd9 100644
    --- a/package.json
    +++ b/package.json
    @@ -15,6 +15,7 @@
         "express-subdomains": "0.0.5",
         "html-entities": "~1.0.10",
         "intro.js": "^0.9.0",
    +    "js2xml": "^1.0.0",
         "knox": "~0.8.10",
         "lodash": "~2.4.1",
         "marked": "~0.3.2",
    diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js
    index 83644cf..40aa715 100644
    --- a/server/lib/api/subscription.js
    +++ b/server/lib/api/subscription.js
    @@ -9,7 +9,22 @@ var _ = require('lodash'),
     	Layout = require('../schemas/Layout'),
     	Subscription = require('../schemas/Subscription');
     
    +var plan_levels = {
    +  free: 0,
    +  basic: 1,
    +  pro: 2,
    +}
    +
     var subscription = module.exports = {
    +  middleware: {
    +    ensureSubscription: function(req, res, next){
    +      Subscription.findOne({ user_id: req.user._id }, function(err, data){
    +        if (err) { return next() }
    +        req.subscription = data
    +        next()
    +      })
    +    },
    +  }
     
     /*
     	index: function(req, res){
    @@ -18,30 +33,115 @@ var subscription = module.exports = {
     		})
     	},
     */
    -  middleware: {
    -    fetchAccount: function(req, res, next){
    -      recurly.subscriptions.listByAccount(req.user._id, function(data){
    -      })
    -    },
    -  },
     
       // synchronise an account with recurly..
    -  // useful when testing locally (if webhooks do not fire)
    +  // useful when testing locally (where webhooks cannot be received)
       sync: function(req, res){
    -    // fetch req.user._id
    +    var subscriber = req.subscription || new Subscription ()
    +    var user = req.user
    +    recurly.subscriptions.listByAccount(req.user._id, function(data){
    +      if (data.description !== 200) {
    +        res.json({ error: "no account" })
    +        return
    +      }
    +      if (! data.subscriptions.subscription) {
    +        res.json({ error: "account error" })
    +        return
    +      }
    +
    +      var plan = data.subscriptions.subscription.plan.plan_code.split("-")
    +      var plan_type = plan[0]
    +      var plan_period = plan[1]
    +      
    +      user.plan_type = plan_type
    +      user.plan_level = plan_levels[plan_type]
    +
    +      subscriber.uuid = data.subscriptions.subscription.uuid
    +      subscriber.user_id = user._id
    +      subscriber.plan_type = plan_type
    +      subscriber.plan_period = plan_period
    +      subscriber.plan_level = plan_levels[plan_type]
    +      
    +      var add_ons = data.subscriptions.subscription.subscription_add_ons.subscription_add_on
    +      if (add_ons) {
    +        if (add_ons.add_on_code) {
    +          add_ons = [ add_ons ]
    +        }
    +        // TODO: handle multiple add-ons.. presumably this will work
    +        add_ons.forEach(function(add_on){
    +          var add_on_type = add_on.add_on_code.split("-")[1]
    +          if (add_on_type == "basic") {
    +            subscriber.basic_layouts = parseInt( add_on.quantity._ )
    +          }
    +          if (add_on_type == "pro") {
    +            subscriber.pro_layouts = parseInt( add_on.quantity._ )
    +          }
    +        })
    +      }
    +      else {
    +        subscriber.basic_layouts = 0
    +        subscriber.pro_layouts = 0
    +      }
    +      
    +      subscriber.save(function(){
    +        user.save(function(){
    +          res.render(subscriber)
    +        })
    +      })
    +    })
       },
     
       show: function(req, res){
    -    // fetch from recurly
    +    res.json(req.subscription || { error: "no subscription" })
       },
       
       update: function(req, res){
    -    // update plan_type on recurly
    -    // update add_ons on recurly
    +    if (! req.subscription ) {
    +      return res.json({ error: "no subscription" })
    +    }
    +    if (! (req.body.plan_type in plan_levels)) {
    +      return res.json({ error: "bad input" })
    +    }
    +    var subscriber = req.subscription
    +    
    +    // change..
    +    // data.plan_code
    +    // data.subscription_add_ons = []
    +    //   add_on.add_on_code
    +    //   add_on.quantity
    +    var basic_layouts = max(0, parseInt(req.body.basic_layouts))
    +    var pro_layouts = max(0, parseInt(req.body.pro_layouts))
    +
    +    var data = {}
    +    data.plan_code = req.body.plan_type + "_monthly"
    +    data.subscription_add_ons = []
    +    
    +    if (plan_levels[req.body.plan_type]) {
    +      data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts })
    +    }
    +    
    +    if (req.body.plan_type == "pro") {
    +      data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts })
    +    }
    +    
    +    
    +    recurly.subscriptions.update(subscriber.uuid, data, function(){
    +      return res.json(subscriber)
    +    })
       },
       
       destroy: function(req, res){
    -    // destroy on recurly
    +    if (! req.subscription ) {
    +      return res.json({ error: "no subscription" })
    +    }
    +    var subscriber = req.subscription
    +
    +    recurly.subscriptions.cancel(subscriber.uuid, function(){
    +      subscriber.remove(function(){
    +        req.user.plan_code = 0
    +        req.user.plan_type = "free"
    +      })
    +    })
       },
     
     };
    \ No newline at end of file
    diff --git a/server/lib/middleware.js b/server/lib/middleware.js
    index 797d677..7dfe821 100644
    --- a/server/lib/middleware.js
    +++ b/server/lib/middleware.js
    @@ -59,7 +59,7 @@ var middleware = {
     		res.locals.opt = {}
     		next()
     	},
    -	
    +  
     	ensureProject: function (req, res, next) {
     		if (req.params.slug) {
     			Project.findOne({ slug: req.params.slug }, function(err, project){
    diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js
    index b766555..24c5096 100644
    --- a/server/lib/schemas/Subscription.js
    +++ b/server/lib/schemas/Subscription.js
    @@ -13,10 +13,8 @@ var SubscriptionSchema = new mongoose.Schema({
     	plan_period: { type: String, default: "monthly" },
     
     	subscription_uuid: { type: String },
    -	subscription_add_ons: [{
    -		name: { type: String },
    -		quantity: { type: Number },
    -	}],
    +	basic_layouts: { type: Number, default: 0 },
    +	pro_layouts: { type: Number, default: 0 },
     	
     	history: [{
     	  action: { type: String },
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 74dd7cd..67193fe 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -154,7 +154,7 @@ var staff = module.exports = {
         },
     
         ensurePlans: function(req, res, next){
    -      Plan.find(function (err, plans) {
    +      Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) {
             res.locals.plans = (plans || []).map(staff.helpers.plan)
             res.locals.plans.sort(function(a,b){ return a.monthly_price })
             next()
    diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js
    index 4f23d0b..a871a3a 100644
    --- a/server/lib/webhook/webhook.js
    +++ b/server/lib/webhook/webhook.js
    @@ -149,6 +149,6 @@ var subscribe = module.exports = {
     	
     	route: function(app){
     		app.post('/subscribe/webhook', subscribe.handle);
    -		app.get('/subscribe/list/:id', subscribe.list);
    +		app.get('/subscribe/list/:id', subscribe.middleware.ensureSubscription, subscribe.list);
     	},
     }
    diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs
    index 49b03db..1dad763 100644
    --- a/views/about/brochure.ejs
    +++ b/views/about/brochure.ejs
    @@ -34,12 +34,11 @@
             
  • VValls logo appears when embedding an exhibition on a web page
  • [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] - + + [[ } else if (! user.plan_level) { ]] + [[ } else if (user.plan_level == plan.level) { ]] Current Level - [[ } else { ]] [[ } ]]
  • @@ -56,11 +55,13 @@
  • No VValls logo on embed
  • [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] - + + [[ } else if (! user.plan_level) { ]] + [[ } else if (user.plan_level == plan.level) { ]] Current Level + [[ } else if (user.plan_level < plan.level) { ]] + [[ } ]] diff --git a/views/partials/header.ejs b/views/partials/header.ejs index ce5bab9..2acf2bc 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -64,6 +64,7 @@ [[ if (profile && String(user._id) == String(profile._id)) { ]] Settings + Subscription [[ } else if (! profile) { ]] Profile [[ } ]] diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index d46058f..053e289 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -12,6 +12,7 @@ [view profile] + [recurly] [[- user.last_seen ]] diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index ae5ca5a..b55c5cd 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -16,6 +16,11 @@
  • +
  • + +
    +
  • +
  • diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs index d1c0588..3efffb5 100644 --- a/views/staff/subscriptions/index.ejs +++ b/views/staff/subscriptions/index.ejs @@ -1,6 +1,6 @@ [[ include ../_header ]] -

    Users

    +

    Subscriptions

    [[ include ../_nav ]] diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index 4ce1d9a..d6a21d5 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -19,6 +19,7 @@ [view profile] [view media] + [view on recurly] -- cgit v1.2.3-70-g09d2 From b9ad0704417aaa8cf4da7a1ec2109959622bd454 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 11:31:31 -0500 Subject: setting up staging env --- server/lib/views/staff.js | 3 ++- views/staff/plans/_form.ejs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 67193fe..c3ecc97 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -728,8 +728,9 @@ var staff = module.exports = { data.name = util.sanitize(data.name) data.slug = util.sanitize(data.slug.toLowerCase()) + data.permissions = {} permissions.forEach(function(field){ - data[field] = data["permissions_" + field] + data.permissions[field] = data["permissions_" + field].length == 2 }) new Plan (data).save(function(err, doc){ diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index 0240e56..61be7e8 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -100,7 +100,7 @@
  • - +
  • -- cgit v1.2.3-70-g09d2 From ca838d172cbd7fca1f2cba3bb1f095821710920a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 17:53:16 -0500 Subject: userlist sort --- public/assets/stylesheets/staff.css | 14 ++++++++++++++ server/lib/views/staff.js | 4 +++- views/staff/_users.ejs | 13 +++++++++++++ views/staff/users/show.ejs | 31 ++++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 4 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index fffadbf..d93e46e 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -30,6 +30,15 @@ nav { nav a { margin-left: 10px; } +nav.subnav { + background: white; + padding: 10px; + font-weight: 200; + font-size: 12px; +} +.alphabet a { + margin-left: 5px; +} hr { border: 1px solid #bbb; margin: 10px auto 10px; @@ -62,8 +71,13 @@ hr { user-select: none; } .staff { + background: white; font-size: 15px; } +.staff hr { + border: 1px solid black; + border-top: 0; +} .staff .body a { border-bottom: 1px dotted; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index c3ecc97..b772859 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -368,8 +368,10 @@ var staff = module.exports = { helpers: { user: function(user){ + var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) user = user.toObject() - user.last_seen = moment( user.last_seen || user.updated_at || user.created_at ).fromNow() + user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() + user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") user.created_ip = util.num2ip( user.created_ip ) user.last_ip = util.num2ip( user.last_ip ) return user diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 46811b6..1af47aa 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,9 +1,22 @@ + + [[ users.forEach(function(user){ ]] + diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index d6a21d5..e441109 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -17,13 +17,38 @@ [[- profile.displayName ]]
    + [[- user.plan_type ]] + [[- user.last_charged ]] + [[- user.username ]]
    + + [[ if (profile.subscription) { ]] +

    Subscription

    + + + + + + + + + +
    + plan + + [[- profile.plan_type ]] +
    + last charged + + [[- profile.last_charged ]] +
    + [[ } ]] +

    Profile

    -- cgit v1.2.3-70-g09d2 From 1169b347c1f339b64f30466004a3f9a06ef7e117 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 18:16:09 -0500 Subject: find users by initial --- public/assets/stylesheets/staff.css | 8 ++++++++ server/lib/views/staff.js | 12 ++++++++++++ views/staff/_users.ejs | 10 ++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index d93e46e..ebc240a 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -39,6 +39,14 @@ nav.subnav { .alphabet a { margin-left: 5px; } +.body .error { + color: #f00; + border: 1px solid #f00; + margin: 20px 5px 200px 5px; + padding: 10px; + width: 400px; + display: inline-block; +} hr { border: 1px solid #bbb; margin: 10px auto 10px; diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index b772859..07050f1 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -38,6 +38,7 @@ var staff = module.exports = { var criteria = req.criteria || {} var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var initial = util.sanitize(req.query.initial) var sort paginationInfo.sort = req.query.sort paginationInfo.sortOptions = ["date", "last_seen", "username"] @@ -54,6 +55,9 @@ var staff = module.exports = { paginationInfo.sort = "username" break } + if (initial) { + criteria.username = new RegExp('^' + initial, "i") + } User.find(criteria) .select(staff.fields.user) .sort(sort) @@ -61,6 +65,14 @@ var staff = module.exports = { .limit(limit) .exec(function (err, users) { res.locals.users = users.map(staff.helpers.user) + if (! res.locals.users.length) { + if (initial) { + res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" + } + else { + res.locals.opt.error = "No users found" + } + } next() }) }, diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 1af47aa..9caf893 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,12 +1,18 @@ +[[ if (! users.length || opt.error) { ]] +
    + [[- opt.error ]] +
    +[[ } ]] +
    [[ users.forEach(function(user){ ]] -- cgit v1.2.3-70-g09d2 From f84ea4bf323f99479298f0576006267bf4182632 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 6 Aug 2015 17:50:55 -0400 Subject: pass thru plans --- public/assets/stylesheets/staff.css | 2 +- server/index.js | 2 ++ server/lib/middleware.js | 14 ++++++++++++-- server/lib/views/staff.js | 9 ++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index ebc240a..7ae4a1e 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -45,7 +45,7 @@ nav.subnav { margin: 20px 5px 200px 5px; padding: 10px; width: 400px; - display: inline-block; + display: block; } hr { border: 1px solid #bbb; diff --git a/server/index.js b/server/index.js index 4926a94..30cf69a 100644 --- a/server/index.js +++ b/server/index.js @@ -82,6 +82,8 @@ site.setup = function(){ // var io = websocket.listen(server) // auth.initSockets(io, SessionStore) + + middleware.updatePlans() } site.route = function () { diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 7dfe821..35c520c 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -6,11 +6,14 @@ var passport = require('passport'), config = require('../../config.json'), User = require('./schemas/User'), Collaborator = require('./schemas/Collaborator'), - Project = require('./schemas/Project'); + Project = require('./schemas/Project'), + Plan = require('./schemas/Plan'); var middleware = { + plans: [], + enableCORS: function (req, res, next) { res.header('Access-Control-Allow-Credentials', true); // TODO Check https vs. http @@ -46,7 +49,7 @@ var middleware = { }, ensureLocals: function (req, res, next) { - res.locals.token = req.csrfToken(); + res.locals.token = req.csrfToken() res.locals.logged_in = req.isAuthenticated() res.locals.user = req.user || { _id: undefined } res.locals.config = config @@ -56,6 +59,7 @@ var middleware = { res.locals.ogUrl = "http://vvalls.com/" res.locals.ogDescription = "3D gallery space, fully customizable" res.locals.ogAuthor = "VValls" + res.locals.plans = plans res.locals.opt = {} next() }, @@ -106,6 +110,12 @@ var middleware = { }) } }, + + updatePlans: function(){ + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + middleware.plans = plans.map(function(plan){ return plan.toObject() }) + }) + }, } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 07050f1..19b361d 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -56,7 +56,12 @@ var staff = module.exports = { break } if (initial) { - criteria.username = new RegExp('^' + initial, "i") + if (initial == "?") { + criteria.username = new RegExp('^[$a-zA-Z]', "i") + } + else { + criteria.username = new RegExp('^' + initial, "i") + } } User.find(criteria) .select(staff.fields.user) @@ -749,6 +754,7 @@ var staff = module.exports = { new Plan (data).save(function(err, doc){ if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() res.redirect("/staff/plans/") }) }, @@ -767,6 +773,7 @@ var staff = module.exports = { req.plan.save(function(err, doc){ if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() res.redirect("/staff/plans/") }) }, -- cgit v1.2.3-70-g09d2 From 33e5644226649d277c6b84dc37fccdd5b7c6e86c Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 7 Aug 2015 12:23:35 -0400 Subject: more accurate counts --- public/assets/javascripts/ui/site/LayoutsModal.js | 10 ++-- server/lib/api/layouts.js | 4 +- server/lib/middleware.js | 60 +++++++++++++++++++++-- server/lib/schemas/Plan.js | 2 +- server/lib/schemas/Project.js | 1 + server/lib/views/staff.js | 45 ++++++++++++++++- views/staff/_nav.ejs | 1 + views/staff/plans/_form.ejs | 6 +-- views/staff/projects/index.ejs | 2 +- 9 files changed, 113 insertions(+), 18 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 639d55c..f69b38f 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -16,13 +16,15 @@ var LayoutsIndex = View.extend({ populate: function(data){ /* - if (data.layoutCount > data.plan.basic_layout_limit) { + if (data.layoutCounts.basic > data.plan.basic_layout_limit) { } - if (data.projectCount > data.plan.stock_project_limit) { + if (data.layoutCounts.pro > data.plan.pro_layout_limit) { } - if (data.projectCount > data.plan.basic_project_limit) { + if (data.projectCounts.stock > data.plan.stock_project_limit) { } - if (data.projectCount > data.plan.pro_project_limit) { + if (data.projectCounts.basic > data.plan.basic_project_limit) { + } + if (data.projectCounts.pro > data.plan.pro_project_limit) { } */ if (! data.layouts.length) { diff --git a/server/lib/api/layouts.js b/server/lib/api/layouts.js index 7e7976c..1c87fae 100644 --- a/server/lib/api/layouts.js +++ b/server/lib/api/layouts.js @@ -16,8 +16,8 @@ var layouts = { layouts: docs, plan: middleware.plans[ res.locals.user.plan_level || 0 ], user: res.locals.user, - layoutCount: res.locals.layoutCount, - projectCount: res.locals.projectCount, + layoutCounts: res.locals.layoutCounts, + projectCounts: res.locals.projectCounts, }) }) }, diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 9d09a10..fe4dc49 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -60,20 +60,48 @@ var middleware = { res.locals.ogUrl = "http://vvalls.com/" res.locals.ogDescription = "3D gallery space, fully customizable" res.locals.ogAuthor = "VValls" - res.locals.plans = plans + res.locals.plans = middleware.plans res.locals.opt = {} next() }, ensureUserProjectsCount: function(req, res, next){ - Project.count({ user_id: req.user.id }, function(err, count){ - res.locals.projectCount = count || 0 + var counts = { stock: 0, basic: 0, pro: 0 } + res.locals.projectCounts = counts + Project.count({ user_id: req.user.id, layout_type: 0 }, function(err, count){ + res.locals.projectCounts.stock = count || 0 + if (req.user.plan_level > 0) { return middleware.ensureBasicProjectsCount(req, res, next) } + else next() + }) + }, + ensureBasicProjectsCount: function(req, res, next){ + Project.count({ user_id: req.user.id, layout_type: 1 }, function(err, count){ + res.locals.projectCounts.basic = count || 0 + if (req.user.plan_level > 1) { return middleware.ensureProProjectsCount(req, res, next) } + else next() + }) + }, + ensureProProjectsCount: function(req, res, next){ + Project.count({ user_id: req.user.id, layout_type: 2 }, function(err, count){ + res.locals.projectCounts.pro = count || 0 next() }) }, + ensureUserLayoutsCount: function(req, res, next){ - Layout.count({ user_id: req.user.id }, function(err, count){ - res.locals.layoutCount = count || 0 + var counts = { basic: 0, pro: 0 } + res.locals.layoutCounts = counts + if (req.user.plan_level == 0) { return next() } + + Layout.count({ user_id: req.user.id, layout_type: 1 }, function(err, count){ + res.locals.layoutCounts.basic = count || 0 + if (req.user.plan_level > 1) { return middleware.ensureProLayoutsCount(req, res, next) } + else next() + }) + }, + ensureProLayoutsCount: function(req, res, next){ + Project.count({ user_id: req.user.id, layout_type: 2 }, function(err, count){ + res.locals.layoutCounts.pro = count || 0 next() }) }, @@ -100,6 +128,28 @@ var middleware = { } }, + ensureLayout: function (req, res, next) { + if (req.params.slug) { + Layout.findOne({ slug: req.params.slug }, function(err, layout){ + if (err) { + console.error(err) + req.layout = null + } + else if (! project) { + req.layout = null + } + else { + req.layout = layout + } + next() + }) + } + else { + req.layout = null + next() + } + }, + ensureIsCollaborator: function(req, res, next) { req.isCollaborator = false req.isOwner = false diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js index 8a19b99..388ce69 100644 --- a/server/lib/schemas/Plan.js +++ b/server/lib/schemas/Plan.js @@ -31,7 +31,7 @@ var PlanSchema = new mongoose.Schema({ permissions: { basic_editor: { type: Boolean, default: false }, pro_editor: { type: Boolean, default: false }, - solids: { type: Boolean, default: false }, + sculpture: { type: Boolean, default: false }, collaborators: { type: Boolean, default: false }, no_logo: { type: Boolean, default: false }, }, diff --git a/server/lib/schemas/Project.js b/server/lib/schemas/Project.js index e9501fc..855d95a 100644 --- a/server/lib/schemas/Project.js +++ b/server/lib/schemas/Project.js @@ -39,6 +39,7 @@ var ProjectSchema = new mongoose.Schema({ created_at: { type: Date }, updated_at: { type: Date }, featured: { type: Boolean, default: false }, + layout_type: { type: Number, default: 0 }, }); module.exports = exports = mongoose.model('project', ProjectSchema); diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 19b361d..6c97bbd 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -21,7 +21,7 @@ var staff = module.exports = { plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + "pro_layout_monthly_price pro_layout_yearly_price " + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", - plans_permissions: "basic_editor pro_editor solids collaborators no_logo", + plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", }, defaults: { @@ -401,6 +401,13 @@ var staff = module.exports = { return project }, + layout: function(layout){ + layout = layout.toObject() + layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") + layout.user = {} + return layout + }, + media: function(media){ media = media.toObject() media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") @@ -520,7 +527,41 @@ var staff = module.exports = { staff.projects.feature ); - + + // + // layouts + + app.get('/staff/layouts', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureLayoutsCount, + + staff.middleware.ensureLayouts, + staff.middleware.ensureLayoutsUsers, + + staff.layouts.index + ); + app.get('/staff/layouts/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + staff.middleware.ensureLayoutUser, + + staff.layouts.show + ); + app.put('/staff/layouts/:slug/feature', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + + staff.layouts.make_stock + ); + // // media diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index a607638..3bb3b08 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -2,6 +2,7 @@ home users projects + layouts media plans diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index 61be7e8..85375fa 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -124,9 +124,9 @@
  • - - - + + +
  • diff --git a/views/staff/projects/index.ejs b/views/staff/projects/index.ejs index e4ba469..1d309ce 100644 --- a/views/staff/projects/index.ejs +++ b/views/staff/projects/index.ejs @@ -7,7 +7,7 @@
    [[ include ../_pagination ]] -[[ include ../_projects ]] +[[ include ../_layouts ]] [[ include ../_pagination ]] [[ include ../_footer ]] -- cgit v1.2.3-70-g09d2 From a8005cd5db8d24342a6b7d53ccedc9808050eef7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 7 Aug 2015 14:58:34 -0400 Subject: layouts staff stuff --- server/lib/schemas/Layout.js | 2 ++ server/lib/views/staff.js | 75 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/schemas/Layout.js b/server/lib/schemas/Layout.js index e3f2616..cff1d78 100644 --- a/server/lib/schemas/Layout.js +++ b/server/lib/schemas/Layout.js @@ -26,6 +26,8 @@ var LayoutSchema = new mongoose.Schema({ rooms: [mongoose.Schema.Types.Mixed], startPosition: mongoose.Schema.Types.Mixed, viewHeight: { type: Number }, + is_stock: { type: Boolean, default: false }, + is_pro: { type: Boolean, default: false }, user_id: { type: mongoose.Schema.ObjectId, index: true }, created_at: { type: Date }, updated_at: { type: Date }, diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 6c97bbd..0fdbbb7 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -17,7 +17,8 @@ var staff = module.exports = { fields: { user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - project: "_id name slug user_id privacy created_at updated_at", + project: "_id name slug user_id privacy layout_type created_at updated_at", + layout: "_id name slug user_id layout_type created_at updated_at", plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + "pro_layout_monthly_price pro_layout_yearly_price " + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", @@ -116,6 +117,35 @@ var staff = module.exports = { }) }, + ensureLayouts: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Layout.find(criteria) + .select(staff.fields.layout) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, layouts) { + res.locals.layouts = layouts.map(staff.helpers.layout) + next() + }) + }, + ensureMedia: function(req, res, next){ var paginationInfo = res.locals.pagination = {} var criteria = req.criteria || {} @@ -223,6 +253,11 @@ var staff = module.exports = { staff.middleware.ensureObjectsUsers(res.locals.projects, next) }, + ensureLayoutsUsers: function(req, res, next){ + if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } + staff.middleware.ensureObjectsUsers(res.locals.layouts, next) + }, + ensureSubscriptionsUsers: function(req, res, next){ if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } staff.middleware.ensureObjectsUsers(res.locals.subscriptions, next) @@ -321,6 +356,13 @@ var staff = module.exports = { }) }, + ensureLayoutsCount: function(req, res, next){ + Layout.count({}, function(err, count){ + res.locals.layoutCount = count || 0 + next() + }) + }, + ensureMediaCount: function(req, res, next){ Media.count({}, function(err, count){ res.locals.mediaCount = count || 0 @@ -552,7 +594,7 @@ var staff = module.exports = { staff.layouts.show ); - app.put('/staff/layouts/:slug/feature', + app.put('/staff/layouts/:slug/stock', middleware.ensureAuthenticated, middleware.ensureIsStaff, @@ -561,7 +603,7 @@ var staff = module.exports = { staff.layouts.make_stock ); - + // // media @@ -744,7 +786,34 @@ var staff = module.exports = { }) }, }, + + // /staff/layouts/ + // /staff/layouts/:name + layouts: { + index: function(req, res){ + res.locals.pagination.count = res.locals.layouts.length + res.locals.pagination.max = res.locals.layoutCount + staff.paginate(req, res) + res.render('staff/layouts/index') + }, + show: function(req, res){ + if (res.locals.layout) { + res.render('staff/layouts/show', { + }) + } + else { + res.render('staff/layouts/show_404') + } + }, + feature: function(req, res){ + res.locals.layout.is_stock = req.body.state == "true" + res.locals.layout.save(function(err, layout){ + res.json({ state: layout.featured }) + }) + }, + }, + media: { index: function(req, res){ res.locals.pagination.count = res.locals.media.length -- cgit v1.2.3-70-g09d2 From 6f0e2933af03a3fb89b5ce2df0579fd8ef6c175b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 7 Aug 2015 18:07:59 -0400 Subject: fix --- server/lib/views/staff.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 0fdbbb7..a3d5bea 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -423,6 +423,19 @@ var staff = module.exports = { next() }) }, + + ensureLayout: function(req, res, next){ + res.locals.layout = req.layout + next() + }, + ensureLayoutUser: function(req, res, next){ + if (! res.locals.layout) { return next() } + User.findOne({ _id: res.locals.layout.user_id }, staff.fields.user, function(err, user){ + res.locals.layoutUser = staff.helpers.user(user) || staff.defaults.user + next() + }) + }, + }, helpers: { @@ -805,7 +818,7 @@ var staff = module.exports = { res.render('staff/layouts/show_404') } }, - feature: function(req, res){ + make_stock: function(req, res){ res.locals.layout.is_stock = req.body.state == "true" res.locals.layout.save(function(err, layout){ res.json({ state: layout.featured }) -- cgit v1.2.3-70-g09d2 From 71c3a4a02c7c46533aec836ef30a0d0ffa96399b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 10 Aug 2015 18:20:22 -0400 Subject: layout stuff --- .../javascripts/mx/extensions/mx.movements.js | 6 +- .../assets/javascripts/mx/primitives/mx.image.js | 3 +- .../rectangles/engine/map/tools/ortho.js | 26 +- .../rectangles/engine/map/tools/polyline.js | 24 +- .../rectangles/engine/shapes/shapelist.js | 1 + public/assets/javascripts/ui/lib/Toolbar.js | 22 ++ public/assets/javascripts/ui/site/StaffView.js | 26 +- public/assets/test/ortho3.html | 38 +-- public/assets/test/ortho4.html | 261 +++++++++++++++++++++ server/lib/middleware.js | 2 +- server/lib/schemas/Media.js | 1 + server/lib/views/staff.js | 3 +- views/staff/_layouts.ejs | 2 +- views/staff/layouts/show.ejs | 4 +- 14 files changed, 352 insertions(+), 67 deletions(-) create mode 100644 public/assets/javascripts/ui/lib/Toolbar.js create mode 100644 public/assets/test/ortho4.html (limited to 'server/lib/views/staff.js') diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js index fa59908..9ed8790 100644 --- a/public/assets/javascripts/mx/extensions/mx.movements.js +++ b/public/assets/javascripts/mx/extensions/mx.movements.js @@ -162,13 +162,13 @@ MX.Movements = function (cam) { case 8: // backspace e.preventDefault() - if (app.controller.sculptureEditor.sculpture) { + if (app.controller.sculptureEditor && app.controller.sculptureEditor.sculpture) { app.controller.sculptureEditor.sculpture.remove() } - else if (app.controller.mediaEditor.scenery) { + else if (app.controller.mediaEditor && app.controller.mediaEditor.scenery) { app.controller.mediaEditor.scenery.remove() } - else if (app.controller.textEditor.scenery) { + else if (app.controller.textEditor && app.controller.textEditor.scenery) { app.controller.textEditor.scenery.remove() } } diff --git a/public/assets/javascripts/mx/primitives/mx.image.js b/public/assets/javascripts/mx/primitives/mx.image.js index 64de4b2..f9de141 100644 --- a/public/assets/javascripts/mx/primitives/mx.image.js +++ b/public/assets/javascripts/mx/primitives/mx.image.js @@ -17,7 +17,7 @@ MX.Image = MX.Object3D.extend({ this.el.style.backgroundRepeat = 'no-repeat' - this.load(ops) + ops.src && this.load(ops) }, load: function(ops){ @@ -64,7 +64,6 @@ MX.Image = MX.Object3D.extend({ if (recenter) { ctx.restore() } - }, }) diff --git a/public/assets/javascripts/rectangles/engine/map/tools/ortho.js b/public/assets/javascripts/rectangles/engine/map/tools/ortho.js index be3d707..ef41096 100644 --- a/public/assets/javascripts/rectangles/engine/map/tools/ortho.js +++ b/public/assets/javascripts/rectangles/engine/map/tools/ortho.js @@ -12,11 +12,11 @@ var OrthoPolylineTool = MapTool.extend(function (base) { if (map.ui.placing) { // close polyline or cancel map.ui.placing = false - if (line.points.length > 2) { - line.build() + if (shapes.workline.points.length > 2) { + shapes.workline.build() } else { - line.reset() + shapes.workline.reset() } return } @@ -29,24 +29,24 @@ var OrthoPolylineTool = MapTool.extend(function (base) { // compare to initial point var p = last_point.clone() if (map.ui.placing) { - if (line.lastPoint().eq(p)) { + if (shapes.workline.lastPoint().eq(p)) { return } - else if (line.canCloseWith(p)) { - line.close() - line.build() + else if (shapes.workline.canCloseWith(p)) { + shapes.workline.close() + shapes.workline.build() map.ui.placing = false } else { - line.add(p) + shapes.workline.add(p) prev_point = p horizontal = ! horizontal } } else { map.ui.placing = true - line = new Polyline () - line.add(p) + shapes.workline = new Polyline () + shapes.workline.add(p) first_point = prev_point = p horizontal = false } @@ -55,7 +55,7 @@ var OrthoPolylineTool = MapTool.extend(function (base) { last_point.a = cursor.x.a last_point.b = cursor.y.a if (map.ui.placing) { - if (line.points.length == 1) { + if (shapes.workline.points.length == 1) { var x = abs(prev_point.a - last_point.a) var y = abs(prev_point.b - last_point.b) if (x > y) { @@ -86,7 +86,7 @@ var OrthoPolylineTool = MapTool.extend(function (base) { } } - if (line.canCloseWith(last_point)) { + if (shapes.workline.canCloseWith(last_point)) { document.body.style.cursor = "pointer" last_point.assign(first_point) cursor.x.a = cursor.x.b = last_point.a @@ -107,7 +107,7 @@ var OrthoPolylineTool = MapTool.extend(function (base) { } } exports.cancel = function(){ - if (map.ui.placing) { line.reset() } + if (map.ui.placing) { shapes.workline.reset() } first_point = null map.ui.placing = false } diff --git a/public/assets/javascripts/rectangles/engine/map/tools/polyline.js b/public/assets/javascripts/rectangles/engine/map/tools/polyline.js index 559aea8..1ab86f6 100644 --- a/public/assets/javascripts/rectangles/engine/map/tools/polyline.js +++ b/public/assets/javascripts/rectangles/engine/map/tools/polyline.js @@ -9,11 +9,11 @@ var PolylineTool = MapTool.extend(function (base) { if (map.ui.placing) { // close polyline or cancel map.ui.placing = false - if (line.points.length > 2) { - line.build() + if (shapes.workline.points.length > 2) { + shapes.workline.build() } else { - line.reset() + shapes.workline.reset() } return } @@ -24,27 +24,27 @@ var PolylineTool = MapTool.extend(function (base) { // compare to initial point var p = last_point.clone() if (map.ui.placing) { - if (line.canCloseWith(p)) { - line.close() - line.build() + if (shapes.workline.canCloseWith(p)) { + shapes.workline.close() + shapes.workline.build() map.ui.placing = false } else { - line.add(p) + shapes.workline.add(p) } } else { map.ui.placing = true - line = new Polyline () - line.add(p) + shapes.workline = new Polyline () + shapes.workline.add(p) } } exports.move = function(e, cursor){ last_point.a = cursor.x.a last_point.b = cursor.y.a - if (map.ui.placing && line.canCloseWith(last_point)) { + if (map.ui.placing && shapes.workline.canCloseWith(last_point)) { document.body.style.cursor = "pointer" - last_point.assign(line.points[0]) + last_point.assign(shapes.workline.points[0]) cursor.x.a = cursor.x.b = last_point.a cursor.y.a = cursor.y.b = last_point.b return @@ -62,7 +62,7 @@ var PolylineTool = MapTool.extend(function (base) { } } exports.cancel = function(){ - if (map.ui.placing) { line.reset() } + if (map.ui.placing) { shapes.workline.reset() } map.ui.placing = false } return exports diff --git a/public/assets/javascripts/rectangles/engine/shapes/shapelist.js b/public/assets/javascripts/rectangles/engine/shapes/shapelist.js index 00e1a4e..932ce36 100644 --- a/public/assets/javascripts/rectangles/engine/shapes/shapelist.js +++ b/public/assets/javascripts/rectangles/engine/shapes/shapelist.js @@ -2,6 +2,7 @@ var ShapeList = Fiber.extend(function(base){ var exports = {} exports.init = function(){ this.shapes = [] + this.workline = null } exports.add = function(shape){ this.shapes.push(shape) diff --git a/public/assets/javascripts/ui/lib/Toolbar.js b/public/assets/javascripts/ui/lib/Toolbar.js new file mode 100644 index 0000000..a9ce51c --- /dev/null +++ b/public/assets/javascripts/ui/lib/Toolbar.js @@ -0,0 +1,22 @@ +var Toolbar = Fiber.extend(function(base){ + var exports = {} + exports.init = function(rapper){ + this.rapper = (typeof rapper == "string") ? $(rapper)[0] : rapper + this.tools = {} + this.els = {} + } + exports.add = function(role, fn){ + var self = this + this.tools[role] = fn + this.els[role] = $("[data-role=" + role + "]", self.rapper) + this.els[role].click(function(){ + $(".active", self.rapper).removeClass('active') + $(this).addClass('active') + fn() + }) + } + exports.pick = function(role){ + this.els[role].trigger("click") + } + return exports +}) \ No newline at end of file diff --git a/public/assets/javascripts/ui/site/StaffView.js b/public/assets/javascripts/ui/site/StaffView.js index 0398f71..59649e3 100644 --- a/public/assets/javascripts/ui/site/StaffView.js +++ b/public/assets/javascripts/ui/site/StaffView.js @@ -4,11 +4,13 @@ var StaffView = View.extend({ events: { "click #toggle-staff": "toggleStaff", "click #toggle-featured": "toggleFeatured", + "click #toggle-stock": "toggleStock", }, initialize: function() { this.$toggleStaff = $("#toggle-staff") this.$toggleFeatured = $("#toggle-featured") + this.$toggleStock = $("#toggle-stock") this.$mediaEmbed = $("#media-embed") if (this.$toggleStaff.length && this.$toggleStaff.data().isstaff) { this.$toggleStaff.html("Is Staff") @@ -16,6 +18,9 @@ var StaffView = View.extend({ if (this.$toggleFeatured.length && this.$toggleFeatured.data().featured) { this.$toggleFeatured.html("Featured Project") } + if (this.$toggleStock.length && this.$toggleStock.data().stock) { + this.$toggleStock.html("Layout is Stock") + } if (this.$mediaEmbed.length) { var media = this.$mediaEmbed.data() this.$mediaEmbed.html( Parser.tag( media ) ) @@ -67,6 +72,25 @@ var StaffView = View.extend({ $("#isFeaturedProject").html(data.state ? "yes" : "no") }.bind(this) }) - }, + }, + + toggleStock: function(){ + console.log("stock") + var state = ! this.$toggleStock.data().stock + $.ajax({ + type: "put", + dataType: "json", + url: window.location.href + "/stock", + data: { + state: state, + _csrf: $("#_csrf").val(), + }, + success: function(data){ + this.$toggleStock.data("stock", data.state) + this.$toggleStock.html(data.state ? "Stock Layout" : "Make this layout Stock") + $("#isStockLayout").html(data.state ? "yes" : "no") + }.bind(this) + }) + }, }) diff --git a/public/assets/test/ortho3.html b/public/assets/test/ortho3.html index ef5732c..f41a0ba 100644 --- a/public/assets/test/ortho3.html +++ b/public/assets/test/ortho3.html @@ -80,6 +80,7 @@ body { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 94c4acd..04cb330 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -114,7 +114,7 @@ var middleware = { console.error(err) req.layout = null } - else if (! project) { + else if (! layout) { req.layout = null } else { diff --git a/server/lib/schemas/Media.js b/server/lib/schemas/Media.js index 8247467..f37fb12 100644 --- a/server/lib/schemas/Media.js +++ b/server/lib/schemas/Media.js @@ -42,6 +42,7 @@ var MediaSchema = new mongoose.Schema({ mute: { type: Boolean, default: false }, keyframe: { type: Number, default: 0.0 }, tag: { type: String, default: "" }, + scale: { type: Number, default: 1.0 }, widthDimension: { type: Number }, heightDimension: { type: Number }, diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index a3d5bea..43330e2 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -6,6 +6,7 @@ var User = require('../schemas/User'), Collaborator = require('../schemas/Collaborator'), Plan = require('../schemas/Plan'), Subscription = require('../schemas/Subscription'), + Layout = require('../schemas/Layout'), config = require('../../../config'), middleware = require('../middleware'), util = require('../util'), @@ -821,7 +822,7 @@ var staff = module.exports = { make_stock: function(req, res){ res.locals.layout.is_stock = req.body.state == "true" res.locals.layout.save(function(err, layout){ - res.json({ state: layout.featured }) + res.json({ state: layout.is_stock }) }) }, }, diff --git a/views/staff/_layouts.ejs b/views/staff/_layouts.ejs index 3f3e6b2..d97883b 100644 --- a/views/staff/_layouts.ejs +++ b/views/staff/_layouts.ejs @@ -1,5 +1,5 @@
  • -[[ layouts.forEach(function(project){ ]] +[[ layouts.forEach(function(layout){ ]]
    [[- layout.name ]] diff --git a/views/staff/layouts/show.ejs b/views/staff/layouts/show.ejs index 0a2014b..b66449f 100644 --- a/views/staff/layouts/show.ejs +++ b/views/staff/layouts/show.ejs @@ -45,14 +45,14 @@ featured? - [[- layout.plan_type == 0 ? "yes" : "no" ]] + [[- layout.is_stock ? "yes" : "no" ]]


    - +

    -- cgit v1.2.3-70-g09d2 From d9050d0faacb0434a94e4bce2acc8f99e189db4f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 12 Aug 2015 12:30:44 -0400 Subject: refactor staff area --- server/lib/views/staff.js | 918 ----------------------------------- server/lib/views/staff/defaults.js | 6 + server/lib/views/staff/fields.js | 9 + server/lib/views/staff/helpers.js | 52 ++ server/lib/views/staff/index.js | 452 +++++++++++++++++ server/lib/views/staff/middleware.js | 421 ++++++++++++++++ views/staff/projects/index.ejs | 2 +- 7 files changed, 941 insertions(+), 919 deletions(-) delete mode 100644 server/lib/views/staff.js create mode 100644 server/lib/views/staff/defaults.js create mode 100644 server/lib/views/staff/fields.js create mode 100644 server/lib/views/staff/helpers.js create mode 100644 server/lib/views/staff/index.js create mode 100644 server/lib/views/staff/middleware.js (limited to 'server/lib/views/staff.js') diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js deleted file mode 100644 index 43330e2..0000000 --- a/server/lib/views/staff.js +++ /dev/null @@ -1,918 +0,0 @@ -/* jshint node: true */ - -var User = require('../schemas/User'), - Project = require('../schemas/Project'), - Media = require('../schemas/Media'), - Collaborator = require('../schemas/Collaborator'), - Plan = require('../schemas/Plan'), - Subscription = require('../schemas/Subscription'), - Layout = require('../schemas/Layout'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'); - - -var staff = module.exports = { - - fields: { - user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - project: "_id name slug user_id privacy layout_type created_at updated_at", - layout: "_id name slug user_id layout_type created_at updated_at", - plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + - "pro_layout_monthly_price pro_layout_yearly_price " + - "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", - plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", - }, - - defaults: { - user: { - _id: "", username: "", displayName: "", - created_at: "", updated_at: "", created_ip: "", last_ip: "", - }, - }, - - middleware: { - - ensureUsers: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var initial = util.sanitize(req.query.initial) - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "last_seen", "username"] - switch (req.query.sort) { - case 'date': - sort = {'created_at': -1} - break - case 'last_seen': - sort = {'last_seen': -1} - break - case 'username': - default: - sort = {'username': 1} - paginationInfo.sort = "username" - break - } - if (initial) { - if (initial == "?") { - criteria.username = new RegExp('^[$a-zA-Z]', "i") - } - else { - criteria.username = new RegExp('^' + initial, "i") - } - } - User.find(criteria) - .select(staff.fields.user) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, users) { - res.locals.users = users.map(staff.helpers.user) - if (! res.locals.users.length) { - if (initial) { - res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" - } - else { - res.locals.opt.error = "No users found" - } - } - next() - }) - }, - - ensureRecentUsers: function(req, res, next){ - var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } - staff.middleware.ensureUsers(dreq, res, next) - }, - - ensureProjects: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - default: - case 'date': - sort = {'updated_at': -1} - break - case 'name': - paginationInfo.sort = "name" - sort = {'slug': 1} - break - } - Project.find(criteria) - .select(staff.fields.project) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, projects) { - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureLayouts: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - default: - case 'date': - sort = {'updated_at': -1} - break - case 'name': - paginationInfo.sort = "name" - sort = {'slug': 1} - break - } - Layout.find(criteria) - .select(staff.fields.layout) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, layouts) { - res.locals.layouts = layouts.map(staff.helpers.layout) - next() - }) - }, - - ensureMedia: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date"] - switch (req.query.sort) { - default: - case 'date': - paginationInfo.sort = "date" - sort = {'created_at': -1} - break - } - Media.find(criteria) - // .select(staff.fields.media) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, media) { - res.locals.media = media.map(staff.helpers.media) - next() - }) - }, - - ensureSubscriptions: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - case 'created': - sort = {'created_at': -1} - break - default: - case 'date': - sort = {'updated_at': -1} - break - } - Subscription.find(criteria) - .select(staff.fields.project) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, subscriptions) { - res.locals.subscriptions = subscriptions.map(staff.helpers.subscription) - next() - }) - }, - - ensurePlans: function(req, res, next){ - Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { - res.locals.plans = (plans || []).map(staff.helpers.plan) - res.locals.plans.sort(function(a,b){ return a.monthly_price }) - next() - }) - }, - ensurePlan: function (req, res, next) { - if (req.params.slug) { - Plan.findOne({ slug: req.params.slug }, function(err, plan){ - if (err || ! plan) { - console.error(err) - res.redirect("/staff/plans/") - } - else { - req.plan = plan - next() - } - }) - } - else { - res.redirect("/staff/plans/") - } - }, - - ensureSubscription: function (req, res, next) { - if (req.params.id) { - Subscription.findOne({ _id: req.params.id }, function(err, subscription){ - if (err || ! subscription) { - console.error(err) - res.redirect("/staff/subscriptions/") - } - else { - req.subscription = subscription - next() - } - }) - } - else { - res.redirect("/staff/subscriptions/") - } - }, - - ensureRecentProjects: function(req, res, next){ - var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } - staff.middleware.ensureProjects(dreq, res, next) - }, - - ensureProjectsUsers: function(req, res, next){ - if (! res.locals.projects || ! res.locals.projects.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.projects, next) - }, - - ensureLayoutsUsers: function(req, res, next){ - if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.layouts, next) - }, - - ensureSubscriptionsUsers: function(req, res, next){ - if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.subscriptions, next) - }, - - ensureMediaUsers: function(req, res, next){ - if (! res.locals.media || ! res.locals.media.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.media, next) - }, - - ensureSubscriptionUser: function(req, res, next){ - if (! res.locals.subscription) { return next() } - staff.middleware.ensureObjectsUsers([ res.locals.subscription ], function(){ - next() - }) - }, - - ensureMediaUser: function(req, res, next){ - if (! res.locals.media) { return next() } - staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){ - res.locals.mediaUser = res.locals.media.User - next() - }) - }, - - ensureObjectsUsers: function(objects, next){ - if (! objects) { return next () } - var dedupe = {}, user_ids - objects.forEach(function(obj){ - dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] - dedupe[ obj.user_id ].push(obj) - }) - user_ids = _.keys(dedupe) - User.find({ _id: { $in: user_ids } }) - .select(staff.fields.user) - .exec(function (err, users) { - if (! users) { return next () } - users.forEach(function(user){ - dedupe[user._id].forEach(function(obj){ - obj.user = user - }) - }) - next() - }) - }, - - ensureProfile: function(req, res, next){ - var username = req.params.username - if (username) { - User.findOne({ username: username }, function (err, user) { - if (user) { - res.locals.profile = req.method == "GET" ? staff.helpers.user(user) : user - } - else { - res.locals.profile = null - } - next() - }) - } - else { - res.locals.profile = null - next() - } - }, - - ensureSingleMedia: function(req, res, next){ - var id = req.params.id - if (id) { - Media.findOne({ _id: id }, function (err, media) { - if (media) { - res.locals.media = req.method == "GET" ? staff.helpers.media(media) : media - } - else { - res.locals.media = null - } - next() - }) - } - else { - res.locals.media = null - next() - } - }, - - ensureUsersCount: function(req, res, next){ - User.count({}, function(err, count){ - res.locals.userCount = count || 0 - next() - }) - }, - - ensureProjectsCount: function(req, res, next){ - Project.count({}, function(err, count){ - res.locals.projectCount = count || 0 - next() - }) - }, - - ensureLayoutsCount: function(req, res, next){ - Layout.count({}, function(err, count){ - res.locals.layoutCount = count || 0 - next() - }) - }, - - ensureMediaCount: function(req, res, next){ - Media.count({}, function(err, count){ - res.locals.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjectCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.projectCount = count || 0 - next() - }) - }, - - ensureProfileMediaCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Media.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjects: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.find({ user_id: res.locals.profile._id }, staff.fields.project, function(err, projects){ - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureProfileMedia: function(req, res, next){ - if (! res.locals.profile) { return next() } - req.criteria = { user_id: res.locals.profile._id } - staff.middleware.ensureMedia(req, res, next) - }, - - ensureProject: function(req, res, next){ - res.locals.project = req.project - next() - }, - - ensureProjectUser: function(req, res, next){ - if (! res.locals.project) { return next() } - User.findOne({ _id: res.locals.project.user_id }, staff.fields.user, function(err, user){ - res.locals.projectUser = staff.helpers.user(user) || staff.defaults.user - next() - }) - }, - - ensureProjectCollaborators: function(req, res, next){ - if (! res.locals.project) { - res.locals.collaborators = [] - return next() - } - Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ - res.locals.collaborators = collaborators || [] - next() - }) - }, - - ensureLayout: function(req, res, next){ - res.locals.layout = req.layout - next() - }, - ensureLayoutUser: function(req, res, next){ - if (! res.locals.layout) { return next() } - User.findOne({ _id: res.locals.layout.user_id }, staff.fields.user, function(err, user){ - res.locals.layoutUser = staff.helpers.user(user) || staff.defaults.user - next() - }) - }, - - }, - - helpers: { - user: function(user){ - var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) - user = user.toObject() - user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() - user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") - user.created_ip = util.num2ip( user.created_ip ) - user.last_ip = util.num2ip( user.last_ip ) - return user - }, - - project: function(project){ - project = project.toObject() - project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") - project.user = {} - return project - }, - - layout: function(layout){ - layout = layout.toObject() - layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") - layout.user = {} - return layout - }, - - media: function(media){ - media = media.toObject() - media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") - media.user = {} - media.shortUrl = media.url.replace(/^http.:\/\//,"") - return media - }, - - plan: function(plan){ - plan = plan.toObject() - plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") - plan.user = {} - return plan - }, - - subscription: function(subscription){ - subscription = subscription.toObject() - subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a") - subscription.user = {} - return subscription - }, - }, - - route: function(app){ - app.get('/staff', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureRecentUsers, - staff.middleware.ensureUsersCount, - staff.middleware.ensureProjectsCount, - staff.middleware.ensureMediaCount, - - staff.index - ); - - // - // users - - app.get('/staff/users', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureUsersCount, - staff.middleware.ensureUsers, - - staff.users.index - ); - app.get('/staff/users/:username', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileProjectCount, - staff.middleware.ensureProfileMediaCount, - staff.middleware.ensureProfileProjects, - - staff.users.show - ); - app.get('/staff/users/:username/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileMedia, - staff.middleware.ensureProfileMediaCount, - - staff.users.media - ); - app.put('/staff/users/:username/bless', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - - staff.users.bless - ); - - if (app.get('env') === 'development') { - app.get('/staff/authorize', - middleware.ensureAuthenticated, - staff.users.blessSelf - ); - } - - // - // projects - - app.get('/staff/projects', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProjectsCount, - - staff.middleware.ensureProjects, - staff.middleware.ensureProjectsUsers, - - staff.projects.index - ); - app.get('/staff/projects/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - staff.middleware.ensureProjectUser, - staff.middleware.ensureProjectCollaborators, - - staff.projects.show - ); - app.put('/staff/projects/:slug/feature', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - - staff.projects.feature - ); - - // - // layouts - - app.get('/staff/layouts', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureLayoutsCount, - - staff.middleware.ensureLayouts, - staff.middleware.ensureLayoutsUsers, - - staff.layouts.index - ); - app.get('/staff/layouts/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureLayout, - staff.middleware.ensureLayout, - staff.middleware.ensureLayoutUser, - - staff.layouts.show - ); - app.put('/staff/layouts/:slug/stock', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureLayout, - staff.middleware.ensureLayout, - - staff.layouts.make_stock - ); - - // - // media - - app.get('/staff/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureMediaCount, - - staff.middleware.ensureMedia, - staff.middleware.ensureMediaUsers, - - staff.media.index - ); - app.get('/staff/media/:id', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSingleMedia, - staff.middleware.ensureMediaUser, - - staff.media.show - ); - - // - // plans - - app.get('/staff/plans', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlans, - - staff.plans.index - ); - app.get('/staff/plans/new', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.plans.new - ); - app.post('/staff/plans/new', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.plans.create - ); - app.get('/staff/plans/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlan, - - staff.plans.edit - ); - app.post('/staff/plans/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlan, - - staff.plans.update - ); - - // - // subscriptions - app.get('/staff/subscriptions', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSubscriptions, - staff.middleware.ensureSubscriptionsUsers, - - staff.subscriptions.index - ); - app.get('/staff/subscriptions/:id', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSubscription, - staff.middleware.ensureSubscriptionUser, - - staff.subscriptions.show - ); - }, - - paginate: function(req, res){ - var info = res.locals.pagination - info.query = "sort=" + info.sort + "&limit=" + info.limit - info.first_page = 0 - info.last_page = Math.max(0, info.max - info.limit) - info.sortOptions = info.sortOptions - if (info.offset > 0) { - info.prev_page = Math.max(0, info.offset - info.limit) - } - else { - info.prev_page = -1 - } - if (info.count == info.limit && info.offset + info.limit < info.max) { - info.next_page = info.offset + info.limit - } - else { - info.next_page = -1 - } - }, - - index: function(req, res){ - res.render('staff/index') - }, - - // /staff/users/ - // /staff/users/:username - users: { - index: function(req, res){ - res.locals.pagination.count = res.locals.users.length - res.locals.pagination.max = res.locals.userCount - staff.paginate(req, res) - res.render('staff/users/index') - }, - show: function(req, res){ - if (res.locals.profile) { - res.render('staff/users/show', { - profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) - }) - } - else { - res.render('staff/users/show_404') - } - }, - media: function(req, res){ - if (res.locals.profile) { - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.profile.mediaCount - staff.paginate(req, res) - res.render('staff/users/media') - } - else { - res.render('staff/users/show_404') - } - }, - blessSelf: function(req, res){ - req.user.isStaff = true - req.user.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - bless: function(req, res){ - res.locals.profile.isStaff = req.body.state == "true" - res.locals.profile.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - }, - - // /staff/projects/ - // /staff/projects/:name - projects: { - index: function(req, res){ - res.locals.pagination.count = res.locals.projects.length - res.locals.pagination.max = res.locals.projectCount - staff.paginate(req, res) - res.render('staff/projects/index') - }, - show: function(req, res){ - if (res.locals.project) { - res.render('staff/projects/show', { - projectJSON: util.escape( JSON.stringify( res.locals.project ) ), - projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), - collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), - }) - } - else { - res.render('staff/projects/show_404') - } - }, - feature: function(req, res){ - res.locals.project.featured = req.body.state == "true" - res.locals.project.save(function(err, project){ - res.json({ state: project.featured }) - }) - }, - }, - - // /staff/layouts/ - // /staff/layouts/:name - layouts: { - index: function(req, res){ - res.locals.pagination.count = res.locals.layouts.length - res.locals.pagination.max = res.locals.layoutCount - staff.paginate(req, res) - res.render('staff/layouts/index') - }, - show: function(req, res){ - if (res.locals.layout) { - res.render('staff/layouts/show', { - }) - } - else { - res.render('staff/layouts/show_404') - } - }, - make_stock: function(req, res){ - res.locals.layout.is_stock = req.body.state == "true" - res.locals.layout.save(function(err, layout){ - res.json({ state: layout.is_stock }) - }) - }, - }, - - - media: { - index: function(req, res){ - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.mediaCount - staff.paginate(req, res) - res.render('staff/media/index') - }, - show: function(req, res){ - if (res.locals.media) { - res.render('staff/media/show', { - mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), - mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), - }) - } - else { - res.render('staff/media/show_404') - } - }, - }, - - plans: { - index: function(req, res){ - res.locals.fields = staff.fields.plans.split(" ") - res.locals.permissions = staff.fields.plans_permissions.split(" ") - res.render('staff/plans/index') - }, - new: function(req, res){ - res.locals.plan = new Plan () - res.render('staff/plans/new') - }, - edit: function(req, res){ - res.locals.plan = req.plan - res.render('staff/plans/edit') - }, - create: function(req, res){ - var plan = new Plan () - var fields = staff.fields.plans.split(" ") - var permissions = staff.fields.plans_permissions.split(" ") - - var data = util.cleanQuery(req.body) - data.name = util.sanitize(data.name) - data.slug = util.sanitize(data.slug.toLowerCase()) - - data.permissions = {} - permissions.forEach(function(field){ - data.permissions[field] = data["permissions_" + field].length == 2 - }) - - new Plan (data).save(function(err, doc){ - if (err || ! doc) { return res.json({ error: err }) } - middleware.updatePlans() - res.redirect("/staff/plans/") - }) - }, - update: function(req, res){ - var fields = staff.fields.plans.split(" ") - var permissions = staff.fields.plans_permissions.split(" ") - - var data = util.cleanQuery(req.body) - data.name = util.sanitize(data.name) - data.slug = util.sanitize(data.slug.toLowerCase()) - - _.extend(req.plan, data) - permissions.forEach(function(field){ - req.plan.permissions[field] = data["permissions_" + field].length == 2 - }) - - req.plan.save(function(err, doc){ - if (err || ! doc) { return res.json({ error: err }) } - middleware.updatePlans() - res.redirect("/staff/plans/") - }) - }, - }, - - subscriptions: { - index: function(req, res){ - res.locals.pagination.count = res.locals.subscriptions.length - res.locals.pagination.max = res.locals.subscriptionCount - staff.paginate(req, res) - res.render('staff/subscriptions/index') - }, - show: function(req, res){ - res.render('staff/subscriptions/show') - }, - }, - -} diff --git a/server/lib/views/staff/defaults.js b/server/lib/views/staff/defaults.js new file mode 100644 index 0000000..4d86c41 --- /dev/null +++ b/server/lib/views/staff/defaults.js @@ -0,0 +1,6 @@ +module.exports = { + user: { + _id: "", username: "", displayName: "", + created_at: "", updated_at: "", created_ip: "", last_ip: "", + }, +} diff --git a/server/lib/views/staff/fields.js b/server/lib/views/staff/fields.js new file mode 100644 index 0000000..57eea7e --- /dev/null +++ b/server/lib/views/staff/fields.js @@ -0,0 +1,9 @@ +module.exports = { + user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", + project: "_id name slug user_id privacy layout_type created_at updated_at", + layout: "_id name slug user_id layout_type created_at updated_at", + plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", + plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", +} diff --git a/server/lib/views/staff/helpers.js b/server/lib/views/staff/helpers.js new file mode 100644 index 0000000..57383f4 --- /dev/null +++ b/server/lib/views/staff/helpers.js @@ -0,0 +1,52 @@ + +var util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + +module.exports = { + user: function(user){ + var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) + user = user.toObject() + user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() + user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") + user.created_ip = util.num2ip( user.created_ip ) + user.last_ip = util.num2ip( user.last_ip ) + return user + }, + + project: function(project){ + project = project.toObject() + project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") + project.user = {} + return project + }, + + layout: function(layout){ + layout = layout.toObject() + layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") + layout.user = {} + return layout + }, + + media: function(media){ + media = media.toObject() + media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") + media.user = {} + media.shortUrl = media.url.replace(/^http.?:\/\//,"") + return media + }, + + plan: function(plan){ + plan = plan.toObject() + plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") + plan.user = {} + return plan + }, + + subscription: function(subscription){ + subscription = subscription.toObject() + subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a") + subscription.user = {} + return subscription + }, +} diff --git a/server/lib/views/staff/index.js b/server/lib/views/staff/index.js new file mode 100644 index 0000000..6a56238 --- /dev/null +++ b/server/lib/views/staff/index.js @@ -0,0 +1,452 @@ +/* jshint node: true */ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + config = require('../../../../config'), + middleware = require('../../middleware'), + util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + + +var staff = module.exports = { + + fields: require('./fields'), + defaults: require('./defaults'), + middleware: require('./middleware'), + helpers: require('./helpers'), + + route: function(app){ + app.get('/staff', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureRecentUsers, + staff.middleware.ensureUsersCount, + staff.middleware.ensureProjectsCount, + staff.middleware.ensureMediaCount, + + staff.index + ); + + // + // users + + app.get('/staff/users', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureUsersCount, + staff.middleware.ensureUsers, + + staff.users.index + ); + app.get('/staff/users/:username', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileProjectCount, + staff.middleware.ensureProfileMediaCount, + staff.middleware.ensureProfileProjects, + + staff.users.show + ); + app.get('/staff/users/:username/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileMedia, + staff.middleware.ensureProfileMediaCount, + + staff.users.media + ); + app.put('/staff/users/:username/bless', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + + staff.users.bless + ); + + if (app.get('env') === 'development') { + app.get('/staff/authorize', + middleware.ensureAuthenticated, + staff.users.blessSelf + ); + } + + // + // projects + + app.get('/staff/projects', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProjectsCount, + + staff.middleware.ensureProjects, + staff.middleware.ensureProjectsUsers, + + staff.projects.index + ); + app.get('/staff/projects/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + staff.middleware.ensureProjectUser, + staff.middleware.ensureProjectCollaborators, + + staff.projects.show + ); + app.put('/staff/projects/:slug/feature', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + + staff.projects.feature + ); + + // + // layouts + + app.get('/staff/layouts', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureLayoutsCount, + + staff.middleware.ensureLayouts, + staff.middleware.ensureLayoutsUsers, + + staff.layouts.index + ); + app.get('/staff/layouts/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + staff.middleware.ensureLayoutUser, + + staff.layouts.show + ); + app.put('/staff/layouts/:slug/stock', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + + staff.layouts.make_stock + ); + + // + // media + + app.get('/staff/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureMediaCount, + + staff.middleware.ensureMedia, + staff.middleware.ensureMediaUsers, + + staff.media.index + ); + app.get('/staff/media/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSingleMedia, + staff.middleware.ensureMediaUser, + + staff.media.show + ); + + // + // plans + + app.get('/staff/plans', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlans, + + staff.plans.index + ); + app.get('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.new + ); + app.post('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.create + ); + app.get('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.edit + ); + app.post('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.update + ); + + // + // subscriptions + app.get('/staff/subscriptions', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscriptions, + staff.middleware.ensureSubscriptionsUsers, + + staff.subscriptions.index + ); + app.get('/staff/subscriptions/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscription, + staff.middleware.ensureSubscriptionUser, + + staff.subscriptions.show + ); + }, + + paginate: function(req, res){ + var info = res.locals.pagination + info.query = "sort=" + info.sort + "&limit=" + info.limit + info.first_page = 0 + info.last_page = Math.max(0, info.max - info.limit) + info.sortOptions = info.sortOptions + if (info.offset > 0) { + info.prev_page = Math.max(0, info.offset - info.limit) + } + else { + info.prev_page = -1 + } + if (info.count == info.limit && info.offset + info.limit < info.max) { + info.next_page = info.offset + info.limit + } + else { + info.next_page = -1 + } + }, + + index: function(req, res){ + res.render('staff/index') + }, + + // /staff/users/ + // /staff/users/:username + users: { + index: function(req, res){ + res.locals.pagination.count = res.locals.users.length + res.locals.pagination.max = res.locals.userCount + staff.paginate(req, res) + res.render('staff/users/index') + }, + show: function(req, res){ + if (res.locals.profile) { + res.render('staff/users/show', { + profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) + }) + } + else { + res.render('staff/users/show_404') + } + }, + media: function(req, res){ + if (res.locals.profile) { + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.profile.mediaCount + staff.paginate(req, res) + res.render('staff/users/media') + } + else { + res.render('staff/users/show_404') + } + }, + blessSelf: function(req, res){ + req.user.isStaff = true + req.user.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + bless: function(req, res){ + res.locals.profile.isStaff = req.body.state == "true" + res.locals.profile.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + }, + + // /staff/projects/ + // /staff/projects/:name + projects: { + index: function(req, res){ + res.locals.pagination.count = res.locals.projects.length + res.locals.pagination.max = res.locals.projectCount + staff.paginate(req, res) + res.render('staff/projects/index') + }, + show: function(req, res){ + if (res.locals.project) { + res.render('staff/projects/show', { + projectJSON: util.escape( JSON.stringify( res.locals.project ) ), + projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), + collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), + }) + } + else { + res.render('staff/projects/show_404') + } + }, + feature: function(req, res){ + res.locals.project.featured = req.body.state == "true" + res.locals.project.save(function(err, project){ + res.json({ state: project.featured }) + }) + }, + }, + + // /staff/layouts/ + // /staff/layouts/:name + layouts: { + index: function(req, res){ + res.locals.pagination.count = res.locals.layouts.length + res.locals.pagination.max = res.locals.layoutCount + staff.paginate(req, res) + res.render('staff/layouts/index') + }, + show: function(req, res){ + if (res.locals.layout) { + res.render('staff/layouts/show', { + }) + } + else { + res.render('staff/layouts/show_404') + } + }, + make_stock: function(req, res){ + res.locals.layout.is_stock = req.body.state == "true" + res.locals.layout.save(function(err, layout){ + res.json({ state: layout.is_stock }) + }) + }, + }, + + + media: { + index: function(req, res){ + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.mediaCount + staff.paginate(req, res) + res.render('staff/media/index') + }, + show: function(req, res){ + if (res.locals.media) { + res.render('staff/media/show', { + mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), + mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), + }) + } + else { + res.render('staff/media/show_404') + } + }, + }, + + plans: { + index: function(req, res){ + res.locals.fields = staff.fields.plans.split(" ") + res.locals.permissions = staff.fields.plans_permissions.split(" ") + res.render('staff/plans/index') + }, + new: function(req, res){ + res.locals.plan = new Plan () + res.render('staff/plans/new') + }, + edit: function(req, res){ + res.locals.plan = req.plan + res.render('staff/plans/edit') + }, + create: function(req, res){ + var plan = new Plan () + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + data.permissions = {} + permissions.forEach(function(field){ + data.permissions[field] = data["permissions_" + field].length == 2 + }) + + new Plan (data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + update: function(req, res){ + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + _.extend(req.plan, data) + permissions.forEach(function(field){ + req.plan.permissions[field] = data["permissions_" + field].length == 2 + }) + + req.plan.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + }, + + subscriptions: { + index: function(req, res){ + res.locals.pagination.count = res.locals.subscriptions.length + res.locals.pagination.max = res.locals.subscriptionCount + staff.paginate(req, res) + res.render('staff/subscriptions/index') + }, + show: function(req, res){ + res.render('staff/subscriptions/show') + }, + }, + +} diff --git a/server/lib/views/staff/middleware.js b/server/lib/views/staff/middleware.js new file mode 100644 index 0000000..5c74d0b --- /dev/null +++ b/server/lib/views/staff/middleware.js @@ -0,0 +1,421 @@ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + util = require('../../util'), + fields = require('./fields'), + helpers = require('./helpers'), + defaults = require('./defaults'), + _ = require('lodash'), + moment = require('moment'); + + +var middleware = module.exports = { + + ensureUsers: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var initial = util.sanitize(req.query.initial) + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "last_seen", "username"] + switch (req.query.sort) { + case 'date': + sort = {'created_at': -1} + break + case 'last_seen': + sort = {'last_seen': -1} + break + case 'username': + default: + sort = {'username': 1} + paginationInfo.sort = "username" + break + } + if (initial) { + if (initial == "?") { + criteria.username = new RegExp('^[$a-zA-Z]', "i") + } + else { + criteria.username = new RegExp('^' + initial, "i") + } + } + User.find(criteria) + .select(fields.user) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, users) { + res.locals.users = users.map(helpers.user) + if (! res.locals.users.length) { + if (initial) { + res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" + } + else { + res.locals.opt.error = "No users found" + } + } + next() + }) + }, + + ensureRecentUsers: function(req, res, next){ + var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } + middleware.ensureUsers(dreq, res, next) + }, + + ensureProjects: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Project.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, projects) { + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureLayouts: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Layout.find(criteria) + .select(fields.layout) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, layouts) { + res.locals.layouts = layouts.map(helpers.layout) + next() + }) + }, + + ensureMedia: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date"] + switch (req.query.sort) { + default: + case 'date': + paginationInfo.sort = "date" + sort = {'created_at': -1} + break + } + Media.find(criteria) + // .select(fields.media) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, media) { + res.locals.media = media.map(helpers.media) + next() + }) + }, + + ensureSubscriptions: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + case 'created': + sort = {'created_at': -1} + break + default: + case 'date': + sort = {'updated_at': -1} + break + } + Subscription.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, subscriptions) { + res.locals.subscriptions = subscriptions.map(helpers.subscription) + next() + }) + }, + + ensurePlans: function(req, res, next){ + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + res.locals.plans = (plans || []).map(helpers.plan) + res.locals.plans.sort(function(a,b){ return a.monthly_price }) + next() + }) + }, + ensurePlan: function (req, res, next) { + if (req.params.slug) { + Plan.findOne({ slug: req.params.slug }, function(err, plan){ + if (err || ! plan) { + console.error(err) + res.redirect("/staff/plans/") + } + else { + req.plan = plan + next() + } + }) + } + else { + res.redirect("/staff/plans/") + } + }, + + ensureSubscription: function (req, res, next) { + if (req.params.id) { + Subscription.findOne({ _id: req.params.id }, function(err, subscription){ + if (err || ! subscription) { + console.error(err) + res.redirect("/staff/subscriptions/") + } + else { + req.subscription = subscription + next() + } + }) + } + else { + res.redirect("/staff/subscriptions/") + } + }, + + ensureRecentProjects: function(req, res, next){ + var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } + middleware.ensureProjects(dreq, res, next) + }, + + ensureProjectsUsers: function(req, res, next){ + if (! res.locals.projects || ! res.locals.projects.length) { return next() } + middleware.ensureObjectsUsers(res.locals.projects, next) + }, + + ensureLayoutsUsers: function(req, res, next){ + if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } + middleware.ensureObjectsUsers(res.locals.layouts, next) + }, + + ensureSubscriptionsUsers: function(req, res, next){ + if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } + middleware.ensureObjectsUsers(res.locals.subscriptions, next) + }, + + ensureMediaUsers: function(req, res, next){ + if (! res.locals.media || ! res.locals.media.length) { return next() } + middleware.ensureObjectsUsers(res.locals.media, next) + }, + + ensureSubscriptionUser: function(req, res, next){ + if (! res.locals.subscription) { return next() } + middleware.ensureObjectsUsers([ res.locals.subscription ], function(){ + next() + }) + }, + + ensureMediaUser: function(req, res, next){ + if (! res.locals.media) { return next() } + middleware.ensureObjectsUsers([ res.locals.media ], function(){ + res.locals.mediaUser = res.locals.media.User + next() + }) + }, + + ensureObjectsUsers: function(objects, next){ + if (! objects) { return next () } + var dedupe = {}, user_ids + objects.forEach(function(obj){ + dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] + dedupe[ obj.user_id ].push(obj) + }) + user_ids = _.keys(dedupe) + User.find({ _id: { $in: user_ids } }) + .select(fields.user) + .exec(function (err, users) { + if (! users) { return next () } + users.forEach(function(user){ + dedupe[user._id].forEach(function(obj){ + obj.user = user + }) + }) + next() + }) + }, + + ensureProfile: function(req, res, next){ + var username = req.params.username + if (username) { + User.findOne({ username: username }, function (err, user) { + if (user) { + res.locals.profile = req.method == "GET" ? helpers.user(user) : user + } + else { + res.locals.profile = null + } + next() + }) + } + else { + res.locals.profile = null + next() + } + }, + + ensureSingleMedia: function(req, res, next){ + var id = req.params.id + if (id) { + Media.findOne({ _id: id }, function (err, media) { + if (media) { + res.locals.media = req.method == "GET" ? helpers.media(media) : media + } + else { + res.locals.media = null + } + next() + }) + } + else { + res.locals.media = null + next() + } + }, + + ensureUsersCount: function(req, res, next){ + User.count({}, function(err, count){ + res.locals.userCount = count || 0 + next() + }) + }, + + ensureProjectsCount: function(req, res, next){ + Project.count({}, function(err, count){ + res.locals.projectCount = count || 0 + next() + }) + }, + + ensureLayoutsCount: function(req, res, next){ + Layout.count({}, function(err, count){ + res.locals.layoutCount = count || 0 + next() + }) + }, + + ensureMediaCount: function(req, res, next){ + Media.count({}, function(err, count){ + res.locals.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjectCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.projectCount = count || 0 + next() + }) + }, + + ensureProfileMediaCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Media.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjects: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.find({ user_id: res.locals.profile._id }, fields.project, function(err, projects){ + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureProfileMedia: function(req, res, next){ + if (! res.locals.profile) { return next() } + req.criteria = { user_id: res.locals.profile._id } + middleware.ensureMedia(req, res, next) + }, + + ensureProject: function(req, res, next){ + res.locals.project = req.project + next() + }, + + ensureProjectUser: function(req, res, next){ + if (! res.locals.project) { return next() } + User.findOne({ _id: res.locals.project.user_id }, fields.user, function(err, user){ + res.locals.projectUser = helpers.user(user) || defaults.user + next() + }) + }, + + ensureProjectCollaborators: function(req, res, next){ + if (! res.locals.project) { + res.locals.collaborators = [] + return next() + } + Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ + res.locals.collaborators = collaborators || [] + next() + }) + }, + + ensureLayout: function(req, res, next){ + res.locals.layout = req.layout + next() + }, + ensureLayoutUser: function(req, res, next){ + if (! res.locals.layout) { return next() } + User.findOne({ _id: res.locals.layout.user_id }, fields.user, function(err, user){ + res.locals.layoutUser = helpers.user(user) || defaults.user + next() + }) + }, + +} \ No newline at end of file diff --git a/views/staff/projects/index.ejs b/views/staff/projects/index.ejs index 1d309ce..e4ba469 100644 --- a/views/staff/projects/index.ejs +++ b/views/staff/projects/index.ejs @@ -7,7 +7,7 @@
    [[ include ../_pagination ]] -[[ include ../_layouts ]] +[[ include ../_projects ]] [[ include ../_pagination ]] [[ include ../_footer ]] -- cgit v1.2.3-70-g09d2