begin
require 'mongo_mutation'
require 'mongo_crushyform'
require 'mongo_stash'
rescue LoadError
nil
end
require 'bureau/adapter'
module BackendApiAdapter
module ClassMethods
def backend_get(id); id=='unique' ? find_one : get(id); end
def backend_post(doc=nil); inst = new(doc); inst.is_new = true; inst; end
end
module InstanceMethods
def backend_delete; delete; end
def backend_put(fields); update_doc(fields); end
def backend_values; @doc; end
def backend_save?; !save.nil?; end
def backend_form(url, cols=nil, opts={})
cols ||= default_backend_columns
if block_given?
fields_list = ''
yield(fields_list)
else
fields_list = respond_to?(:crushyform) ? crushyform(cols) : backend_fields(cols)
end
o = "
\n"
o
end
def backend_delete_form(url, opts={}); backend_form(url, [], {:submit_text=>'X', :method=>'DELETE'}.update(opts)){}; end
def backend_clone_form(url, opts={})
backend_form(url, [], {:submit_text=>'CLONE', :method=>'POST'}.update(opts)) do |out|
out << "\n"
end
end
# Silly but usable form prototype
# Not really meant to be used in a real case
# It uses a textarea for everything
# Override it
# Or even better, use Sequel-Crushyform plugin instead
def backend_fields(cols)
o = ''
cols.each do |c|
identifier = "#{id}-#{self.class}-#{c}"
o << " \n"
o << " \n"
end
o
end
def backend_form_title; self.new? ? "
New #{model.human_name}
\n" : "
Edit #{self.to_label}
\n"; end
def backend_show; 'OK'; end
end
end
module MongoBureau
BUREAU_CRUSHYFORM_TYPES = {
}
def self.included(base)
base.extend(BackendApiAdapter::ClassMethods)
base.extend(MongoCrushyform::ClassMethods) if defined?(MongoCrushyform)
base.extend(Bureau::Adapter::ClassMethods)
base.extend(ClassMethods)
base.bureau_config = {:nut_tree_class=>'sortable-grid'}
base.crushyform_types.update(BUREAU_CRUSHYFORM_TYPES)
end
module ClassMethods
attr_accessor :list_options
def list_view(r)
@list_options = {:request=>r, :destination=>r.fullpath, :path=>r.script_name, :filter=>r['filter'] }
@list_options.store(:sortable,sortable_on_that_page?)
out = list_view_header
out << scene_selector unless bureau_config[:scene_selector_class].nil?
out << many_to_many_picker unless bureau_config[:minilist_class].nil?
out << "
"
self.find(typecast_filter(@list_options[:filter]||{}), (self.respond_to?(:list_view_fields) ? {fields: self.list_view_fields} : {})).each do |m|
out << m.to_nutshell
end
out << "
"
end
def sortable_on_that_page?
o = @list_options
o[:search].nil? && @schema.key?('position') && (@schema['position'][:scope].nil? || (o[:filter]||{}).key?(@schema['position'][:scope]))
end
def minilist_view
o = "
\n"
self.find.each do |m|
thumb = m.respond_to?(:to_bureau_thumb) ? m.to_bureau_thumb('stash_thumb_gif') : m.placeholder_thumb('stash_thumb_gif')
o << "
#{thumb}
#{m.to_label}
\n"
end
o << "
\n"
end
def scene_selector
o = @list_options
klass = bureau_config[:scene_selector_class].is_a?(Symbol) ? Kernel.const_get(bureau_config[:scene_selector_class]) : bureau_config[:scene_selector_class]
obj = klass.get(o[:filter]["id_#{bureau_config[:scene_selector_class]}"])
unless obj.nil?
out = "
Point and click in order to highlight a zone.
\n"
out << obj.build_image_tag('image','original', :class=>'mapolygon-me')
save_btn = command_plus.sub(/btn btn-plus/, 'save-mapolygon').sub(/>, '>Create this zone<').sub(/(href='[^']*)/, "\\1&model[coordinates]=")
out << "
#{save_btn}
\n"
end
end
private
def image_slot(name='image',opts={})
super(name,opts)
# First image slot is considered the best bureau thumb
unless instance_methods.include?(:to_bureau_thumb)
define_method :to_bureau_thumb do |style|
generic_thumb(name, style)
end
end
end
def typecast_filter filter={}
filter.each do |k,v|
filter[k] = true if v=='true'
filter[k] = false if v=='false'
filter[k] = v.to_i if v[/^\d+$/]
end
end
end
include BackendApiAdapter::InstanceMethods
include MongoCrushyform::InstanceMethods if defined?(MongoCrushyform)
include Bureau::Adapter::InstanceMethods
def after_stash(col)
convert(col, "-resize '100x75^' -gravity center -extent 100x75", 'stash_thumb_gif')
convert(col, "-resize '184x138^' -gravity center -extent 184x138", 'nutshell_jpg')
end
def bureau_attachment_url_for obj, col='image', size='original'
return obj.attachment_url(col,size) if obj.respond_to?(:attachment_url)
"/gridfs/#{obj.doc[col][size]}"
end
def generic_thumb(img , size='stash_thumb_gif', obj=self)
return placeholder_thumb(size) if obj.nil?
current = obj.doc[img]
if !current.nil? && !current[size].nil?
"\n"
else
placeholder_thumb(size)
end
end
def to_thumb(c)
current = @doc[c]
if current.respond_to?(:[])
img_url = @doc[c]['stash_thumb_gif'].nil? ? model.list_options&&"#{model.list_options[:path]}/_static/img/file.png" : bureau_attachment_url_for(self,c,'stash_thumb_gif')
"\n"
end
end
def scene_selector_coordinates; @doc['coordinates']; end
def in_nutshell
o = model.list_options
out = "
\n"
out << self.to_bureau_thumb('nutshell_jpg') if self.respond_to?(:to_bureau_thumb)
cols = model.bureau_config[:quick_update_fields] || nutshell_backend_columns.select{|col|
[:boolean,:select].include?(model.schema[col][:type]) && !model.schema[col][:multiple] && !model.schema[col][:no_quick_update]
}
cols.each do |c|
column_label = model.schema[c][:name] || c.to_s.sub(/^id_/, '').tr('_', ' ').capitalize
out << "\n"
end
out << "
\n"
end
def nutshell_children
o = model.list_options
out = ""
nutshell_backend_associations.each do |k, opts|
next if opts[:hidden]
k = Kernel.const_get(k)
link = "#{o[:path]}/list/#{k}?filter[#{model.foreign_key_name}]=#{self.id}"
text = opts[:link_text] || "#{k.human_name}(s)"
out << "#{text} #{self.children_count(k) unless opts[:hide_count]}\n"
end
out
end
def nutshell_backend_associations
model.relationships
end
def default_backend_columns; model.schema.keys; end
def cloning_backend_columns; default_backend_columns.reject{|c| model.schema[c][:type]==:attachment}; end
end