<commit_before>require 'rack/golem'
require 'json'

module PopulateMe
  module Control
    F = ::File
    DIR = F.expand_path(F.dirname(__FILE__)+'/control')
    BEFORE = proc{
    }

    def self.included(klass)
      klass.class_eval do
        include ::Rack::Golem
        extend ClassMethods
      end
      klass.before(&BEFORE)
    end

    module ClassMethods
      def new(*)
        ::Rack::Static.new(::Rack::MethodOverride.new(super), :urls => ["/_public"], :root => DIR)
      end 
      def config
        @config ||= {
          :client_name => '<NAME>',
          :website_url => 'www.domain.com',
          :page_title => 'Populate Me',
          :path => '/admin',
          :logout_path => '/admin/logout', # sometimes higher in stack
          :menu => [['Home', '/admin']],
        }
      end
    end

    def index(class_name=nil, id=nil)
      if class_name.nil?
        @r.env['erb.location'] = DIR+'/views/'
        erb :populate_me_layout
      else
        http_method = @r.request_method.downcase
        if ['post','put','delete'].include?(http_method)
          @model_class_name, @id = class_name, id
          build_model_vars
          return if @res.status==404
          @res['Content-Type'] = 'text/json'
          __send__(http_method)
        else
          send_404
          '' # Trick for the moment but it needs a throw for 404
        end
      end
    end    

    def menu(*levels)
      level_menu = config[:menu]
      levels.each do |l|
        level_menu = level_menu.assoc(l)[1]
      end
      items = level_menu.map do |i|
        {
          'title'=>i[0].gsub(/-/, ' '),
          'href'=> i[1].kind_of?(String) ? i[1] : "#{config[:path]}/menu/#{levels.join('/')}/#{i[0]}"
        }
      end
      page_title = levels.empty? ? config[:page_title] : levels.join(' / ').gsub(/-/, ' ')
      
      @res['Content-Type'] = 'text/json'
      JSON.generate({
        'action'=>'menu',
        'page_title'=>page_title,
        'items'=>items
      })
    end

    def list(class_name)
      @model_class_name = class_name
      resolve_model_class
      items = @model_class.find(@r['filter']||{}).map {|m| m.to_nutshell }
      
      @res['Content-Type'] = 'text/json'
      JSON.generate({
        'action'=> 'list',
        'page_title'=> @model_class.human_plural_name,
        'class_name'=> class_name,
        'sortable'=> @model_class.sortable_on_that_page?(@r),
        'command_plus'=> !@model_class.populate_config[:no_plus],
        'command_search'=> !@model_class.populate_config[:no_search],
        'items'=> items,
      })
    end

    def form(class_name=nil, id=nil)
      @model_class_name, @id = class_name, id<commit_msg>Use URL escape so that the menu never breaks and works well<commit_after>require 'rack/golem'
require 'json'

module PopulateMe
  module Control
    F = ::File
    DIR = F.expand_path(F.dirname(__FILE__)+'/control')
    BEFORE = proc{
    }

    def self.included(klass)
      klass.class_eval do
        include ::Rack::Golem
        extend ClassMethods
      end
      klass.before(&BEFORE)
    end

    module ClassMethods
      def new(*)
        ::Rack::Static.new(::Rack::MethodOverride.new(super), :urls => ["/_public"], :root => DIR)
      end 
      def config
        @config ||= {
          :client_name => '<NAME>',
          :website_url => 'www.domain.com',
          :page_title => 'Populate Me',
          :path => '/admin',
          :logout_path => '/admin/logout', # sometimes higher in stack
          :menu => [['Home', '/admin']],
        }
      end
    end

    def index(class_name=nil, id=nil)
      if class_name.nil?
        @r.env['erb.location'] = DIR+'/views/'
        erb :populate_me_layout
      else
        http_method = @r.request_method.downcase
        if ['post','put','delete'].include?(http_method)
          @model_class_name, @id = class_name, id
          build_model_vars
          return if @res.status==404
          @res['Content-Type'] = 'text/json'
          __send__(http_method)
        else
          send_404
          '' # Trick for the moment but it needs a throw for 404
        end
      end
    end    

    def menu(*levels)
      level_menu = config[:menu]
      levels.each do |l|
        level_menu = level_menu.assoc(::Rack::Utils.unescape(l))[1]
      end
      items = level_menu.map do |i|
        {
          'title'=>i[0],
          'href'=> i[1].kind_of?(String) ? i[1] : "#{config[:path]}/menu/#{levels.join('/')}/#{::Rack::Utils.escape(i[0])}"
        }
      end
      page_title = levels.empty? ? config[:page_title] : ::Rack::Utils.unescape(levels.join(' / '))
      
      @res['Content-Type'] = 'text/json'
      JSON.generate({
        'action'=>'menu',
        'page_title'=>page_title,
        'items'=>items
      })
    end

    def list(class_name)
      @model_class_name = class_name
      resolve_model_class
      items = @model_class.find(@r['filter']||{}).map {|m| m.to_nutshell }
      
      @res['Content-Type'] = 'text/json'
      JSON.generate({
        'action'=> 'list',
        'page_title'=> @model_class.human_plural_name,
        'class_name'=> class_name,
        'sortable'=> @model_class.sortable_on_that_page?(@r),
        'command_plus'=> !@model_class.populate_config[:no_plus],
        'command_search'=> !@model_class.populate_config[:no_search],
        'items'=> items,
      })
    end

    def form(class_name=nil, id=nil)
      @model_class_name, @id = class_name, id
{'fraction_non_alphanumeric': 0.15577063550036524, 'fraction_numerical': 0.005113221329437546, 'mean_word_length': 2.197314652656159, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6481008', 'n_tokens_mistral': 1833, 'n_tokens_neox': 1808, 'n_words': 339}