Skip to content
This repository has been archived by the owner on Jun 12, 2018. It is now read-only.

Commit

Permalink
Add pending event sharing management and link it with the proxy
Browse files Browse the repository at this point in the history
* Fetch sharings having rules with doctype 'event' and display a notification
button in the calendar header

* Do not list the shared event's calendar in menu
* Do not list sharings already accepted
* Handle realtime
  • Loading branch information
gregorylegarec committed May 26, 2016
1 parent 721a631 commit 99a1774
Show file tree
Hide file tree
Showing 29 changed files with 425 additions and 25 deletions.
12 changes: 11 additions & 1 deletion client/app/application.coffee
@@ -1,5 +1,7 @@
module.exports =

listenTo: Backbone.Model.prototype.listenTo

initialize: ->

window.app = @
Expand Down Expand Up @@ -30,12 +32,15 @@ module.exports =
EventCollection = require 'collections/events'
ContactCollection = require 'collections/contacts'
CalendarsCollection = require 'collections/calendars'
SharingCollection = require 'collections/sharings'

@tags = new TagCollection()
@events = new EventCollection()
@contacts = new ContactCollection()
@calendars = new CalendarsCollection()

@pendingEventSharings = new SharingCollection()

# Main Store is used to mark which months were loaded or not.
# That way the app knows when data fetching is required.
@mainStore =
Expand All @@ -51,12 +56,13 @@ module.exports =
isMobile = @isMobile()

@router = new Router isMobile: isMobile

@menu = new Menu collection: @calendars
@menu.render().$el.prependTo 'body'

SocketListener.watch @events
SocketListener.watch @contacts
SocketListener.watch @calendars
SocketListener.watch @pendingEventSharings

if window.initcalendars?
@calendars.reset window.initcalendars
Expand All @@ -74,6 +80,10 @@ module.exports =
@contacts.reset window.initcontacts
delete window.initcontacts

if window.initPendingEventSharings
@pendingEventSharings.reset window.initPendingEventSharings
delete window.initPendingEventSharings

Backbone.history.start()

# Starts the automatic update of 'today'
Expand Down
6 changes: 4 additions & 2 deletions client/app/collections/scheduleitems.coffee
Expand Up @@ -8,8 +8,10 @@ module.exports = class ScheduleItemsCollection extends Backbone.Collection
# to check every event calendar in the a given calendars collection
# to verify the visibility
visibleItems: (calendars) ->
new ScheduleItemsCollection @filter (item) ->
calendar = calendars.get item.getCalendar()?.get('id')
new ScheduleItemsCollection @filter (scheduleItem) ->
return true if scheduleItem.isShared()

calendar = calendars.get scheduleItem.getCalendar()?.get('id')
return calendar?.get 'visible'


Expand Down
11 changes: 11 additions & 0 deletions client/app/collections/sharings.coffee
@@ -0,0 +1,11 @@
Sharing = require '../models/sharing'

module.exports = class SharingCollection extends Backbone.Collection
model: Sharing

initialize: ->
@on 'accepted refused', @onAnsweredSharing


onAnsweredSharing: (sharing) ->
@remove sharing
10 changes: 10 additions & 0 deletions client/app/lib/base_view.coffee
Expand Up @@ -22,3 +22,13 @@ module.exports = class BaseView extends Backbone.View
@$el.removeData().unbind()
@remove()
Backbone.View::remove.call @


# "Snap" the view to the given view if an element with the view ID already
# exists in it.
# Do nothing if the element with the given ID does not exist.
snap: (view) ->
selector = if @id then "##{@id}" else ".#{@className}"
view.$(selector).each (index, element) =>
if element then @setElement element
@
18 changes: 18 additions & 0 deletions client/app/lib/popup_view.coffee
@@ -0,0 +1,18 @@
BaseView = require 'lib/base_view'

# Represent a popup view
module.exports = class PopupView extends BaseView

initialize: (options) ->
super
@anchor = options.anchor


hide: ->
@$el.hide()
@


