Merge branch 'develop' of github.com:martini/zammad into develop

This commit is contained in:
Felix Niklas 2015-11-04 12:32:04 +01:00
commit 8e6807b0eb
23 changed files with 267 additions and 226 deletions

View file

@ -443,7 +443,7 @@ class App.Controller extends Spine.Controller
} }
processData: true, processData: true,
success: (data, status, xhr) -> success: (data, status, xhr) ->
App.Store.write( "user-ticket-popover::#{params.user_id}", data ) App.SessionStorage.set( "user-ticket-popover::#{params.user_id}", data )
# load assets # load assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets( data.assets )
@ -452,7 +452,7 @@ class App.Controller extends Spine.Controller
) )
# get data # get data
data = App.Store.get( "user-ticket-popover::#{params.user_id}" ) data = App.SessionStorage.get( "user-ticket-popover::#{params.user_id}" )
if data if data
show( params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed } ) show( params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed } )
@delay( @delay(

View file

@ -504,13 +504,13 @@ class App.ControllerTable extends App.Controller
data[type][key] = {} data[type][key] = {}
data[type][key] = value data[type][key] = value
@log 'debug', @table_id, 'preferencesStore', data @log 'debug', @table_id, 'preferencesStore', data
localStorage.setItem(@preferencesStoreKey(), JSON.stringify(data)) App.LocalStorage.set(@preferencesStoreKey(), data, @Session.get('id'))
preferencesGet: => preferencesGet: =>
data = localStorage.getItem(@preferencesStoreKey()) data = App.LocalStorage.get(@preferencesStoreKey(), @Session.get('id'))
return {} if !data return {} if !data
@log 'debug', @table_id, 'preferencesGet', data @log 'debug', @table_id, 'preferencesGet', data
JSON.parse(data) data
preferencesStoreKey: => preferencesStoreKey: =>
"tablePreferences:#{@table_id}" "tablePreferences:#{@table_id}"

View file

@ -5,14 +5,14 @@ class App.DashboardActivityStream extends App.Controller
@fetch() @fetch()
# bind to rebuild view event # bind to rebuild view event
@bind( 'activity_stream_rebuild', @load ) @bind('activity_stream_rebuild', @load)
fetch: => fetch: =>
# use cache of first page # use cache of first page
cache = App.Store.get( 'activity_stream' ) cache = App.SessionStorage.get('activity_stream')
if cache if cache
@load( cache ) @load(cache)
# init fetch via ajax, all other updates on time via websockets # init fetch via ajax, all other updates on time via websockets
else else
@ -25,15 +25,16 @@ class App.DashboardActivityStream extends App.Controller
} }
processData: true processData: true
success: (data) => success: (data) =>
App.Store.write( 'activity_stream', data )
@load(data) @load(data)
) )
load: (data) => load: (data) =>
App.SessionStorage.set('activity_stream', data)
items = data.activity_stream items = data.activity_stream
# load assets App.Collection.loadAssets(data.assets)
App.Collection.loadAssets( data.assets )
@render(items) @render(items)
@ -51,7 +52,7 @@ class App.DashboardActivityStream extends App.Controller
html = $('<div class="activity-entries"></div>') html = $('<div class="activity-entries"></div>')
for item in items for item in items
html.append( @renderItem(item) ) html.append(@renderItem(item))
@$('.activity-entries').remove() @$('.activity-entries').remove()
@el.append html @el.append html

View file

