diff --git a/.gitignore b/.gitignore index 0a9a6497..46faf732 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea *.gem *.rbc .bundle diff --git a/lib/volt/controllers/collection_helpers.rb b/lib/volt/controllers/collection_helpers.rb index 9e142d86..c3a59b81 100644 --- a/lib/volt/controllers/collection_helpers.rb +++ b/lib/volt/controllers/collection_helpers.rb @@ -34,6 +34,10 @@ def local_store Volt.current_app.local_store end + def session_store + Volt.current_app.session_store + end + def cookies Volt.current_app.cookies end diff --git a/lib/volt/models.rb b/lib/volt/models.rb index 13cd02e0..9c8ccdfd 100644 --- a/lib/volt/models.rb +++ b/lib/volt/models.rb @@ -8,6 +8,7 @@ require 'volt/models/persistors/params' require 'volt/models/persistors/cookies' if RUBY_PLATFORM == 'opal' require 'volt/models/persistors/flash' +require 'volt/models/persistors/session_store' require 'volt/models/persistors/local_store' require 'volt/models/root_models/root_models' # require 'volt/models/root_models/store_root' diff --git a/lib/volt/models/persistors/html_store.rb b/lib/volt/models/persistors/html_store.rb new file mode 100644 index 00000000..5c5d6d07 --- /dev/null +++ b/lib/volt/models/persistors/html_store.rb @@ -0,0 +1,55 @@ +require 'volt/models/persistors/base' +require 'volt/utils/html_storage' +require 'volt/utils/ejson' + +module Volt + module Persistors + # Backs a collection in the local store + class HtmlStore < Base + + # Implement in LocalStore and SessionStore + def self.storage + raise 'should be implemented in SessionStore or LocalStore' + end + + # Called when a model is added to the collection + def added(model, index) + root_model.persistor.save_all + end + + def loaded(initial_state = nil) + super + # When the main model is first loaded, we pull in the data from the + # store if it exists + if @model.path == [] + json_data = self.class.storage['volt-store'] + if json_data + root_attributes = EJSON.parse(json_data) + + @loading_data = true + root_attributes.each_pair do |key, value| + @model.send(:"_#{key}=", value) + end + @loading_data = nil + end + end + end + + # Called when an item is changed (or removed) + def changed(attribute_name) + root_model.persistor.save_all + + true + end + + # Called on the root + def save_all + return if @loading_data + + json_data = EJSON.stringify(@model.to_h) + + self.class.storage['volt-store'] = json_data + end + end + end +end diff --git a/lib/volt/models/persistors/local_store.rb b/lib/volt/models/persistors/local_store.rb index 460b2ef6..fd67dd0c 100644 --- a/lib/volt/models/persistors/local_store.rb +++ b/lib/volt/models/persistors/local_store.rb @@ -1,49 +1,15 @@ -require 'volt/models/persistors/base' +require 'volt/models/persistors/html_store' require 'volt/utils/local_storage' -require 'volt/utils/ejson' module Volt module Persistors # Backs a collection in the local store - class LocalStore < Base - # Called when a model is added to the collection - def added(model, index) - root_model.persistor.save_all - end - - def loaded(initial_state = nil) - super - # When the main model is first loaded, we pull in the data from the - # store if it exists - if @model.path == [] - json_data = LocalStorage['volt-store'] - if json_data - root_attributes = EJSON.parse(json_data) - - @loading_data = true - root_attributes.each_pair do |key, value| - @model.send(:"_#{key}=", value) - end - @loading_data = nil - end - end - end + class LocalStore < HtmlStore - # Callled when an item is changed (or removed) - def changed(attribute_name) - root_model.persistor.save_all - - true + def self.storage + LocalStorage end - # Called on the root - def save_all - return if @loading_data - - json_data = EJSON.stringify(@model.to_h) - - LocalStorage['volt-store'] = json_data - end end end end diff --git a/lib/volt/models/persistors/session_store.rb b/lib/volt/models/persistors/session_store.rb new file mode 100644 index 00000000..131721ac --- /dev/null +++ b/lib/volt/models/persistors/session_store.rb @@ -0,0 +1,15 @@ +require 'volt/models/persistors/html_store' +require 'volt/utils/session_storage' + +module Volt + module Persistors + # Backs a collection in the local store + class SessionStore < HtmlStore + + def self.storage + SessionStorage + end + + end + end +end diff --git a/lib/volt/models/root_models/root_models.rb b/lib/volt/models/root_models/root_models.rb index ab0a6d3c..55df476c 100644 --- a/lib/volt/models/root_models/root_models.rb +++ b/lib/volt/models/root_models/root_models.rb @@ -11,7 +11,7 @@ class BaseRootModel < Volt::Model end -ROOT_MODEL_NAMES = [:Store, :Page, :Params, :Cookies, :LocalStore, :Flash] +ROOT_MODEL_NAMES = [:Store, :Page, :Params, :Cookies, :LocalStore, :SessionStore, :Flash] ROOT_MODEL_NAMES.each do |base_name| Object.const_set("#{base_name}Root", Class.new(BaseRootModel)) diff --git a/lib/volt/utils/html_storage.rb b/lib/volt/utils/html_storage.rb new file mode 100644 index 00000000..599f8e34 --- /dev/null +++ b/lib/volt/utils/html_storage.rb @@ -0,0 +1,59 @@ +if RUBY_PLATFORM == 'opal' + module Volt + class HtmlStorage + + # Implement in SessionStorage and LocalStorage + def self.area + raise 'should be implemented in SessionStorage or LocalStorage' + end + + def self.[](key) + ` + var val = #{area}.getItem(key); + return val === null ? nil : val; + ` + end + + def self.[]=(key, value) + `#{area}.setItem(key, value)` + end + + def self.clear + `#{area}.clear()` + self + end + + def self.delete(key) + ` + var val = #{area}.getItem(key); + #{area}.removeItem(key); + return val === null ? nil : val; + ` + end + end + end +else + module Volt + class HtmlStorage + @@store = {} + + def self.[](key) + @@store[key] + end + + def self.[]=(key, value) + @@store[key] = value + end + + def self.clear + @@store = {} + + self + end + + def self.delete(key) + @@store.delete(key) + end + end + end +end diff --git a/lib/volt/utils/local_storage.rb b/lib/volt/utils/local_storage.rb index 76ef7aff..b1be6c09 100644 --- a/lib/volt/utils/local_storage.rb +++ b/lib/volt/utils/local_storage.rb @@ -1,53 +1,13 @@ -if RUBY_PLATFORM == 'opal' - module Volt - module LocalStorage - def self.[](key) - ` - var val = localStorage.getItem(key); - return val === null ? nil : val; - ` - end - - def self.[]=(key, value) - `localStorage.setItem(key, value)` - end +require 'volt/utils/html_storage' - def self.clear - `localStorage.clear()` - self - end +module Volt + class LocalStorage < HtmlStorage - def self.delete(key) - ` - var val = localStorage.getItem(key); - localStorage.removeItem(key); - return val === null ? nil : val; - ` + if RUBY_PLATFORM == 'opal' + def self.area + `localStorage` end end - end -else - module Volt - module LocalStorage - @@store = {} - - def self.[](key) - @@store[key] - end - def self.[]=(key, value) - @@store[key] = value - end - - def self.clear - @@store = {} - - self - end - - def self.delete(key) - @@store.delete(key) - end - end end end diff --git a/lib/volt/utils/session_storage.rb b/lib/volt/utils/session_storage.rb new file mode 100644 index 00000000..336dd873 --- /dev/null +++ b/lib/volt/utils/session_storage.rb @@ -0,0 +1,13 @@ +require 'volt/utils/html_storage' + +module Volt + class SessionStorage < HtmlStorage + + if RUBY_PLATFORM == 'opal' + def self.area + `sessionStorage` + end + end + + end +end diff --git a/lib/volt/volt/repos.rb b/lib/volt/volt/repos.rb index 6b640444..3187fe72 100644 --- a/lib/volt/volt/repos.rb +++ b/lib/volt/volt/repos.rb @@ -32,6 +32,13 @@ def local_store end end + def session_store + @session_store ||= begin + check_for_client?('session_store') + SessionStoreRoot.new({}, persistor: Persistors::SessionStore) + end + end + def cookies @cookies ||= begin check_for_client?('cookies')