toggle: (display)->
@$el.toggle display
@
39 changes: 32 additions & 7 deletions client/app/lib/socket_listener.coffee
Expand Up @@ -3,25 +3,50 @@ class SocketListener extends CozySocketListener
models:
'event': require 'models/event'
'contact': require 'models/contact'
'sharing': require 'models/sharing'

events: [
'event.create', 'event.update', 'event.delete'
'contact.create', 'contact.update', 'contact.delete'
'sharing.create', 'sharing.delete'
]

constructor: ->
super
@queue = async.queue @handleModel, 1


onEvent: (event) ->
start = moment(event.get('start')).format('YYYY-MM')
#TODO: do not rely on window object
if window.app.mainStore.loadedMonths[start]
@onRemoteCreateOrUpdate event


onSharing: (sharing) ->
targets = sharing.get 'targets'
currentUserIsTheRecipient = not targets
rules = sharing.get 'rules'

if currentUserIsTheRecipient and rules and rules.find( (rule) ->
return rule.docType.toLowerCase() is 'event' )
@onRemoteCreateOrUpdate sharing


handleModel: (model, next) =>
model.fetch
success: (fetched) =>
if fetched.get('docType') isnt 'event'
@onRemoteCreateOrUpdate fetched
docType = fetched.get('docType')
# generate specific handler name to avoid switch/case
# onEvent, onSharing, etc.
handler = 'on' +
docType.charAt(0).toUpperCase() +
docType.slice(1)

if typeof @[handler] is 'function'
@[handler] fetched
else
start = moment(fetched.get('start')).format('YYYY-MM')
if window.app.mainStore.loadedMonths[start]
@onRemoteCreateOrUpdate fetched
@onRemoteCreateOrUpdate fetched

setTimeout next, 50

Expand All @@ -41,11 +66,11 @@ class SocketListener extends CozySocketListener
for collection in @collections when model = collection.get id
model.trigger 'destroy', model, model.collection, {}


# Todo : should not we be more specific at what we are listening and where
# we insert it ?
onRemoteCreateOrUpdate: (fetched) ->
for collection in @collections
if fetched instanceof collection.model
console.log('D')
collection.add fetched, {merge: true}


Expand Down
4 changes: 4 additions & 0 deletions client/app/lib/view_collection.coffee
Expand Up @@ -35,6 +35,7 @@ module.exports = class ViewCollection extends BaseView

# bind listeners to the collection
initialize: ->
throw new Error('Collection is undefined') if not @collection
super
@views = {}
@listenTo @collection, "reset", @onReset
Expand All @@ -46,6 +47,9 @@ module.exports = class ViewCollection extends BaseView
@collectionEl = @el
@$collectionEl = @$el

getRenderData: ->
collection: @collection?.toJSON()

# if we have views before a render call, we detach them
render: ->
view.$el.detach() for id, view of @views
Expand Down
3 changes: 3 additions & 0 deletions client/app/models/scheduleitem.coffee
Expand Up @@ -350,3 +350,6 @@ module.exports = class ScheduleItem extends Backbone.Model

@startDateChanged = false
@attendeesChanged = false

isShared: ->
return @get('shareID')?
24 changes: 24 additions & 0 deletions client/app/models/sharing.coffee
@@ -0,0 +1,24 @@
request = require 'lib/request'


module.exports = class Sharing extends Backbone.Model

urlRoot: 'sharings'

accept: (callback) ->
id = @get 'id'
request.post 'sharing/accept', @toJSON(), (err, response) =>
if err
callback err, null
else
callback null, response
@trigger 'accepted', @

refuse: (callback) ->
id = @get 'id'
request.post 'sharing/refuse', @toJSON(), (err, response) =>
if err
callback err, null
else
callback null, response
@trigger 'refused', @
3 changes: 3 additions & 0 deletions client/app/router.coffee
Expand Up @@ -95,13 +95,16 @@ module.exports = class Router extends Backbone.Router

displayCalendar: (view, year, month, day) =>
@lastDisplayCall = Array.apply arguments