@ -3,7 +3,7 @@ class App.DashboardRss extends App.Controller
super super
# bind to rebuild view event # bind to rebuild view event
@bind( 'rss_rebuild', @fetch ) @bind('rss_rebuild', @fetch)
# refresh list ever 600 sec. # refresh list ever 600 sec.
@fetch() @fetch()
@ -11,7 +11,7 @@ class App.DashboardRss extends App.Controller
fetch: => fetch: =>
# get data from cache # get data from cache
cache = App.Store.get( 'dashboard_rss' ) cache = App.SessionStorage.get('dashboard_rss')
if cache if cache
cache.head = 'Heise ATOM' cache.head = 'Heise ATOM'
@render( cache ) @render( cache )
@ -34,7 +34,7 @@ class App.DashboardRss extends App.Controller
message: data.message message: data.message
) )
else else
App.Store.write( 'dashboard_rss', data ) App.SessionStorage.set('dashboard_rss', data)
data.head = 'Heise ATOM' data.head = 'Heise ATOM'
@render(data) @render(data)
error: => error: =>

View file

@ -134,7 +134,7 @@ class App.TicketCreate extends App.Controller
fetch: (params) -> fetch: (params) ->
# use cache # use cache
cache = App.Store.get( 'ticket_create_attributes' ) cache = App.SessionStorage.get( 'ticket_create_attributes' )
if cache && !params.ticket_id && !params.article_id if cache && !params.ticket_id && !params.article_id
@ -157,7 +157,7 @@ class App.TicketCreate extends App.Controller
success: (data, status, xhr) => success: (data, status, xhr) =>
# cache request # cache request
App.Store.write( 'ticket_create_attributes', data ) App.SessionStorage.set( 'ticket_create_attributes', data )
# get edit form attributes # get edit form attributes
@form_meta = data.form_meta @form_meta = data.form_meta

View file

@ -22,7 +22,7 @@ class Index extends App.ControllerContent
fetch: (params) -> fetch: (params) ->
# use cache # use cache
cache = App.Store.get( 'ticket_create_attributes' ) cache = App.SessionStorage.get( 'ticket_create_attributes' )
if cache if cache
@ -42,7 +42,7 @@ class Index extends App.ControllerContent
success: (data, status, xhr) => success: (data, status, xhr) =>
# cache request # cache request
App.Store.write( 'ticket_create_attributes', data ) App.SessionStorage.set( 'ticket_create_attributes', data )
# get edit form attributes # get edit form attributes
@form_meta = data.form_meta @form_meta = data.form_meta

View file

@ -1757,6 +1757,12 @@ class App.CustomerChatRef extends App.Controller
@render() @render()
@interval(
=>
@updateNavMenu()
6800
)
render: -> render: ->
@html App.view('layout_ref/customer_chat')() @html App.view('layout_ref/customer_chat')()
@ -1765,11 +1771,36 @@ class App.CustomerChatRef extends App.Controller
# @testChat @chatWindows[0], 100 # @testChat @chatWindows[0], 100
@initQuiz() @initQuiz()
@updateNavMenu()
show: (params) => show: (params) =>
# highlight navbar # highlight navbar
@navupdate '#layout_ref/customer_chat' @navupdate '#layout_ref/customer_chat'
randomCounter: (min, max) ->
parseInt(Math.random() * (max - min) + min)
counter: =>
@randomCounter(0,100)
switch: (state = undefined) =>
# read state
if state is undefined
value = App.SessionStorage.get('chat')
if value is undefined
value = false
return value
# write state
App.SessionStorage.set('chat', state)
updateNavMenu: =>
delay = ->
App.Event.trigger('menu:render')
@delay(delay, 200)
testChat: (chat, count) -> testChat: (chat, count) ->
for i in [0..count] for i in [0..count]
text = @questions[Math.floor(Math.random() * @questions.length)].question text = @questions[Math.floor(Math.random() * @questions.length)].question
@ -1878,7 +1909,7 @@ class CustomerChatRouter extends App.ControllerPermanent
App.Config.set( 'layout_ref/customer_chat', CustomerChatRouter, 'Routes' ) App.Config.set( 'layout_ref/customer_chat', CustomerChatRouter, 'Routes' )
App.Config.set( 'CustomerChatRef', { controller: 'CustomerChatRef', authentication: true }, 'permanentTask' ) App.Config.set( 'CustomerChatRef', { controller: 'CustomerChatRef', authentication: true }, 'permanentTask' )
App.Config.set( 'CustomerChatRef', { prio: 1200, parent: '', name: 'Customer Chat', target: '#layout_ref/customer_chat', switch: true, counter: true, role: ['Agent'], class: 'chat' }, 'NavBar' ) App.Config.set( 'CustomerChatRef', { prio: 1200, parent: '', name: 'Customer Chat', target: '#layout_ref/customer_chat', key: 'CustomerChatRef', role: ['Agent'], class: 'chat' }, 'NavBar' )
class chatWindowRef extends Spine.Controller class chatWindowRef extends Spine.Controller

