Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AndyObtiva/6e977d607f1ff1ba18867c9db0f3a222 to your computer and use it in GitHub Desktop.
Save AndyObtiva/6e977d607f1ff1ba18867c9db0f3a222 to your computer and use it in GitHub Desktop.
# Source: https://github.com/AndyObtiva/glimmer-dsl-web/blob/master/lib/glimmer-dsl-web/samples/regular/todo_mvc/presenters/todo_presenter.rb
require 'glimmer/data_binding/observer'
require_relative '../models/todo'
class TodoPresenter
FILTERS = [:all, :active, :completed]
FILTER_ROUTE_REGEXP = /\#\/([^\/]*)$/
attr_accessor :can_clear_completed, :active_todo_count, :created_todo
attr_reader :todos, :new_todo, :filter
def initialize
@todos = []
@new_todo = Todo.new(task: '')
@filter = :all
@can_clear_completed = false
@active_todo_count = 0
todo_stat_refresh_observer.observe(todos) # refresh stats if todos array adds/removes todo objects
end
def active_todos = todos.select(&:active?)
def completed_todos = todos.select(&:completed?)
def create_todo
todo = new_todo.clone
todos.append(todo)
observe_todo_completion_to_update_todo_stats(todo)
new_todo.task = ''
self.created_todo = todo # notifies View observer indirectly to add created todo to todo list
end
def filter=(filter)
return if filter == @filter
@filter = filter
end
def destroy(todo)
delete(todo)
end
def clear_completed
refresh_todo_stats do
completed_todos.each { |todo| delete(todo) }
end
end
def toggle_all_completed
target_completed_value = active_todos.any?
todos_to_update = target_completed_value ? active_todos : completed_todos
refresh_todo_stats do
todos_to_update.each { |todo| todo.completed = target_completed_value }
end
end
def setup_filter_routes
@filter_router_function = -> (event) { apply_route_filter }
$$.addEventListener('popstate', &@filter_router_function)
apply_route_filter
end
def apply_route_filter
route_filter_match = $$.document.location.href.to_s.match(FILTER_ROUTE_REGEXP)
return if route_filter_match.nil?
route_filter = route_filter_match[1]
route_filter = 'all' if route_filter == ''
self.filter = route_filter
end
def unsetup_filter_routes
$$.removeEventListener('popstate', &@filter_router_function)
@filter_router_function = nil
end
private
def observe_todo_completion_to_update_todo_stats(todo)
# saving observer registration object to deregister when deleting todo
observers_for_todo_stats[todo.object_id] = todo_stat_refresh_observer.observe(todo, :completed)
end
def todo_stat_refresh_observer
@todo_stat_refresh_observer ||= Glimmer::DataBinding::Observer.proc { refresh_todo_stats }
end
def delete(todo)
todos.delete(todo)
observer_registration = observers_for_todo_stats.delete(todo.object_id)
observer_registration&.deregister
todo.deleted = true # notifies View observer indirectly to delete todo
end
def observers_for_todo_stats
@observers_for_todo_stats = {}
end
def refresh_todo_stats(&work_before_refresh)
if work_before_refresh
@do_not_refresh_todo_stats = true
work_before_refresh.call
@do_not_refresh_todo_stats = nil
end
return if @do_not_refresh_todo_stats
refresh_can_clear_completed
refresh_active_todo_count
end
def refresh_can_clear_completed
self.can_clear_completed = todos.any?(&:completed?)
end
def refresh_active_todo_count
self.active_todo_count = active_todos.count
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment