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

337 lines
11 KiB
CoffeeScript
Raw Permalink Normal View History

# Homework - Client Side
version = "1.3"
2014-06-05 17:03:10 +02:00
# Utilities
2014-11-12 17:27:20 +01:00
tick = new Tracker.Dependency()
Meteor.setInterval (-> tick.changed();), 15000
2014-11-15 10:22:48 +01:00
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 = ->
2014-10-09 16:46:23 +02:00
swal {
title: 'Are you sure?'
text: 'Do you want to permanently delete all your data?'
type: 'warning'
showCancelButton: yes
confirmButtonColor: "#DD6B55"
confirmButtonText: "Yes!"
}, -> 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()
2014-10-09 16:46:23 +02:00
return yes if getUser().username
2014-05-28 18:45:41 +02:00
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
UI.registerHelper "APIAvailable", -> Meteor.settings.public?.enableAPI?
UI.registerHelper "facebookAvailable", ->
Accounts.loginServicesConfigured() and ServiceConfiguration.configurations.find(service: "facebook").count() > 0
UI.registerHelper "twitterAvailable", ->
Accounts.loginServicesConfigured() and ServiceConfiguration.configurations.find(service: "twitter").count() > 0
2014-05-31 19:31:56 +02:00
UI.registerHelper "email", ->
2014-10-09 16:46:23 +02:00
if getUser()
if getUser().username then return getUser().username
else 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: ->
2015-03-02 16:30:47 +01:00
if not getUser() then @redirect 'home'
else if not amIValid() then @redirect 'verifyEmail'
@next()
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: ->
if getUser()
2015-03-02 16:58:13 +01:00
if amIValid() is no then @redirect 'verifyEmail' else @redirect 'notes'
@next()
2014-11-15 10:22:48 +01:00
# Page Routing
2014-11-12 17:27:20 +01:00
Router.route '/',
name: 'home'
template: 'homepage'
2015-03-02 16:30:47 +01:00
action: ->
@render 'homepage', to: 'outside'
# Iron Router Workaround for a bug where content from previous renderings carries over if not overwritten
@render 'nothing'
2014-11-12 17:27:20 +01:00
onBeforeAction: ->
# Dispatch user to the right landing page based on his account status
if getUser()
2015-03-02 16:58:13 +01:00
if amIValid() is yes then @redirect 'notes' else @redirect 'verifyEmail'
2014-11-12 17:27:20 +01:00
@next()
Router.route '/login', controller: guestController
Router.route '/register', controller: guestController
Router.route '/account', controller: loggedInController
Router.route '/notes/:_id?',
name: 'notes'
2014-11-15 10:22:48 +01:00
waitOn: -> Meteor.subscribe 'notes', no
2014-11-12 17:27:20 +01:00
data: -> notes.findOne _id: @params._id
controller: loggedInController
Router.route '/verify/:token?',
name: 'verifyEmail'
template: 'verifyEmail'
action: ->
if Meteor.status().connected is no
@render 'reconnect'
2015-03-02 16:58:13 +01:00
else @render(); @render 'nothing', to: 'outside'
2014-11-12 17:27:20 +01:00
onBeforeAction: ->
if getUser()
2014-11-15 10:22:48 +01:00
if amIValid()
2015-03-02 16:30:47 +01:00
@redirect 'home'
@next()
2014-11-15 10:22:48 +01:00
else if @params.token? and @params.token isnt ""
# Automatic verification
@render 'loading'
Accounts.verifyEmail @params.token, (err) =>
if err
errCallback err; Router.go 'verifyEmail', token: @params.token
else
showErr type:'success', msg:'Verification complete'
Router.go 'home'
@next()
2015-03-02 16:58:13 +01:00
@next()
2014-11-15 10:22:48 +01:00
else
2015-03-02 16:30:47 +01:00
@redirect 'home'
@next()
2014-11-15 10:22:48 +01:00
Router.route '/archive/:_id?',
name: 'archive'
waitOn: -> @notes = Meteor.subscribe 'notes', yes
onStop: -> @notes.stop()
controller: loggedInController
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) ->
2014-10-09 16:46:23 +02:00
if err then errCallback err else Router.go 'home'
2014-05-31 18:09:56 +02:00
errCallback = (err) ->
if err.reason
showError msg: err.reason
else showError msg: err
loginCallback = (e) ->
if e? then errCallback e
else
Router.go 'notes'
swal 'Ok', 'Logged In', 'success'
2014-05-30 10:33:32 +02:00
2014-10-09 16:46:23 +02:00
Template.homepage.events
'click #facebook': -> Meteor.loginWithFacebook loginCallback
'click #twitter': -> Meteor.loginWithTwitter loginCallback
2014-11-12 17:27:20 +01:00
Template.reconnect.helpers
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
2014-11-12 17:27:20 +01:00
Template.account.helpers
dateformat: -> if getUser() then return getUser().dateformat
2015-03-09 18:03:25 +01:00
apikey: -> if getUser() then return getUser().apiKey
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"
2015-03-09 18:03:25 +01:00
t.find('#set-api-key').value = ''
'click #save-settings': (e,t) ->
Meteor.users.update getUser()._id,
2015-03-09 18:03:25 +01:00
$set:
dateformat: t.find('#set-date-format').value
apiKey: t.find('#set-api-key').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-11-12 17:27:20 +01:00
formattedDate = ->
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
2014-11-15 10:22:48 +01:00
notePaginator = new Paginator(10)
notelist = ->
notePaginator.calibrate(notes.find(archived: no).count())
opt = notePaginator.queryOptions()
notes.find({ archived: no },{
sort: {date: 1}, skip: opt.skip, limit: opt.limit
})
2014-11-12 17:27:20 +01:00
Template.notelist.helpers
notelist: -> notelist().fetch()
active: ->
return no unless Router.current() and Router.current().data()
return @_id is Router.current().data()._id
empty: -> notelist().count() is 0
getDate: formattedDate
2014-11-15 10:22:48 +01:00
paginator: -> notePaginator
pageActive: -> if @active then "btn-primary" else "btn-default"
2014-11-12 17:27:20 +01:00
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-11-15 10:22:48 +01:00
'click .btn': -> notePaginator.page @index
2014-06-03 15:40:59 +02:00
# Archive
2014-11-15 10:22:48 +01:00
archivePaginator = new Paginator(10)
archived = ->
archivePaginator.calibrate(notes.find(archived: yes).count())
opt = archivePaginator.queryOptions()
notes.find({archived: yes},{
sort: {date: 1}, limit: opt.limit, skip: opt.skip
})
2014-11-12 17:27:20 +01:00
Template.archivedlist.helpers
empty: -> archived().count() is 0
getDate: formattedDate
archived: -> archived().fetch()
2014-11-15 10:22:48 +01:00
paginator: -> archivePaginator
pageActive: -> if @active then "btn-primary" else "btn-default"
2014-11-12 17:27:20 +01:00
Template.archivedlist.events
2014-06-03 15:40:59 +02:00
'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()
2014-11-15 10:22:48 +01:00
'click .btn': (e) -> archivePaginator.page @index
2014-06-03 15:40:59 +02:00
# Note Editor
2014-11-12 17:27:20 +01:00
Template.editor.helpers
note: -> Router.current().data()
dateformat: -> getUser().dateformat
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
# "Error" visualization template
showError = (err) ->
2014-10-09 16:46:23 +02:00
return unless err?
type = err.type or 'error'
if !err.title?
title = if type is 'error' then 'Error' else 'Ok'
else title = err.title
swal title, err.msg, type
2014-06-05 17:03:10 +02:00
# Verify Email page
2014-11-12 17:27:20 +01:00
Template.verifyEmail.helpers
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
2014-11-12 17:27:20 +01:00
2014-05-31 18:09:56 +02:00
Template.register.events
'click #register-btn': (e,t) -> registerRequest null,t
'keypress .register': (e,t) -> registerRequest e,t