1
0
mirror of https://github.com/fazo96/homework.git synced 2025-01-10 12:14:22 +01:00
homework/client/client.coffee

294 lines
9.7 KiB
CoffeeScript
Raw Normal View History

# Homework - Client Side
2014-10-04 08:17:10 +02:00
version = "1.1.4"
2014-06-05 17:03:10 +02:00
# Utilities
tick = new Deps.Dependency()
Meteor.setInterval (-> tick.changed();), 15000
notes = new Meteor.Collection "notes"
userSub = Meteor.subscribe 'user'
2014-05-28 18:45:41 +02:00
getUser = -> Meteor.user()
2014-05-31 18:09:56 +02:00
deleteAccount = ->
Meteor.call 'deleteMe', (r) -> if r is yes then Router.go 'home'
2014-05-28 18:45:41 +02:00
amIValid = ->
return no unless getUser()
return yes for mail in getUser().emails when mail.verified is yes; no
2014-05-30 08:27:49 +02:00
2014-05-31 18:09:56 +02:00
# Common Helpers for the Templates
2014-09-30 09:22:09 +02:00
UI.registerHelper "version", -> version
UI.registerHelper "status", -> Meteor.status()
UI.registerHelper "loading", -> Meteor.loggingIn() or !Meteor.status().connected
2014-05-31 19:31:56 +02:00
UI.registerHelper "email", ->
if getUser() then return getUser().emails[0].address
2014-05-28 18:45:41 +02:00
UI.registerHelper "verified", -> amIValid()
2014-09-30 09:22:09 +02:00
Meteor.startup ->
console.log "Homework version "+version
console.log "This software is Free Software (MIT License)"
console.log "More information at http://github.com/fazo96/homework"
2014-05-30 10:33:32 +02:00
# Router
2014-05-31 18:09:56 +02:00
###
2014-06-01 11:47:27 +02:00
Important: 'home' dispatches the user to the correct landing page.
2014-05-31 18:09:56 +02:00
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
2014-06-01 11:47:27 +02:00
the server doesn't let the user if he doesn't have permission. It's still safe.
2014-05-31 18:09:56 +02:00
###
2014-05-30 10:33:32 +02:00
Router.configure
layoutTemplate: 'layout'
loadingTemplate: 'loading'
notFoundTemplate: '404'
action: ->
if Meteor.status().connected is no
@render 'reconnect'
else if Meteor.loggingIn()
@render 'loading'
else @render()
2014-09-24 10:59:52 +02:00
loggedInController = RouteController.extend
action: ->
if Meteor.status().connected is no
@render 'reconnect'
else if !@ready() or Meteor.loggingIn()
@render 'loading'
else @render()
2014-09-24 10:59:52 +02:00
onBeforeAction: ->
2014-10-01 08:42:06 +02:00
showError()
2014-09-24 10:59:52 +02:00
if not getUser() then Router.go 'home'
else if not amIValid() then Router.go 'verifyEmail'
2014-09-24 10:59:52 +02:00
guestController = RouteController.extend
action: ->
if Meteor.status().connected is no
@render 'reconnect'
else @render()
2014-09-24 10:59:52 +02:00
onBeforeAction: ->
2014-10-01 08:42:06 +02:00
showError()
2014-09-24 10:59:52 +02:00
if getUser()
if amIValid() is no then Router.go 'verifyEmail' else Router.go 'notes'
2014-09-24 10:59:52 +02:00
2014-05-30 10:33:32 +02:00
Router.map ->
@route 'home',
2014-05-31 19:31:56 +02:00
path: '/'
2014-06-05 17:03:10 +02:00
template: 'homepage'
2014-09-30 09:22:09 +02:00
action: -> @render 'homepage', to: 'outside'
2014-05-31 18:09:56 +02:00
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'
2014-09-24 10:59:52 +02:00
@route 'login', controller: guestController
@route 'register', controller: guestController
@route 'account', controller: loggedInController
2014-05-30 10:33:32 +02:00
@route 'notes',
2014-06-03 15:40:59 +02:00
path: '/notes/:_id?'
2014-09-24 10:59:52 +02:00
waitOn: -> Meteor.subscribe 'my-notes'
2014-06-03 15:40:59 +02:00
data: -> notes.findOne _id: @params._id
2014-09-24 10:59:52 +02:00
controller: loggedInController
2014-06-03 15:40:59 +02:00
@route 'archive',
path: '/archive/:_id?'
2014-09-24 10:59:52 +02:00
waitOn: -> @notes = Meteor.subscribe 'archive'
onStop: -> @notes.stop()
controller: loggedInController
2014-05-30 10:33:32 +02:00
@route 'verifyEmail',
2014-05-30 11:40:15 +02:00
path: '/verify/:token?'
2014-05-30 10:33:32 +02:00
template: 'verifyEmail'
action: ->
if Meteor.status().connected is no
@render 'reconnect'
else @render()
2014-05-30 10:33:32 +02:00
onBeforeAction: ->
if getUser()
if amIValid() then Router.go 'home'
else Router.go 'home'
2014-09-24 10:59:52 +02:00
# Automatic verification
2014-05-31 19:31:56 +02:00
if @params.token? and @params.token isnt ""
2014-09-24 10:59:52 +02:00
@render 'loading'
2014-05-30 11:40:15 +02:00
Accounts.verifyEmail @params.token, (err) ->
2014-05-31 19:31:56 +02:00
if err
2014-09-24 10:59:52 +02:00
errCallback err; Router.go 'verifyEmail', token: @params.token
else
showErr type:'success', msg:'Verification complete'
Router.go 'home'
@route '404', path: '*'
2014-05-30 11:40:15 +02:00
2014-05-31 18:09:56 +02:00
# Client Templates
2014-06-05 17:03:10 +02:00
# Some utility callbacks
2014-06-01 11:47:27 +02:00
logoutCallback = (err) ->
if err then errCallback err
else Router.go 'home'; Meteor.unsubscribe "my-notes"
2014-05-31 18:09:56 +02:00
errCallback = (err) ->
if err.reason
showError msg: err.reason
else showErrror msg: err
2014-05-30 10:33:32 +02:00
Template.reconnect.time = ->
tick.depend()
if Meteor.status().retryTime
'(retrying '+moment(Meteor.status().retryTime).fromNow()+')'
2014-06-05 17:03:10 +02:00
# 3 Buttons navigation Menu
2014-05-31 18:09:56 +02:00
Template.menu.events
'click .go-home': -> Router.go 'home'
'click .go-account': -> Router.go 'account'
'click .go-archive': -> Router.go 'archive'
2014-05-30 08:27:49 +02:00
2014-06-05 17:03:10 +02:00
# Account Page
Template.account.dateformat = -> getUser().dateformat
2014-05-30 10:33:32 +02:00
Template.account.events
'click #reset-settings': (e,t) ->
t.find('#set-date-format').value = "MM/DD/YYYY"
'click #save-settings': (e,t) ->
Meteor.users.update getUser()._id,
$set: dateformat: t.find('#set-date-format').value
showError msg: 'Settings saved', type: 'success'
'click #btn-logout': -> Meteor.logout logoutCallback
2014-05-31 19:31:56 +02:00
'click #btn-delete-me': -> deleteAccount()
2014-06-05 17:03:10 +02:00
# Notes list
2014-06-01 11:47:27 +02:00
Template.notelist.active = ->
return no unless Router.current() and Router.current().data()
return @_id is Router.current().data()._id
2014-06-03 15:40:59 +02:00
Template.notelist.empty = -> Template.notelist.notelist().length is 0
2014-06-01 11:47:27 +02:00
Template.notelist.getDate = ->
return unless @date
tick.depend()
#dif = moment(@date, getUser().dateformat).diff(moment(), 'days')
dif = moment.unix(@date).diff(moment(), 'days')
color = "primary"
color = "info" if dif < 7
color = "warning" if dif is 1
color = "danger" if dif < 1
msg: moment.unix(@date).fromNow(), color: color
Template.notelist.notelist = ->
2014-06-03 15:40:59 +02:00
notes.find({ archived: no },{ sort: date: 1}).fetch()
2014-05-30 10:33:32 +02:00
Template.notelist.events
2014-06-03 15:40:59 +02:00
'click .close-note': -> notes.update @_id, $set: archived: yes
2014-09-23 10:32:08 +02:00
'click .edit-note': -> Router.go 'notes'
'keypress #newNote': (e,template) ->
2014-05-28 10:19:06 +02:00
if e.keyCode is 13 and template.find('#newNote').value isnt ""
notes.insert
title: template.find('#newNote').value
2014-06-01 11:47:27 +02:00
content: "", date: no, archived: no, userId: Meteor.userId()
template.find('#newNote').value = ""
2014-06-03 15:40:59 +02:00
# Archive
Template.archivedlist.empty = -> Template.archivedlist.archived().length is 0
Template.archivedlist.getDate = Template.notelist.getDate
2014-06-03 15:40:59 +02:00
Template.archivedlist.archived = ->
notes.find({ archived: yes },{ sort: date: 1}).fetch()
Template.archivedlist.events =
'click .close-note': -> notes.remove @_id
'click .note': -> notes.update @_id, $set: archived: no
'click .clear': ->
notes.remove item._id for item in Template.archivedlist.archived()
# Note Editor
2014-06-01 11:47:27 +02:00
Template.editor.note = -> Router.current().data()
Template.editor.dateformat = -> getUser().dateformat
Template.editor.formattedDate = ->
return unless @date
moment.unix(@date).format(getUser().dateformat)
saveCurrentNote = (t,e) ->
2014-05-31 18:09:56 +02:00
if e and e.keyCode isnt 13 then return
dat = no
if t.find('.date').value isnt ""
dat = moment(t.find('.date').value,getUser().dateformat)
if dat.isValid()
dat = dat.unix()
else
dat = no; showError msg: 'Invalid date'
t.find('.date').value = ""
2014-05-30 10:33:32 +02:00
notes.update Router.current().data()._id,
$set:
2014-05-28 14:57:43 +02:00
title: t.find('.editor-title').value
content: t.find('.area').value
date: dat
Template.editor.events
2014-06-05 17:03:10 +02:00
'click .close-editor': -> Router.go 'notes'
'click .save-editor': (e,t) -> saveCurrentNote t
'click .set-date': (e,t) ->
t.find('.date').value = moment().add(1,'days').format(getUser().dateformat)
'keypress .title': (e,t) -> saveCurrentNote t, e
2014-06-05 17:03:10 +02:00
# Notifications (not used yet)
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
2014-05-28 10:19:06 +02:00
Template.notifications.events
'click .close-notification': (e,template) ->
alerts.splice alerts.indexOf(this), 1
alertDep.changed()
2014-05-28 10:19:06 +02:00
# "Error" visualization template
errorDep = new Deps.Dependency; shownError = undefined
showError = (err) ->
2014-10-01 08:42:06 +02:00
if err?
shownError = err; shownError.type = err.type or "danger"
else shownError = undefined
errorDep.changed()
Template.error.error = -> errorDep.depend(); shownError
2014-10-01 08:42:06 +02:00
Template.error.events 'click .close': -> showError()
2014-06-05 17:03:10 +02:00
# Verify Email page
2014-09-24 10:59:52 +02:00
Template.verifyEmail.token = -> Router.current().params.token
2014-05-28 18:45:41 +02:00
Template.verifyEmail.events
'click #btn-verify': (e,template) ->
2014-05-31 19:31:56 +02:00
t = template.find('#token-field').value; t = t.split("/")
t = t[t.length-1] # Remove all the part before the last "/"
Accounts.verifyEmail t, (err) ->
2014-05-30 10:33:32 +02:00
if err then errCallback err else Router.go 'notes'
2014-05-28 18:45:41 +02:00
'click #btn-resend': ->
2014-05-30 10:33:32 +02:00
Meteor.call 'resendConfirmEmail', (err) ->
if err
errCallback err
else showError { type:"success", msg: "Confirmation email sent" }
2014-05-31 18:09:56 +02:00
'click #btn-delete': -> deleteAccount()
2014-05-30 10:33:32 +02:00
'click #btn-logout': -> Meteor.logout logoutCallback
2014-05-28 18:45:41 +02:00
2014-05-31 18:09:56 +02:00
# 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) ->
2014-05-31 19:31:56 +02:00
if err then errCallback err else Router.go 'notes'
2014-05-31 18:09:56 +02:00
Template.login.events
'keypress .login': (e,template) -> loginRequest e,template
'click #login-btn': (e,template) -> loginRequest null,template
2014-05-28 18:45:41 +02:00
2014-06-05 17:03:10 +02:00
# New Account page
2014-05-31 18:09:56 +02:00
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