@displayView new CalendarView
year: parseInt year
month: (parseInt(month) + 11) % 12
date: parseInt day
view: view
model:
events: app.events
# TODO : All router logic should be in app object
pendingEventSharingsCollection: app.pendingEventSharings

app.menu.activate 'calendar'
@onCalendar = true
Expand Down
13 changes: 12 additions & 1 deletion client/app/views/calendar_view.coffee
@@ -1,6 +1,7 @@
app = require 'application'
BaseView = require 'lib/base_view'
EventPopover = require './calendar_popover_event'
EventSharingButtonView = require './pending_event_sharings_button'
Header = require './calendar_header'
helpers = require 'helpers'
timezones = require('helpers/timezone').timezones
Expand All @@ -17,15 +18,25 @@ module.exports = class CalendarView extends BaseView
initialize: (@options) ->

@eventCollection = @model.events

@listenTo @eventCollection, 'add' , @refresh
@listenTo @eventCollection, 'reset', @refresh
@listenTo @eventCollection, 'remove', @onRemove
@listenTo @eventCollection, 'change', @refreshOne
@model = null

@calendarsCollection = app.calendars
@listenTo @calendarsCollection, 'change', @onCalendarCollectionChange

@eventSharingButtonView = new EventSharingButtonView
collection: @model.pendingEventSharingsCollection

@model = null


render: ->
super()
@eventSharingButtonView.snap(@).render()


afterRender: ->
locale = moment.localeData()
Expand Down
17 changes: 17 additions & 0 deletions client/app/views/collection_counter.coffee
@@ -0,0 +1,17 @@
# Fix naming of ViewCollection Class to CollectionView
CollectionView = require 'lib/view_collection'

module.exports = class CollectionCounterView extends CollectionView

className: 'collection-counter'
template: require('./templates/collection_counter')


initialize: (options) ->
super options

@stopListening @collection

@listenTo @collection, 'add remove reset', @render

afterRender: ->
65 changes: 65 additions & 0 deletions client/app/views/pending_event_sharings_button.coffee
@@ -0,0 +1,65 @@
# Fix naming of ViewCollection Class to CollectionView
CollectionView = require 'lib/view_collection'
CollectionCounterView = require './collection_counter'
PopupView = require 'lib/popup_view'

module.exports = class PendingEventSharingsButtonView extends CollectionView

id: 'shared-events-button'
template: require('./templates/pending_event_sharings_button')
itemview: require('./pending_event_sharings_button_item')
collectionEl: '#shared-events-popup'


events:
'click button': 'togglePopup'
'keyup': 'onKeyUp'


initialize: ->
super()

@counterView = new CollectionCounterView
collection: @collection


togglePopup: (display) ->
@popup and @popup.toggle()


render: ->
super
@counterView.snap(@).render()


afterRender: ->
if @collection.length then @$el.show() else @$el.hide()

super

@popup = new PopupView
el: @$ @collectionEl
anchor: @$el


addItem: (model) ->
@$el.show()
super model


removeItem: (model) ->
super model

if @collection.length == 0
@popup.hide()
@$el.hide()


onKeyUp: (event) ->
keys = ESC: 27
if event.keyCode is keys.ESC
@withdraw


withdraw: ->
@togglePopup(false)
27 changes: 27 additions & 0 deletions client/app/views/pending_event_sharings_button_item.coffee
@@ -0,0 +1,27 @@
BaseView = require 'lib/base_view'

module.exports = class PendingEventSharingsButtonItemView extends BaseView

className: 'event-sharings-button-item'
template: require './templates/pending_event_sharings_button_item'

events:
'click .accept': 'onAccept'
'click .decline': 'onDecline'

initialize: ->
@listenTo @model, 'accepted refused', @destroy

onAccept: ->
@model.accept (err) =>
if err
@onAnswerError err


onDecline: ->
@model.refuse (err) =>
if err
@onAnswerError err

onAnswerError: (err) ->
console.error err

0 comments on commit 99a1774

Please sign in to comment.