View file

@ -6,18 +6,25 @@ class App.Navigation extends App.ControllerWidgetPermanent
@render() @render()
# rerender view, e. g. on langauge change # rerender view, e. g. on langauge change
@bind 'ui:rerender', (data) => @bind 'ui:rerender', =>
@renderMenu() @renderMenu()
@renderPersonal() @renderPersonal()
# rerender menu
@bind 'menu:render', =>
@renderMenu()
# rerender menu
@bind 'personal:render', =>
@renderPersonal()
# update selected item # update selected item
@bind 'navupdate', (data) => @bind 'navupdate', =>
@update( arguments[0] ) @update(arguments[0])
# rebuild nav bar with given user data # rebuild nav bar with given user data
@bind 'auth', (user) => @bind 'auth', (user) =>
@log 'Navigation', 'debug', 'navbar rebuild', user @log 'Navigation', 'debug', 'navbar rebuild', user
@render() @render()
# fetch new recent viewed after collection change # fetch new recent viewed after collection change
@ -43,6 +50,16 @@ class App.Navigation extends App.ControllerWidgetPermanent
renderMenu: => renderMenu: =>
items = @getItems( navbar: @Config.get( 'NavBar' ) ) items = @getItems( navbar: @Config.get( 'NavBar' ) )
# apply counter and switch info from persistant controllers (if exists)
for item in items
if item.key
worker = App.TaskManager.worker(item.key)
if worker
if worker.counter
item.counter = worker.counter()
if worker.switch
item.switch = worker.switch()
# get open tabs to repopen on rerender # get open tabs to repopen on rerender
open_tab = {} open_tab = {}
@$('.open').children('a').each( (i,d) -> @$('.open').children('a').each( (i,d) ->
@ -56,12 +73,24 @@ class App.Navigation extends App.ControllerWidgetPermanent
href = $(d).attr('href') href = $(d).attr('href')
active_tab[href] = true active_tab[href] = true
) )
# render menu
@$('.js-menu').html App.view('navigation/menu')( @$('.js-menu').html App.view('navigation/menu')(
items: items items: items
open_tab: open_tab open_tab: open_tab
active_tab: active_tab active_tab: active_tab
) )
# bind on switch changes and execute it on controller
@$('.js-menu .js-switch').bind('change', (e) =>
val = $(e.target).prop('checked')
key = $(e.target).closest('.menu-item').data('key')
return if !key
worker = App.TaskManager.worker(key)
return if !worker
worker.switch(val)
)
renderPersonal: => renderPersonal: =>
@recentViewNavbarItemsRebuild() @recentViewNavbarItemsRebuild()
items = @getItems( navbar: @Config.get( 'NavBarRight' ) ) items = @getItems( navbar: @Config.get( 'NavBarRight' ) )
@ -198,7 +227,6 @@ class App.Navigation extends App.ControllerWidgetPermanent
# remove not needed popovers # remove not needed popovers
@delay( removePopovers, 280, 'removePopovers' ) @delay( removePopovers, 280, 'removePopovers' )
# observer search box # observer search box
@$('#global-search').bind( 'focusout', (e) => @$('#global-search').bind( 'focusout', (e) =>
# delay to be able to click x # delay to be able to click x

View file

@ -23,9 +23,9 @@ class Index extends App.ControllerContent
return @params if @params return @params if @params
@params = {} @params = {}
paramsRaw = localStorage.getItem('report::params') paramsRaw = App.SessionStorage.get('report::params')
if paramsRaw if paramsRaw
@params = JSON.parse(paramsRaw) @params = paramsRaw
return @params return @params
@params.timeRange = 'year' @params.timeRange = 'year'
@ -58,7 +58,7 @@ class Index extends App.ControllerContent
storeParams: => storeParams: =>
# store latest params # store latest params
localStorage.setItem('report::params', JSON.stringify(@params)) App.SessionStorage.set('report::params', @params)
render: (data = {}) => render: (data = {}) =>

View file

@ -122,7 +122,7 @@ class Table extends App.Controller
for key, value of params for key, value of params
@[key] = value @[key] = value
@view_mode = localStorage.getItem( "mode:#{@view}" ) || 's' @view_mode = App.LocalStorage.get("mode:#{@view}", @Session.get('id')) || 's'
@log 'notice', 'view:', @view, @view_mode @log 'notice', 'view:', @view, @view_mode
return if !@view return if !@view
@ -381,7 +381,7 @@ class Table extends App.Controller
viewmode: (e) => viewmode: (e) =>
e.preventDefault() e.preventDefault()
@view_mode = $(e.target).data('mode') @view_mode = $(e.target).data('mode')
localStorage.setItem( "mode:#{@view}", @view_mode ) App.LocalStorage.set("mode:#{@view}", @view_mode, @Session.get('id'))
@fetch() @fetch()
#@render() #@render()

View file

@ -32,7 +32,7 @@ class App.TicketZoom extends App.Controller
@overview_id = false @overview_id = false
@key = 'ticket::' + @ticket_id @key = 'ticket::' + @ticket_id
cache = App.Store.get(@key) cache = App.SessionStorage.get(@key)
if cache if cache
@load(cache) @load(cache)
update = => update = =>
@ -168,7 +168,7 @@ class App.TicketZoom extends App.Controller
@ticketUpdatedAtLastCall = newTicketRaw.updated_at @ticketUpdatedAtLastCall = newTicketRaw.updated_at
@load(data, force) @load(data, force)
App.Store.write(@key, data) App.SessionStorage(@key, data)
if !@doNotLog if !@doNotLog
@doNotLog = 1 @doNotLog = 1

View file

@ -137,6 +137,7 @@ class App.TicketZoomArticleNew extends App.Controller
ticket: ticket ticket: ticket
articleTypes: @articleTypes articleTypes: @articleTypes
article: @defaults article: @defaults
form_id: @form_id
isCustomer: @isRole('Customer') isCustomer: @isRole('Customer')
) )
@setArticleType(@type) @setArticleType(@type)
@ -167,7 +168,7 @@ class App.TicketZoomArticleNew extends App.Controller
html5Upload.initialize( html5Upload.initialize(
uploadUrl: App.Config.get('api_path') + '/ticket_attachment_upload', uploadUrl: App.Config.get('api_path') + '/ticket_attachment_upload',
dropContainer: @el.get(0), dropContainer: @$('.article-add').get(0),
cancelContainer: @cancelContainer, cancelContainer: @cancelContainer,
inputField: @$('.article-attachment input').get(0), inputField: @$('.article-attachment input').get(0),
key: 'File', key: 'File',

View file

@ -91,7 +91,7 @@ class App.TicketZoomHighlighter extends App.Controller
articles.off('mousedown', @onMouseDown) articles.off('mousedown', @onMouseDown)
articles.on('mousedown', @onMouseDown) #future: touchend articles.on('mousedown', @onMouseDown) #future: touchend
# for testing purposes the highlights get stored in localStorage # for testing purposes the highlights get stored in atrticle preferences
loadHighlights: (ticket_article_id) -> loadHighlights: (ticket_article_id) ->
return if !@isRole('Agent') return if !@isRole('Agent')
article = App.TicketArticle.find(ticket_article_id) article = App.TicketArticle.find(ticket_article_id)

View file

@ -19,7 +19,7 @@ class App.WidgetTag extends App.Controller
@render() @render()
return return
@tags = App.Store.get( @cacheKey ) || [] @tags = App.SessionStorage.get( @cacheKey ) || []
if !_.isEmpty(@tags) if !_.isEmpty(@tags)
@render() @render()
@delay( @delay(
@ -42,7 +42,7 @@ class App.WidgetTag extends App.Controller
processData: true processData: true
success: (data, status, xhr) => success: (data, status, xhr) =>
@tags = data.tags @tags = data.tags
App.Store.write( @cacheKey, @tags ) App.SessionStorage.set( @cacheKey, @tags )
@render() @render()
) )

View file

@ -4,25 +4,25 @@ class App.Collection
@init: -> @init: ->
_instance = new _collectionSingleton _instance = new _collectionSingleton
@load: ( args ) -> @load: (args) ->
if _instance == undefined if _instance == undefined
_instance ?= new _collectionSingleton _instance ?= new _collectionSingleton
_instance.load( args ) _instance.load(args)
@loadAssets: ( args ) -> @loadAssets: (args) ->
if _instance == undefined if _instance == undefined
_instance ?= new _collectionSingleton _instance ?= new _collectionSingleton
_instance.loadAssets( args ) _instance.loadAssets(args)
@reset: ( args ) -> @reset: (args) ->
if _instance == undefined if _instance == undefined
_instance ?= new _collectionSingleton _instance ?= new _collectionSingleton
_instance.reset( args ) _instance.reset(args)
@resetCollections: ( args ) -> @resetCollections: (args) ->
if _instance == undefined if _instance == undefined
_instance ?= new _collectionSingleton _instance ?= new _collectionSingleton
_instance.resetCollections( args ) _instance.resetCollections(args)
class _collectionSingleton extends Spine.Module class _collectionSingleton extends Spine.Module
@include App.LogInclude @include App.LogInclude
@ -35,7 +35,7 @@ class _collectionSingleton extends Spine.Module
@log 'error', 'loadAssets:trigger, got no data, cant load assets' @log 'error', 'loadAssets:trigger, got no data, cant load assets'
return return
@loadAssets( data ) @loadAssets(data)
# add trigger - bind new events # add trigger - bind new events
App.Event.bind 'resetCollection', (data) => App.Event.bind 'resetCollection', (data) =>
@ -43,28 +43,14 @@ class _collectionSingleton extends Spine.Module
@log 'error', 'resetCollection:trigger, got no data, cant for collections' @log 'error', 'resetCollection:trigger, got no data, cant for collections'
return return
@resetCollections( data ) @resetCollections(data)
# find collections to load
@_loadObjectsFromSessionStore()
_loadObjectsFromSessionStore: ->
list = App.Store.list()
for key in list
parts = key.split('::')
if parts[0] is 'collection'
data = App.Store.get( key )
data['type'] = parts[1]
data['sessionStorage'] = true
@log 'debug', 'load INIT', data
@load( data )
resetCollections: (data) -> resetCollections: (data) ->
# load assets
# load collection
for type, collection of data for type, collection of data
@log 'debug', 'resetCollection:trigger', type, collection @log 'debug', 'resetCollection:trigger', type, collection
@reset( sessionStorage: data.sessionStorage, type: type, data: collection ) @reset(type: type, data: collection)
reset: (params) -> reset: (params) ->
@ -74,42 +60,28 @@ class _collectionSingleton extends Spine.Module
@log 'error', 'reset', "no such collection #{params.type}", params @log 'error', 'reset', "no such collection #{params.type}", params
return return
# remove permanent storage
@localDelete( params.type )
# reset in-memory # reset in-memory
appObject.refresh( params.data, { clear: true } ) appObject.refresh(params.data, { clear: true })
# remember in store if not already requested from local storage
for object in params.data
@localStore( params.type, object )
loadAssets: (assets) -> loadAssets: (assets) ->
@log 'debug', 'loadAssets', assets @log 'debug', 'loadAssets', assets
for type, collections of assets for type, collections of assets
@load( sessionStorage: false, type: type, data: collections ) @load(type: type, data: collections)
load: (params) -> load: (params) ->
# no data to load # no data to load
return if _.isEmpty( params.data ) return if _.isEmpty(params.data)
# check if collection exists # check if collection exists
appObject = App[ params.type ] appObject = App[params.type]
if !appObject if !appObject
@log 'error', 'reset', "no such collection #{params.type}", params @log 'error', 'reset', "no such collection #{params.type}", params
return return
sessionStorage = params.sessionStorage
# load full array once # load full array once
if _.isArray( params.data ) if _.isArray(params.data)
appObject.refresh( params.data ) appObject.refresh(params.data)
# remember in store if not already requested from local storage
if !sessionStorage
for object in params.data
@localStore( params.type, object )
return return
# load data from object # load data from object
@ -117,26 +89,12 @@ class _collectionSingleton extends Spine.Module
if !params.refresh && appObject if !params.refresh && appObject
# check if new object is newer, just load newer objects # check if new object is newer, just load newer objects
if object.updated_at && appObject.exists( key ) if object.updated_at && appObject.exists(key)
exists = appObject.find( key ) exists = appObject.find(key)
if exists.updated_at if exists.updated_at
if exists.updated_at < object.updated_at if exists.updated_at < object.updated_at
appObject.refresh( object ) appObject.refresh(object)
else else
appObject.refresh( object ) appObject.refresh(object)
else else
appObject.refresh( object ) appObject.refresh(object)
# remember in store if not already requested from local storage
if !sessionStorage
@localStore( params.type, object)
localDelete: (type) ->
list = App.Store.list()
for key in list
parts = key.split('::')
if parts[0] is 'collection' && parts[1] is type
App.Store.delete(key)
localStore: (type, object) ->
App.Store.write( 'collection::' + type + '::' + object.id, { data: [ object ] } )

View file

@ -0,0 +1,64 @@
class App.LocalStorage
_instance = undefined # Must be declared here to force the closure on the class
@set: (key, value, user_id) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.set(key, value, user_id)
@get: (key, user_id) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.get(key, user_id)
@delete: (key, user_id) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.delete(key)
@clear: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.clear()
@list: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.list()
# The actual Singleton class
class _storeSingleton
constructor: ->
# write to local storage
set: (key, value, user_id) ->
try
if user_id
key = "personal::#{user_id}::#{key}"
localStorage.setItem(key, JSON.stringify(value))
catch e
if e is QUOTA_EXCEEDED_ERR
# do something nice to notify your users
App.Log.error 'App.LocalStorage', 'Local storage quote exceeded!'
# get item
get: (key, user_id) ->
if user_id
key = "personal::#{user_id}::#{key}"
value = localStorage.getItem(key)
return if !value
JSON.parse(value)
# delete item
delete: (key, user_id) ->
if user_id
key = "personal::#{user_id}::#{key}"
localStorage.removeItem(key)
# clear local storage
clear: ->
localStorage.clear()
# return list of all keys
list: ->
window.localStorage

View file

@ -0,0 +1,61 @@
class App.SessionStorage
_instance = undefined # Must be declared here to force the closure on the class
@set: (key, value) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.set(key, value)
@get: (key) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.get(key)
@delete: (key) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.delete(key)
@clear: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.clear()
@list: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.list()
# The actual Singleton class
class _storeSingleton
constructor: ->
App.Event.bind 'clearStore', =>
@clear()
# write to local storage
set: (key, value) ->
try
sessionStorage.setItem(key, JSON.stringify(value))
catch e
if e is QUOTA_EXCEEDED_ERR
# do something nice to notify your users
App.Log.error 'App.SessionStorage', 'Session storage quote exceeded!'
# get item
get: (key) ->
value = sessionStorage.getItem(key)
return if !value
JSON.parse(value)
# delete item
delete: (key) ->
sessionStorage.removeItem(key)
# clear local storage
clear: ->
sessionStorage.clear()
# return list of all keys
list: ->
window.sessionStorage

View file

@ -1,93 +0,0 @@
class App.Store
_instance = undefined # Must be declared here to force the closure on the class
@renew: ->
_instance = new _storeSingleton
@write: (key, value) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.write(key, value)
@get: (args) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.get(args)
@delete: (args) ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.delete(args)
@clear: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.clear()
@list: ->
if _instance == undefined
_instance ?= new _storeSingleton
_instance.list()
# The actual Singleton class
class _storeSingleton
store: {}
constructor: ->
@support = true
if !window.sessionStorage
@support = false
# @support = false
# clear store on every login/logout
if @support
App.Event.bind 'clearStore', =>
@clear('all')
# write to local storage
write: (key, value) ->
@store[key] = value
return if !@support
return if !App.Config.get('ui_client_storage')
try
sessionStorage.setItem( key, JSON.stringify( value ) )
catch e
if e is QUOTA_EXCEEDED_ERR
# do something nice to notify your users
App.Log.error 'App.Store', 'Local storage quote exceeded, please relogin!'
# get item
get: (key) ->
return @store[key] if !@support
return @store[key] if !App.Config.get('ui_client_storage')
value = sessionStorage.getItem( key )
return if !value
object = JSON.parse( value )
return object
# delete item
delete: (key) ->
delete @store[key]
return if !@support
return if !App.Config.get('ui_client_storage')
sessionStorage.removeItem( key )
# clear local storage
clear: ->
@store = {}
sessionStorage.clear()
# return list of all keys
list: ->
list = []
if !@support || !App.Config.get('ui_client_storage')
for key of @store
list.push key
return list
# logLength = sessionStorage.length-1;
# for count in [0..logLength]
# key = sessionStorage.key( count )
# if key
# list.push key
for key of window.sessionStorage
list.push key
list

View file

@ -290,7 +290,6 @@ class _webSocketSingleton extends App.Controller
# fill collection # fill collection
if item['collection'] if item['collection']
@log 'debug', 'onmessage collection:' + item['collection'] @log 'debug', 'onmessage collection:' + item['collection']
App.Store.write( item['collection'], item['data'] )
# fire event # fire event
if item['event'] if item['event']

View file

@ -1,18 +1,9 @@
class App.Model extends Spine.Model class App.Model extends Spine.Model
@destroyBind: false
@apiPath: App.Config.get('api_path') @apiPath: App.Config.get('api_path')
constructor: -> constructor: ->
super super
# delete object from local storage on destroy
if !@constructor.destroyBind
@bind( 'destroy', (e) ->
className = Object.getPrototypeOf(e).constructor.className
key = "collection::#{className}::#{e.id}"
App.Store.delete(key)
)
uiUrl: -> uiUrl: ->
'#' '#'

View file

@ -21,19 +21,19 @@
</ul> </ul>
</div> </div>
<% else: %> <% else: %>
<a class="menu-item js-<%- item.class %>MenuItem<%- ' is-active' if @active_tab[item.target] %>" href="<%= item.target %>"> <a class="menu-item js-<%- item.class %>MenuItem<%- ' is-active' if @active_tab[item.target] %>" href="<%= item.target %>" data-key="<%- item.key %>">
<%- @Icon(item.class, 'menu-item-icon') %> <%- @Icon(item.class, 'menu-item-icon') %>
<span class="menu-item-name"> <span class="menu-item-name">
<%- @T(item.name) %> <%- @T(item.name) %>
</span> </span>
<% if item.counter: %> <% if item.counter isnt undefined: %>
<span class="counter badge badge--big"></span> <span class="counter badge badge--big"><%= item.counter %></span>
<% end %> <% end %>
<% if item.switch: %> <% if item.switch isnt undefined: %>
<span class="zammad-switch zammad-switch--dark zammad-switch--small"> <span class="zammad-switch zammad-switch--dark zammad-switch--small">
<input type="checkbox" id="<%- item.class %>-switch"> <input type="checkbox" id="<%- item.class %>-switch" class="js-switch" <% if item.switch: %>checked<% end %>>
<label for="<%- item.class %>-switch"></label> <label for="<%- item.class %>-switch"></label>
</span> </span>
<% end %> <% end %>
</a> </a>
<% end %> <% end %>

View file

@ -1,7 +1,7 @@
<form class="article-add <% if @article.internal: %>is-internal<% else: %>is-public<% end %>" data-type="<%= @article.type %>"> <form class="article-add <% if @article.internal: %>is-internal<% else: %>is-public<% end %>" data-type="<%= @article.type %>">
<input type="hidden" name="type" value="<%= @article.type %>"> <input type="hidden" name="type" value="<%= @article.type %>">
<input type="hidden" name="internal" value="<%= @article.internal %>"> <input type="hidden" name="internal" value="<%= @article.internal %>">
<input type="hidden" name="form_id" value="<%= @article.form_id %>"> <input type="hidden" name="form_id" value="<%= @form_id %>">
<input type="hidden" name="in_reply_to" value="<%= @article.in_reply_to %>"> <input type="hidden" name="in_reply_to" value="<%= @article.in_reply_to %>">
<div class="editControls"> <div class="editControls">
<div class="js-avatar"></div> <div class="js-avatar"></div>

View file

@ -374,8 +374,8 @@ test( "events level", function() {
}); });
// local store // session store
test( "local store", function() { test( "session store", function() {
var tests = [ var tests = [
'some 123äöüßadajsdaiosjdiaoidj', 'some 123äöüßadajsdaiosjdiaoidj',
@ -384,17 +384,17 @@ test( "local store", function() {
]; ];
// write/get // write/get
App.Store.clear() App.SessionStorage.clear()
_.each(tests, function(test) { _.each(tests, function(test) {
App.Store.write( 'test1', test ); App.SessionStorage.set( 'test1', test );
var item = App.Store.get( 'test1' ); var item = App.SessionStorage.get( 'test1' );
deepEqual( test, item, 'write/get - compare stored and actual data' ) deepEqual( test, item, 'write/get - compare stored and actual data' )
}); });
// undefined/get // undefined/get
App.Store.clear() App.SessionStorage.clear()
_.each(tests, function(test) { _.each(tests, function(test) {
var item = App.Store.get( 'test1' ); var item = App.SessionStorage.get( 'test1' );
deepEqual( undefined, item, 'undefined/get - compare not existing data and actual data' ) deepEqual( undefined, item, 'undefined/get - compare not existing data and actual data' )
}); });
@ -405,16 +405,16 @@ test( "local store", function() {
{ key: '123äöüß', value: { key1: [1,2,3,4] }, key2: [1,2,'äöüß'] }, { key: '123äöüß', value: { key1: [1,2,3,4] }, key2: [1,2,'äöüß'] },
]; ];
App.Store.clear() App.SessionStorage.clear()
_.each(tests, function(test) { _.each(tests, function(test) {
App.Store.write( test.key, test.value ); App.SessionStorage.set( test.key, test.value );
}); });
_.each(tests, function(test) { _.each(tests, function(test) {
var item = App.Store.get( test.key ); var item = App.SessionStorage.get( test.key );
deepEqual( test.value, item, 'write/get/delete - compare stored and actual data' ); deepEqual( test.value, item, 'write/get/delete - compare stored and actual data' );
App.Store.delete( test.key ); App.SessionStorage.delete( test.key );
item = App.Store.get( test.key ); item = App.SessionStorage.get( test.key );
deepEqual( undefined, item, 'write/get/delete - compare deleted data' ); deepEqual( undefined, item, 'write/get/delete - compare deleted data' );
}); });