# Homework - Client Side # Variables and utility stuff notes = new Meteor.Collection "notes" getUser = -> Meteor.user() deleteAccount = -> Meteor.call 'deleteMe', (r) -> if r is yes then Router.go 'home' amIValid = -> return no unless getUser() return yes for mail in getUser().emails when mail.verified is yes; no daysUntil = (time) -> date = new Date time; now = new Date() #console.log date+" "+now now.setHours(0); now.setMinutes(0); now.setSeconds(0) (Math.floor ((date.getTime() - now.getTime()) / 1000 / 60 / 60) + 1) / 24 # Common Helpers for the Templates UI.registerHelper "loggingIn", -> Meteor.loggingIn() UI.registerHelper "email", -> if getUser() then return getUser().emails[0].address UI.registerHelper "verified", -> amIValid() # Router ### Important: 'home' dispatches the user to the correct landing page. Routes are client side, but even if by hacking the client you can access pages without being logged in, it's impossible to inteact with data because the server doesn't let the user if he doesn't have permission. It's still safe. ### Router.configure layoutTemplate: 'layout' loadingTemplate: 'loading' notFoundTemplate: '404' Router.map -> @route 'home', path: '/' action: -> @render 'homepage', to: 'outside' onBeforeAction: -> # Dispatch user to the right landing page based on his account status if getUser() if amIValid() is yes then Router.go 'notes' else Router.go 'verifyEmail' @route 'login', onBeforeAction: -> Router.go 'home' if getUser() @route 'register', onBeforeAction: -> Router.go 'home' if getUser() @route 'account', onBeforeAction: -> if not getUser() then Router.go 'home' @route 'notes', waitOn: -> Meteor.subscribe "my-notes" onBeforeAction: -> if not getUser() then Router.go 'home' @route 'note', path: '/note/:_id' waitOn: -> Meteor.subscribe "my-notes" data: -> notes.findOne _id: @params._id onBeforeAction: -> if not @data()? then Router.go 'home' @route 'verifyEmail', path: '/verify/:token?' template: 'verifyEmail' onBeforeAction: -> if @params.token? and @params.token isnt "" Accounts.verifyEmail @params.token, (err) -> if err errCallback err; Router.go 'verifyEmail' else Router.go 'home' @route 'homepage', action: -> @render '404' @route '404', path: '*' # You can't set a callback for when the user logs in using a cookie so... # Cheap ass work around for routing the user after he logs in with a token Deps.autorun -> t = Router.current(); return unless t and t.lookupTemplate if getUser() and t.lookupTemplate() is 'login' then Router.go 'home' # Client Templates # Some utilities logoutCallback = (err) -> if err then errCallback err else Router.go 'home'; Meteor.unsubscribe "my-notes" errCallback = (err) -> if err.reason showError msg: err.reason else showErrror msg: err # Menu Template.menu.events 'click .go-home': -> Router.go 'home' 'click .go-account': -> Router.go 'account' 'click .go-archive': -> Router.go 'archive' # User Interface Template.account.events 'click #btn-logout': (e,template) -> Meteor.logout logoutCallback 'click #btn-delete-me': -> deleteAccount() # Notes template Template.notelist.active = -> return no unless Router.current() and Router.current().data() return @_id is Router.current().data()._id Template.notelist.empty = -> notes.find().count() is 0 Template.notelist.getDate = -> return unless @date; diff = daysUntil @date if diff <= 0 then return msg:"You missed it!", color: "danger" if diff is 1 then return msg:"Today", color: "warning" if diff is 2 then return msg:"Tomorrow", color: "info" #if new Date(@date).getMonth() > Date.now().getMonth() #return msg:"Next Month", color:"success" unless diff < 7 msg: "due in "+diff+" days", color: "primary" #day = new Date(@date).toLocaleString().split(' ')[0] Template.notelist.notes = -> d = notes.find({},{ sort: date: 1}).fetch() Template.notelist.events 'click .close-note': -> notes.remove @_id 'keypress #newNote': (e,template) -> if e.keyCode is 13 and template.find('#newNote').value isnt "" notes.insert title: template.find('#newNote').value content: "", date: no, archived: no, userId: Meteor.userId() template.find('#newNote').value = "" # Note Editor Template.editor.note = -> Router.current().data() Template.editor.rendered = -> $('.date').datepicker weekStart: 1 startDate: "today" todayBtn: "linked" saveCurrentNote = (t,e) -> if e and e.keyCode isnt 13 then return notes.update Router.current().data()._id, $set: title: t.find('.editor-title').value content: t.find('.area').value date: t.find('.date').value Template.editor.events 'click .close-editor': -> Router.go 'notes' 'click .save-editor': (e,t) -> saveCurrentNote t 'keypress .title': (e,t) -> saveCurrentNote t, e # Notifications alerts = [] alertDep = new Deps.Dependency # Show a notification notify = (data) -> alerts.push title: data.title msg: data.msg type: data.type or "danger" alertDep.changed() # Clear all notifications clearNotifications = -> alerts.clear(); alertDep.changed() # Get all the notifications Template.notifications.notification = -> alertDep.depend(); alerts Template.notifications.events 'click .close-notification': (e,template) -> alerts.splice alerts.indexOf(this), 1 alertDep.changed() # "Error" visualization template errorDep = new Deps.Dependency; shownError = undefined showError = (err) -> shownError = err; shownError.type = err.type or "danger" errorDep.changed() clearError = -> shownError = undefined; errorDep.changed() Template.error.error = -> errorDep.depend(); shownError Template.error.events 'click .close': -> clearError() # Verify Email Template.verifyEmail.events 'click #btn-verify': (e,template) -> t = template.find('#token-field').value; t = t.split("/") t = t[t.length-1] # Remove all the part before the last "/" console.log "Email ver. using token: "+template.find('#token-field').value Accounts.verifyEmail t, (err) -> if err then errCallback err else Router.go 'notes' 'click #btn-resend': -> Meteor.call 'resendConfirmEmail', (err) -> if err errCallback err else showError { type:"success", msg: "Confirmation email sent" } 'click #btn-delete': -> deleteAccount() 'click #btn-logout': -> Meteor.logout logoutCallback # Login loginRequest = (e,template) -> if e and e.keyCode isnt 13 then return mail = template.find('#l-mail').value; pass = template.find('#l-pass').value Meteor.loginWithPassword mail, pass, (err) -> if err then errCallback err else Router.go 'notes' Template.login.events 'keypress .login': (e,template) -> loginRequest e,template 'click #login-btn': (e,template) -> loginRequest null,template # Register registerRequest = (e,template) -> if e and e.keyCode isnt 13 then return mail = template.find('#r-mail').value; pass = template.find('#r-pass').value pass2 = template.find('#r-pass-2').value if not mail showError msg: "Please enter an Email" else if not pass showError msg: "Please enter a password" else if pass.length < 8 showError msg: "Password too short" else if pass2 isnt pass showError msg: "The passwords don't match" else # Sending actual registration request try Accounts.createUser { email: mail, password: pass }, (err) -> if err then errCallback err else Router.go 'confirmEmail' catch err showError msg: err Template.register.events 'click #register-btn': (e,t) -> registerRequest null,t 'keypress .register': (e,t) -> registerRequest e,t