engine2 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/engine2.rb +0 -2
- data/lib/engine2/action.rb +14 -13
- data/lib/engine2/core.rb +68 -57
- data/lib/engine2/handler.rb +4 -1
- data/lib/engine2/meta.rb +58 -11
- data/lib/engine2/meta/delete_meta.rb +2 -15
- data/lib/engine2/meta/infra_meta.rb +1 -2
- data/lib/engine2/meta/link_meta.rb +1 -0
- data/lib/engine2/meta/list_meta.rb +4 -3
- data/lib/engine2/meta/save_meta.rb +2 -15
- data/lib/engine2/meta/view_meta.rb +0 -1
- data/lib/engine2/model.rb +32 -22
- data/lib/engine2/scheme.rb +7 -15
- data/lib/engine2/type_info.rb +10 -13
- data/lib/engine2/version.rb +1 -1
- data/views/engine2.coffee +11 -7
- data/views/engine2actions.coffee +4 -1
- data/views/infra/inspect.slim +1 -1
- data/views/modals/close_m.slim +1 -1
- data/views/modals/confirm_m.slim +1 -1
- data/views/modals/empty_m.slim +1 -1
- data/views/modals/menu_m.slim +1 -1
- data/views/modals/yes_no_m.slim +1 -1
- data/views/panels/menu_m.slim +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 5a2ad0107737d0e5096b9a72b31743f01b8107ba
         | 
| 4 | 
            +
              data.tar.gz: 6557952f0c927307bb297d71afc2cbb8086d3318
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 247de7a7bd6535a169b713cd08d1c9034d4e9de87301530986d9eae7b4ef98b4ceb9bff5610daf7ee66cc168c7f110dd585dd7db5691e07112f372c3345792d4
         | 
| 7 | 
            +
              data.tar.gz: b41f9ea4e158dd174b4f71566f93d4fcc0f5bff6270f3885cc5f13e52b9e7fae0ba2f696273611453222bec33aed9f34556cd5a63c46f3a3f3dc8787e4ea7917
         | 
    
        data/lib/engine2.rb
    CHANGED
    
    
    
        data/lib/engine2/action.rb
    CHANGED
    
    | @@ -1,10 +1,11 @@ | |
| 1 1 | 
             
            # coding: utf-8
         | 
| 2 2 |  | 
| 3 3 | 
             
            module Engine2
         | 
| 4 | 
            +
             | 
| 4 5 | 
             
                class Action < BasicObject
         | 
| 5 6 | 
             
                    ACCESS_FORBIDDEN ||= ->h{false}
         | 
| 6 7 | 
             
                    attr_reader :parent, :name, :number, :actions, :recheck_access
         | 
| 7 | 
            -
                    attr_reader :meta_proc | 
| 8 | 
            +
                    attr_reader :meta_proc
         | 
| 8 9 |  | 
| 9 10 | 
             
                    class << self
         | 
| 10 11 | 
             
                        attr_accessor :count
         | 
| @@ -20,17 +21,7 @@ module Engine2 | |
| 20 21 | 
             
                    end
         | 
| 21 22 |  | 
| 22 23 | 
             
                    def * &blk
         | 
| 23 | 
            -
                        if blk
         | 
| 24 | 
            -
                            @meta_proc = if meta_proc = @meta_proc
         | 
| 25 | 
            -
                                @meta_proc_chained = true
         | 
| 26 | 
            -
                                ::Kernel::lambda do |obj|
         | 
| 27 | 
            -
                                    obj.instance_eval(&meta_proc)
         | 
| 28 | 
            -
                                    obj.instance_eval(&blk)
         | 
| 29 | 
            -
                                end
         | 
| 30 | 
            -
                            else
         | 
| 31 | 
            -
                                blk
         | 
| 32 | 
            -
                            end
         | 
| 33 | 
            -
                        end
         | 
| 24 | 
            +
                        @meta_proc = @meta_proc ? @meta_proc.chain(&blk) : blk if blk
         | 
| 34 25 | 
             
                        @meta
         | 
| 35 26 | 
             
                    end
         | 
| 36 27 |  | 
| @@ -74,6 +65,12 @@ module Engine2 | |
| 74 65 | 
             
                        end
         | 
| 75 66 | 
             
                    end
         | 
| 76 67 |  | 
| 68 | 
            +
                    def define_action_invoke name, meta_class = DummyMeta, assets = {}, &blk
         | 
| 69 | 
            +
                        define_action name, meta_class, assets do
         | 
| 70 | 
            +
                            self.*.define_singleton_method(:invoke, &blk)
         | 
| 71 | 
            +
                        end
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
             | 
| 77 74 | 
             
                    def undefine_action name
         | 
| 78 75 | 
             
                        ::Kernel.raise E2Error.new("No action #{name} defined") unless @actions[name]
         | 
| 79 76 | 
             
                        @actions.delete(name)
         | 
| @@ -163,7 +160,7 @@ module Engine2 | |
| 163 160 | 
             
                                model_name = model.name.to_sym
         | 
| 164 161 | 
             
                                model.synchronize_type_info
         | 
| 165 162 | 
             
                                model_actions[model_name] = action.to_a_rec{|a| !a.*.assets[:assoc]}
         | 
| 166 | 
            -
                                action.run_scheme(model_name) if SCHEMES | 
| 163 | 
            +
                                action.run_scheme(model_name) if SCHEMES[model_name, false]
         | 
| 167 164 | 
             
                                false
         | 
| 168 165 | 
             
                            else
         | 
| 169 166 | 
             
                                true
         | 
| @@ -216,6 +213,10 @@ module Engine2 | |
| 216 213 | 
             
                        end
         | 
| 217 214 | 
             
                        ::Kernel::puts "VERIFY #{::Time.now - t}"
         | 
| 218 215 | 
             
                    end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                    def p *args
         | 
| 218 | 
            +
                        ::Kernel::p *args
         | 
| 219 | 
            +
                    end
         | 
| 219 220 | 
             
                end
         | 
| 220 221 |  | 
| 221 222 |  | 
    
        data/lib/engine2/core.rb
    CHANGED
    
    | @@ -27,6 +27,14 @@ class Proc | |
| 27 27 | 
             
                    loc = source_location
         | 
| 28 28 | 
             
                    "\"#<Proc:#{loc.first[/\w+.rb/]}:#{loc.last}>\""
         | 
| 29 29 | 
             
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def chain &blk
         | 
| 32 | 
            +
                    proc = self
         | 
| 33 | 
            +
                    lambda do |obj|
         | 
| 34 | 
            +
                        obj.instance_eval(&proc)
         | 
| 35 | 
            +
                        obj.instance_eval(&blk)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                end
         | 
| 30 38 | 
             
            end
         | 
| 31 39 |  | 
| 32 40 | 
             
            class Hash
         | 
| @@ -123,7 +131,7 @@ class Sequel::Database | |
| 123 131 | 
             
                attr_accessor :models, :default_schema
         | 
| 124 132 |  | 
| 125 133 | 
             
                def cache_file
         | 
| 126 | 
            -
                    "#{ | 
| 134 | 
            +
                    "#{Engine2::app}/#{opts[:orig_opts][:name]}.dump"
         | 
| 127 135 | 
             
                end
         | 
| 128 136 |  | 
| 129 137 | 
             
                def load_schema_cache_from_file
         | 
| @@ -236,7 +244,7 @@ module E2Model | |
| 236 244 | 
             
                            else
         | 
| 237 245 | 
             
                                info[:validations].each_pair do |validation, args|
         | 
| 238 246 | 
             
                                    validation_proc = Engine2::Validations[validation] || args[:lambda] # swap ?
         | 
| 239 | 
            -
                                    raise "Validation not found for field '#{name}' of type #{validation}" unless validation_proc
         | 
| 247 | 
            +
                                    raise E2Error.new("Validation not found for field '#{name}' of type #{validation}") unless validation_proc
         | 
| 240 248 | 
             
                                    if result = validation_proc.(self, name, info)
         | 
| 241 249 | 
             
                                        errors.add(name, result)
         | 
| 242 250 | 
             
                                        break
         | 
| @@ -345,11 +353,7 @@ module E2Model | |
| 345 353 | 
             
                                    fields << name
         | 
| 346 354 | 
             
                                else
         | 
| 347 355 | 
             
                                    fields << :"#{table}__#{name}"
         | 
| 348 | 
            -
                                     | 
| 349 | 
            -
                                    unless assoc
         | 
| 350 | 
            -
                                        # fail
         | 
| 351 | 
            -
                                    end
         | 
| 352 | 
            -
                                    joins[table] = assoc
         | 
| 356 | 
            +
                                    joins[table] = model.many_to_one_associations[table]
         | 
| 353 357 | 
             
                                end
         | 
| 354 358 |  | 
| 355 359 | 
             
                                if f_info[:dummy]
         | 
| @@ -375,11 +379,9 @@ module E2Model | |
| 375 379 | 
             
                        @opts[:select].compact!
         | 
| 376 380 |  | 
| 377 381 | 
             
                        joins.reduce(self) do |joined, (table, assoc)|
         | 
| 378 | 
            -
                            assoc = model.many_to_one_associations[table] # || model.one_to_one_associations[table]
         | 
| 379 382 | 
             
                            m = Object.const_get(assoc[:class_name])
         | 
| 380 383 | 
             
                            keys = assoc[:qualified_key]
         | 
| 381 | 
            -
                             | 
| 382 | 
            -
                            joined.left_join(table, m.primary_keys.zip(keys))
         | 
| 384 | 
            +
                            joined.left_join(table, m.primary_keys.zip(keys.is_a?(Array) ? keys : [keys]))
         | 
| 383 385 | 
             
                        end
         | 
| 384 386 | 
             
                    end
         | 
| 385 387 |  | 
| @@ -433,65 +435,74 @@ module Engine2 | |
| 433 435 | 
             
                PATH ||= File.expand_path('../..', File.dirname(__FILE__))
         | 
| 434 436 |  | 
| 435 437 | 
             
                class << self
         | 
| 436 | 
            -
                     | 
| 437 | 
            -
             | 
| 438 | 
            +
                    attr_reader :app, :reloading
         | 
| 439 | 
            +
                    attr_reader :core_loaded
         | 
| 438 440 |  | 
| 439 | 
            -
             | 
| 441 | 
            +
                    def database name
         | 
| 442 | 
            +
                        Object.const_set(name, yield) unless Object.const_defined?(name)
         | 
| 443 | 
            +
                    end
         | 
| 440 444 |  | 
| 441 | 
            -
             | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 445 | 
            +
                    def connect *args
         | 
| 446 | 
            +
                        db = Sequel.connect *args
         | 
| 447 | 
            +
                        db
         | 
| 448 | 
            +
                    end
         | 
| 444 449 |  | 
| 445 | 
            -
             | 
| 446 | 
            -
             | 
| 447 | 
            -
                     | 
| 448 | 
            -
                    db
         | 
| 449 | 
            -
                end
         | 
| 450 | 
            +
                    def boot &blk
         | 
| 451 | 
            +
                        @boot_blk = blk
         | 
| 452 | 
            +
                    end
         | 
| 450 453 |  | 
| 451 | 
            -
             | 
| 452 | 
            -
             | 
| 453 | 
            -
             | 
| 454 | 
            -
                def DUMMYDB.synchronize *args;end
         | 
| 454 | 
            +
                    def model_boot &blk
         | 
| 455 | 
            +
                        @model_boot_blk = blk
         | 
| 456 | 
            +
                    end
         | 
| 455 457 |  | 
| 456 | 
            -
             | 
| 457 | 
            -
             | 
| 458 | 
            -
             | 
| 458 | 
            +
                    def bootstrap_e2db
         | 
| 459 | 
            +
                        e2_db_file = (defined? JRUBY_VERSION) ? "jdbc:sqlite:#{@app}/engine2.db" : "sqlite://#{@app}/engine2.db"
         | 
| 460 | 
            +
                        Engine2.const_set :E2DB, connect(e2_db_file, loggers: [Logger.new($stdout)], convert_types: false, name: :engine2)
         | 
| 461 | 
            +
                        Engine2.const_set :DUMMYDB, Sequel::Database.new(uri: 'dummy')
         | 
| 462 | 
            +
                        def DUMMYDB.synchronize *args;end
         | 
| 463 | 
            +
                    end
         | 
| 459 464 |  | 
| 460 | 
            -
             | 
| 461 | 
            -
             | 
| 462 | 
            -
             | 
| 465 | 
            +
                    def reload
         | 
| 466 | 
            +
                        @core_loaded = true
         | 
| 467 | 
            +
                        t = Time.now
         | 
| 468 | 
            +
                        Action.count = 0
         | 
| 469 | 
            +
                        SCHEMES.user.clear
         | 
| 470 | 
            +
             | 
| 471 | 
            +
                        Sequel::DATABASES.each do |db|
         | 
| 472 | 
            +
                            db.models.each{|n, m| Object.send(:remove_const, n) if Object.const_defined?(n)} unless db == E2DB || db == DUMMYDB
         | 
| 473 | 
            +
                        end
         | 
| 463 474 |  | 
| 464 | 
            -
             | 
| 465 | 
            -
                    require 'engine2/pre_bootstrap'
         | 
| 466 | 
            -
                    t = Time.now
         | 
| 467 | 
            -
                    Action.count = 0
         | 
| 468 | 
            -
                    SCHEMES.clear
         | 
| 475 | 
            +
                        load "#{app}/boot.rb"
         | 
| 469 476 |  | 
| 470 | 
            -
             | 
| 471 | 
            -
                         | 
| 472 | 
            -
             | 
| 477 | 
            +
                        Sequel::DATABASES.each &:load_schema_cache_from_file
         | 
| 478 | 
            +
                        @model_boot_blk.() if @model_boot_blk
         | 
| 479 | 
            +
                        load 'engine2/models/Files.rb'
         | 
| 480 | 
            +
                        load 'engine2/models/UserInfo.rb'
         | 
| 481 | 
            +
                        Dir["#{app}/models/*"].each{|m| load m}
         | 
| 482 | 
            +
                        puts "MODELS: #{Sequel::DATABASES.reduce(0){|s, d|s + d.models.size}}, Time: #{Time.now - t}"
         | 
| 483 | 
            +
                        Sequel::DATABASES.each &:dump_schema_cache_to_file
         | 
| 473 484 |  | 
| 474 | 
            -
             | 
| 485 | 
            +
                        Engine2.send(:remove_const, :ROOT) if defined? ROOT
         | 
| 486 | 
            +
                        Engine2.const_set(:ROOT, Action.new(nil, :api, DummyMeta, {}))
         | 
| 475 487 |  | 
| 476 | 
            -
             | 
| 477 | 
            -
             | 
| 478 | 
            -
             | 
| 479 | 
            -
                     | 
| 480 | 
            -
                    Dir["#{app}/models/*"].each{|m| load m}
         | 
| 481 | 
            -
                    puts "MODELS, Time: #{Time.now - t}"
         | 
| 482 | 
            -
                    Sequel::DATABASES.each &:dump_schema_cache_to_file
         | 
| 488 | 
            +
                        @boot_blk.(ROOT)
         | 
| 489 | 
            +
                        ROOT.setup_action_tree
         | 
| 490 | 
            +
                        puts "BOOTSTRAP #{app}, Time: #{Time.new - t}"
         | 
| 491 | 
            +
                    end
         | 
| 483 492 |  | 
| 484 | 
            -
                     | 
| 485 | 
            -
             | 
| 486 | 
            -
             | 
| 493 | 
            +
                    def bootstrap app, opts = {}
         | 
| 494 | 
            +
                        @app = app
         | 
| 495 | 
            +
                        @reloading = opts[:reloading]
         | 
| 496 | 
            +
                        bootstrap_e2db
         | 
| 487 497 |  | 
| 488 | 
            -
             | 
| 489 | 
            -
             | 
| 490 | 
            -
             | 
| 491 | 
            -
                     | 
| 492 | 
            -
                    require 'engine2/post_bootstrap'
         | 
| 498 | 
            +
                        require 'engine2/pre_bootstrap'
         | 
| 499 | 
            +
                        reload
         | 
| 500 | 
            +
                        require 'engine2/post_bootstrap'
         | 
| 501 | 
            +
                    end
         | 
| 493 502 | 
             
                end
         | 
| 494 503 |  | 
| 504 | 
            +
                @core_loaded = false
         | 
| 505 | 
            +
             | 
| 495 506 | 
             
                class E2Error < RuntimeError
         | 
| 496 507 | 
             
                    def initialize msg
         | 
| 497 508 | 
             
                        super
         | 
| @@ -534,9 +545,9 @@ module Engine2 | |
| 534 545 | 
             
                        option name, properties, index, &blk
         | 
| 535 546 | 
             
                    end
         | 
| 536 547 |  | 
| 537 | 
            -
                    def option_index iname
         | 
| 548 | 
            +
                    def option_index iname, raise = true
         | 
| 538 549 | 
             
                        index = @entries.index{|e| (e.is_a?(MenuBuilder) ? e.name : e[:name]) == iname}
         | 
| 539 | 
            -
                        raise E2Error.new("No menu option #{iname} found")  | 
| 550 | 
            +
                        raise E2Error.new("No menu option #{iname} found") if !index && raise
         | 
| 540 551 | 
             
                        index
         | 
| 541 552 | 
             
                    end
         | 
| 542 553 |  | 
    
        data/lib/engine2/handler.rb
    CHANGED
    
    | @@ -113,7 +113,10 @@ module Engine2 | |
| 113 113 | 
             
                    get '/*' do |name|
         | 
| 114 114 | 
             
                        headers 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0'
         | 
| 115 115 | 
             
                        if name.empty?
         | 
| 116 | 
            -
                             | 
| 116 | 
            +
                            if settings.environment == :development
         | 
| 117 | 
            +
                                load('engine2.rb') if Engine2::reloading
         | 
| 118 | 
            +
                                Engine2::reload
         | 
| 119 | 
            +
                            end
         | 
| 117 120 | 
             
                            name = 'index'
         | 
| 118 121 | 
             
                        end
         | 
| 119 122 | 
             
                        slim name.to_sym
         | 
    
        data/lib/engine2/meta.rb
    CHANGED
    
    | @@ -140,13 +140,13 @@ module Engine2 | |
| 140 140 |  | 
| 141 141 | 
             
                class DummyMeta < Meta
         | 
| 142 142 | 
             
                    meta_type :dummy
         | 
| 143 | 
            -
             | 
| 144 | 
            -
                    # def invoke handler
         | 
| 145 | 
            -
                    #     {}
         | 
| 146 | 
            -
                    # end
         | 
| 147 143 | 
             
                end
         | 
| 148 144 |  | 
| 149 145 | 
             
                module MetaAPISupport
         | 
| 146 | 
            +
                    def reload_routes!
         | 
| 147 | 
            +
                        @meta[:reload_routes] = true
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
             | 
| 150 150 | 
             
                    def info
         | 
| 151 151 | 
             
                        @meta[:info] ||= {}
         | 
| 152 152 | 
             
                    end
         | 
| @@ -166,6 +166,10 @@ module Engine2 | |
| 166 166 | 
             
                        end
         | 
| 167 167 | 
             
                    end
         | 
| 168 168 |  | 
| 169 | 
            +
                    def loc! hash
         | 
| 170 | 
            +
                        hash.each{|k, v| info! k, loc: v}
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 169 173 | 
             
                    def decorate list
         | 
| 170 174 | 
             
                        list.each do |f|
         | 
| 171 175 | 
             
                            m = (info[f] ||= {})
         | 
| @@ -420,13 +424,10 @@ module Engine2 | |
| 420 424 | 
             
                            panel_panel_template 'menu_m' unless panel[:panel_template] == false
         | 
| 421 425 | 
             
                            # modal_action false if panel[:panel_template] == false
         | 
| 422 426 | 
             
                            panel_class '' unless panel[:class]
         | 
| 427 | 
            +
                            footer true unless panel[:footer] == false
         | 
| 423 428 | 
             
                        end
         | 
| 424 429 | 
             
                    end
         | 
| 425 430 |  | 
| 426 | 
            -
                    def glyphicon name
         | 
| 427 | 
            -
                        "<span class='glyphicon glyphicon-#{name}'></span>"
         | 
| 428 | 
            -
                    end
         | 
| 429 | 
            -
             | 
| 430 431 | 
             
                    def panel
         | 
| 431 432 | 
             
                        @meta[:panel] ||= {}
         | 
| 432 433 | 
             
                    end
         | 
| @@ -450,6 +451,10 @@ module Engine2 | |
| 450 451 | 
             
                    def panel_title tle
         | 
| 451 452 | 
             
                        panel[:title] = tle
         | 
| 452 453 | 
             
                    end
         | 
| 454 | 
            +
             | 
| 455 | 
            +
                    def footer ftr
         | 
| 456 | 
            +
                        panel[:footer] = ftr
         | 
| 457 | 
            +
                    end
         | 
| 453 458 | 
             
                end
         | 
| 454 459 |  | 
| 455 460 | 
             
                class MenuMeta < Meta
         | 
| @@ -543,16 +548,14 @@ module Engine2 | |
| 543 548 | 
             
                        panel_template 'scaffold/list'
         | 
| 544 549 | 
             
                        panel_panel_template 'panels/menu_m' unless action.parent.*.assets[:model]
         | 
| 545 550 | 
             
                        search_template 'scaffold/search'
         | 
| 546 | 
            -
                        panel_title "#{ | 
| 551 | 
            +
                        panel_title "#{:list.icon} #{LOCS[assets[:model].name.to_sym]}"
         | 
| 547 552 | 
             
                        menu(:panel_menu).option :cancel, icon: "remove"
         | 
| 548 553 | 
             
                        menu :menu do
         | 
| 549 554 | 
             
                            properties break: 2, group_class: "btn-group-xs"
         | 
| 550 555 | 
             
                            option :search_toggle, icon: "search", show: "action.meta.search_fields", class: "action.ui_state.search_active && 'active'", button_loc: false
         | 
| 551 | 
            -
             | 
| 552 556 | 
             
                            # divider
         | 
| 553 557 | 
             
                            option :refresh, icon: "refresh", button_loc: false
         | 
| 554 558 | 
             
                            option :default_order, icon: "signal", button_loc: false
         | 
| 555 | 
            -
                            option :select_toggle, icon: "check", enabled: "action.meta.config.selectable", button_loc: false
         | 
| 556 559 | 
             
                            divider
         | 
| 557 560 | 
             
                            option :debug_info, icon: "list-alt" do
         | 
| 558 561 | 
             
                                option :show_meta, icon: "eye-open"
         | 
| @@ -566,6 +569,13 @@ module Engine2 | |
| 566 569 | 
             
                        @meta[:state] = [:query, :ui_state]
         | 
| 567 570 | 
             
                    end
         | 
| 568 571 |  | 
| 572 | 
            +
                    def select_toggle_menu
         | 
| 573 | 
            +
                        m = menu :menu
         | 
| 574 | 
            +
                        unless m.option_index(:select_toggle, false)
         | 
| 575 | 
            +
                            m.option_after :default_order, :select_toggle, icon: "check", enabled: "action.meta.config.selectable", button_loc: false
         | 
| 576 | 
            +
                        end
         | 
| 577 | 
            +
                    end
         | 
| 578 | 
            +
             | 
| 569 579 | 
             
                    def post_run
         | 
| 570 580 | 
             
                        unless panel[:class]
         | 
| 571 581 | 
             
                            panel_class case @meta[:fields].size
         | 
| @@ -666,6 +676,10 @@ module Engine2 | |
| 666 676 | 
             
                    include MetaModelSupport
         | 
| 667 677 | 
             
                    attr_reader :validations
         | 
| 668 678 |  | 
| 679 | 
            +
                    def self.included meta
         | 
| 680 | 
            +
                        meta.http_method :post
         | 
| 681 | 
            +
                    end
         | 
| 682 | 
            +
             | 
| 669 683 | 
             
                    def validate_fields *fields
         | 
| 670 684 | 
             
                        if fields.empty?
         | 
| 671 685 | 
             
                            @validate_fields
         | 
| @@ -736,6 +750,10 @@ module Engine2 | |
| 736 750 | 
             
                module MetaViewSupport
         | 
| 737 751 | 
             
                    include MetaModelSupport, MetaAPISupport, MetaTabSupport, MetaPanelSupport, MetaMenuSupport
         | 
| 738 752 |  | 
| 753 | 
            +
                    def self.included meta
         | 
| 754 | 
            +
                        meta.meta_type :view
         | 
| 755 | 
            +
                    end
         | 
| 756 | 
            +
             | 
| 739 757 | 
             
                    def pre_run
         | 
| 740 758 | 
             
                        super
         | 
| 741 759 | 
             
                        panel_template 'scaffold/view'
         | 
| @@ -761,6 +779,35 @@ module Engine2 | |
| 761 779 | 
             
                    end
         | 
| 762 780 | 
             
                end
         | 
| 763 781 |  | 
| 782 | 
            +
                module MetaDeleteSupport
         | 
| 783 | 
            +
                    include MetaModelSupport
         | 
| 784 | 
            +
             | 
| 785 | 
            +
                    def self.included meta
         | 
| 786 | 
            +
                        meta.http_method :delete
         | 
| 787 | 
            +
                        meta.meta_type :delete
         | 
| 788 | 
            +
                    end
         | 
| 789 | 
            +
             | 
| 790 | 
            +
                    def pre_run
         | 
| 791 | 
            +
                        super
         | 
| 792 | 
            +
                        action.parent.parent.*.menu(:item_menu).option :confirm_delete, icon: "trash", show: "action.selected_size() == 0", button_loc: false
         | 
| 793 | 
            +
                    end
         | 
| 794 | 
            +
                end
         | 
| 795 | 
            +
             | 
| 796 | 
            +
                module MetaBulkDeleteSupport
         | 
| 797 | 
            +
                    include MetaModelSupport
         | 
| 798 | 
            +
             | 
| 799 | 
            +
                    def self.included meta
         | 
| 800 | 
            +
                        meta.http_method :delete
         | 
| 801 | 
            +
                        meta.meta_type :bulk_delete
         | 
| 802 | 
            +
                    end
         | 
| 803 | 
            +
             | 
| 804 | 
            +
                    def pre_run
         | 
| 805 | 
            +
                        super
         | 
| 806 | 
            +
                        action.parent.parent.*.select_toggle_menu
         | 
| 807 | 
            +
                        action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_delete, icon: "trash", show: "action.selected_size() > 0"
         | 
| 808 | 
            +
                    end
         | 
| 809 | 
            +
                end
         | 
| 810 | 
            +
             | 
| 764 811 | 
             
                (FormRendererPostProcessors ||= {}).merge!(
         | 
| 765 812 | 
             
                    boolean: lambda{|meta, field, info|
         | 
| 766 813 | 
             
                        meta.info[field][:render].merge! true_value: info[:true_value], false_value: info[:false_value]
         | 
| @@ -2,7 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module Engine2
         | 
| 4 4 | 
             
                class DeleteMetaBase < Meta
         | 
| 5 | 
            -
                    include MetaModelSupport
         | 
| 6 5 |  | 
| 7 6 | 
             
                    def invoke_delete_db handler, ids
         | 
| 8 7 | 
             
                        begin
         | 
| @@ -40,13 +39,7 @@ module Engine2 | |
| 40 39 | 
             
                end
         | 
| 41 40 |  | 
| 42 41 | 
             
                class DeleteMeta < DeleteMetaBase
         | 
| 43 | 
            -
                     | 
| 44 | 
            -
                    meta_type :delete
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                    def pre_run
         | 
| 47 | 
            -
                        super
         | 
| 48 | 
            -
                        action.parent.parent.*.menu(:item_menu).option :confirm_delete, icon: "trash", show: "action.selected_size() == 0", button_loc: false
         | 
| 49 | 
            -
                    end
         | 
| 42 | 
            +
                    include MetaDeleteSupport
         | 
| 50 43 |  | 
| 51 44 | 
             
                    def invoke handler
         | 
| 52 45 | 
             
                        handler.permit id = handler.params[:id]
         | 
| @@ -55,13 +48,7 @@ module Engine2 | |
| 55 48 | 
             
                end
         | 
| 56 49 |  | 
| 57 50 | 
             
                class BulkDeleteMeta < DeleteMetaBase
         | 
| 58 | 
            -
                     | 
| 59 | 
            -
                    meta_type :bulk_delete
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                    def pre_run
         | 
| 62 | 
            -
                        super
         | 
| 63 | 
            -
                        action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_delete, icon: "trash", show: "action.selected_size() > 0"
         | 
| 64 | 
            -
                    end
         | 
| 51 | 
            +
                    include MetaBulkDeleteSupport
         | 
| 65 52 |  | 
| 66 53 | 
             
                    def invoke handler
         | 
| 67 54 | 
             
                        ids = handler.param_to_json(:ids)
         | 
| @@ -12,7 +12,7 @@ module Engine2 | |
| 12 12 | 
             
                                option :inspect_modal, icon: :wrench, button_loc: false # , show: "action.logged_on"
         | 
| 13 13 |  | 
| 14 14 | 
             
                                option :logout_form, icon: :"log-out" # , show: "action.logged_on"
         | 
| 15 | 
            -
                                option :login_form, icon: :"log-in" # , show: "!action.logged_on"
         | 
| 15 | 
            +
                                option :login_form, icon: :"log-in", disabled: 'action.action_pending' # , show: "!action.logged_on"
         | 
| 16 16 | 
             
                            end
         | 
| 17 17 |  | 
| 18 18 | 
             
                            @meta_type = :infra
         | 
| @@ -249,7 +249,6 @@ module Engine2 | |
| 249 249 |  | 
| 250 250 | 
             
                class LoginMeta < Meta
         | 
| 251 251 | 
             
                    include MetaApproveSupport
         | 
| 252 | 
            -
                    http_method :post
         | 
| 253 252 | 
             
                    meta_type :login
         | 
| 254 253 |  | 
| 255 254 | 
             
                    def after_approve handler, record
         | 
| @@ -113,6 +113,7 @@ module Engine2 | |
| 113 113 |  | 
| 114 114 | 
             
                    def pre_run
         | 
| 115 115 | 
             
                        super
         | 
| 116 | 
            +
                        action.parent.parent.*.select_toggle_menu
         | 
| 116 117 | 
             
                        action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_unlink, icon: "minus", show: "action.selected_size() > 0", button_loc: false
         | 
| 117 118 | 
             
                    end
         | 
| 118 119 |  | 
| @@ -155,7 +155,7 @@ module Engine2 | |
| 155 155 | 
             
                    meta_type :star_to_many_list
         | 
| 156 156 | 
             
                    def pre_run
         | 
| 157 157 | 
             
                        super
         | 
| 158 | 
            -
                        panel_title "#{ | 
| 158 | 
            +
                        panel_title "#{:list.icon} #{LOCS[assets[:assoc][:name]]}"
         | 
| 159 159 | 
             
                    end
         | 
| 160 160 |  | 
| 161 161 | 
             
                    # def decode_panel_title handler
         | 
| @@ -177,10 +177,11 @@ module Engine2 | |
| 177 177 | 
             
                        handler.permit parent = handler.params[:parent_id]
         | 
| 178 178 | 
             
                        model = assets[:model]
         | 
| 179 179 | 
             
                        assoc = assets[:assoc]
         | 
| 180 | 
            +
                        parent_keys = split_keys(parent)
         | 
| 180 181 | 
             
                        case assoc[:type]
         | 
| 181 182 | 
             
                        when :one_to_many
         | 
| 182 183 | 
             
                            keys = assoc[:keys]
         | 
| 183 | 
            -
                            condition =  | 
| 184 | 
            +
                            condition = parent_keys.all?(&:empty?) ? false : Hash[keys.map{|k| k.qualify(model.table_name)}.zip(parent_keys)]
         | 
| 184 185 | 
             
                            if handler.params[:negate]
         | 
| 185 186 | 
             
                                query = query.exclude(condition)
         | 
| 186 187 | 
             
                                query = query.or(Hash[keys.zip([nil])]) if keys.all?{|k|model.db_schema[k][:allow_null] == true} # type_info[:required] ?
         | 
| @@ -194,7 +195,7 @@ module Engine2 | |
| 194 195 | 
             
                            l_keys = assoc[:left_keys].map{|k| k.qualify(j_table)}
         | 
| 195 196 | 
             
                            r_keys = assoc[:right_keys].map{|k| k.qualify(j_table)}
         | 
| 196 197 | 
             
                            r_keys_vals = Hash[r_keys.zip(q_pk)]
         | 
| 197 | 
            -
                            l_keys_vals =  | 
| 198 | 
            +
                            l_keys_vals = parent_keys.all?(&:empty?) ? false : Hash[l_keys.zip(parent_keys)]
         | 
| 198 199 |  | 
| 199 200 | 
             
                            if handler.params[:negate]
         | 
| 200 201 | 
             
                                query.exclude(model.db[j_table].select(nil).where(r_keys_vals, l_keys_vals).exists)
         | 
| @@ -4,7 +4,6 @@ module Engine2 | |
| 4 4 |  | 
| 5 5 | 
             
                class SaveMeta < Meta
         | 
| 6 6 | 
             
                    include MetaApproveSupport
         | 
| 7 | 
            -
                    http_method :post
         | 
| 8 7 |  | 
| 9 8 | 
             
                    def validate_and_approve handler, record, json
         | 
| 10 9 | 
             
                        record.skip_save_refresh = true
         | 
| @@ -28,7 +27,7 @@ module Engine2 | |
| 28 27 | 
             
                end
         | 
| 29 28 |  | 
| 30 29 | 
             
                class InsertMeta < SaveMeta
         | 
| 31 | 
            -
                    meta_type : | 
| 30 | 
            +
                    meta_type :approve
         | 
| 32 31 | 
             
                    def allocate_record handler, json
         | 
| 33 32 | 
             
                        record = super(handler, json)
         | 
| 34 33 | 
             
                        record.instance_variable_set(:"@new", true)
         | 
| @@ -40,7 +39,7 @@ module Engine2 | |
| 40 39 | 
             
                end
         | 
| 41 40 |  | 
| 42 41 | 
             
                class UpdateMeta < SaveMeta
         | 
| 43 | 
            -
                    meta_type : | 
| 42 | 
            +
                    meta_type :approve
         | 
| 44 43 | 
             
                    def allocate_record handler, json
         | 
| 45 44 | 
             
                        record = super(handler, json)
         | 
| 46 45 | 
             
                        model = assets[:model]
         | 
| @@ -48,16 +47,4 @@ module Engine2 | |
| 48 47 | 
             
                        record
         | 
| 49 48 | 
             
                    end
         | 
| 50 49 | 
             
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                module TimeStampMeta
         | 
| 53 | 
            -
                    def before_approve handler, record
         | 
| 54 | 
            -
                        super
         | 
| 55 | 
            -
                        puts "before approve"
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                    def after_approve handler, record
         | 
| 59 | 
            -
                        super
         | 
| 60 | 
            -
                        puts "after approve"
         | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
                end
         | 
| 63 50 | 
             
            end
         | 
    
        data/lib/engine2/model.rb
    CHANGED
    
    | @@ -7,28 +7,25 @@ module Engine2 | |
| 7 7 | 
             
                    attr_reader :before_save_processors, :after_save_processors, :before_destroy_processors, :after_destroy_processors
         | 
| 8 8 | 
             
                    attr_reader :validation_in_transaction
         | 
| 9 9 |  | 
| 10 | 
            -
                     | 
| 11 | 
            -
                         | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                                @after_destroy_processors = nil
         | 
| 28 | 
            -
                                @type_info_synchronized = nil
         | 
| 29 | 
            -
                            end
         | 
| 30 | 
            -
                            cls.setup_schema
         | 
| 10 | 
            +
                    def self.extended cls
         | 
| 11 | 
            +
                        models = cls.db.models
         | 
| 12 | 
            +
                        raise E2Error.new("Model '#{cls.name}' already defined") if models[cls.name.to_sym]
         | 
| 13 | 
            +
                        models[cls.name.to_sym] = cls
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        cls.instance_eval do
         | 
| 16 | 
            +
                            @many_to_one_associations = association_reflections.select{|n, a| a[:type] == :many_to_one}
         | 
| 17 | 
            +
                            @one_to_many_associations = association_reflections.select{|n, a| a[:type] == :one_to_many}
         | 
| 18 | 
            +
                            @many_to_many_associations = association_reflections.select{|n, a| a[:type] == :many_to_many}
         | 
| 19 | 
            +
                            # @one_to_one_associations = association_reflections.select{|n, a| a[:type] == :one_to_one}
         | 
| 20 | 
            +
                            @validation_in_transaction = nil
         | 
| 21 | 
            +
                            @before_save_processors = nil
         | 
| 22 | 
            +
                            @after_save_processors = nil
         | 
| 23 | 
            +
                            @around_save_processors = nil
         | 
| 24 | 
            +
                            @before_destroy_processors = nil
         | 
| 25 | 
            +
                            @after_destroy_processors = nil
         | 
| 26 | 
            +
                            @type_info_synchronized = nil
         | 
| 31 27 | 
             
                        end
         | 
| 28 | 
            +
                        cls.setup_schema
         | 
| 32 29 | 
             
                    end
         | 
| 33 30 |  | 
| 34 31 | 
             
                    def install_processors processors
         | 
| @@ -111,6 +108,7 @@ module Engine2 | |
| 111 108 |  | 
| 112 109 | 
             
                    def synchronize_type_info
         | 
| 113 110 | 
             
                        resolve_dependencies
         | 
| 111 | 
            +
                        verify_associations
         | 
| 114 112 | 
             
                        @before_save_processors = install_processors(BeforeSaveProcessors)
         | 
| 115 113 | 
             
                        @after_save_processors = install_processors(AfterSaveProcessors)
         | 
| 116 114 | 
             
                        @around_save_processors = {}
         | 
| @@ -119,6 +117,18 @@ module Engine2 | |
| 119 117 | 
             
                        @type_info_synchronized = true
         | 
| 120 118 | 
             
                    end
         | 
| 121 119 |  | 
| 120 | 
            +
                    def verify_associations
         | 
| 121 | 
            +
                        one_to_many_associations.each do |name, assoc|
         | 
| 122 | 
            +
                            other = Object.const_get(assoc[:class_name])
         | 
| 123 | 
            +
                            other_type_info = other.type_info
         | 
| 124 | 
            +
                            if other_keys = assoc[:keys]
         | 
| 125 | 
            +
                                other_keys.each do |key|
         | 
| 126 | 
            +
                                    raise E2Error.new("No key '#{key}' found in model '#{other}' being related from #{self}") unless other_type_info[key]
         | 
| 127 | 
            +
                                end
         | 
| 128 | 
            +
                            end
         | 
| 129 | 
            +
                        end
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
             | 
| 122 132 | 
             
                    def resolve_dependencies
         | 
| 123 133 | 
             
                        resolved = {}
         | 
| 124 134 | 
             
                        @type_info.each_pair do |name, info|
         | 
| @@ -133,7 +143,7 @@ module Engine2 | |
| 133 143 | 
             
                        deps = @type_info[name][:depends]
         | 
| 134 144 | 
             
                        deps.each do |e|
         | 
| 135 145 | 
             
                            if !resolved[e]
         | 
| 136 | 
            -
                                raise "Circular dependency for field '#{name}' in model '#{self}'" if seen.include?(e)
         | 
| 146 | 
            +
                                raise E2Error.new("Circular dependency for field '#{name}' in model '#{self}'") if seen.include?(e)
         | 
| 137 147 | 
             
                                resolve_dependency(e, resolved, seen)
         | 
| 138 148 | 
             
                            end
         | 
| 139 149 | 
             
                        end if deps
         | 
    
        data/lib/engine2/scheme.rb
    CHANGED
    
    | @@ -6,31 +6,23 @@ module Engine2 | |
| 6 6 | 
             
                    VIEW ||= {view: true}.freeze
         | 
| 7 7 | 
             
                    LINK ||= {star_to_many_link: true, view: true, star_to_many_unlink: true}.freeze # star_to_many_bulk_unlink: true
         | 
| 8 8 |  | 
| 9 | 
            -
                    attr_reader : | 
| 9 | 
            +
                    attr_reader :builtin, :user
         | 
| 10 10 | 
             
                    def initialize
         | 
| 11 11 | 
             
                        @builtin = {}
         | 
| 12 | 
            -
                        @ | 
| 12 | 
            +
                        @user = {}
         | 
| 13 13 | 
             
                    end
         | 
| 14 14 |  | 
| 15 15 | 
             
                    def define_scheme name, &blk
         | 
| 16 | 
            -
                        schemes = Engine2:: | 
| 17 | 
            -
                        raise "Scheme '#{name}' already defined" if schemes[name]
         | 
| 16 | 
            +
                        schemes = Engine2::core_loaded ? @user : @builtin
         | 
| 17 | 
            +
                        raise E2Error.new("Scheme '#{name}' already defined") if schemes[name]
         | 
| 18 18 | 
             
                        schemes[name] = blk
         | 
| 19 19 | 
             
                    end
         | 
| 20 20 |  | 
| 21 | 
            -
                    def  | 
| 22 | 
            -
                         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                    def [] name
         | 
| 26 | 
            -
                        scheme = @schemes[name]
         | 
| 27 | 
            -
                        raise E2Error.new("Scheme #{name} not found") unless scheme
         | 
| 21 | 
            +
                    def [] name, raise = true
         | 
| 22 | 
            +
                        scheme = @builtin[name] || @user[name]
         | 
| 23 | 
            +
                        raise E2Error.new("Scheme #{name} not found") if !scheme && raise
         | 
| 28 24 | 
             
                        scheme
         | 
| 29 25 | 
             
                    end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                    def merge!
         | 
| 32 | 
            -
                        @schemes.merge!(@builtin){|n| raise E2Error.new("Scheme collision: #{n}")}
         | 
| 33 | 
            -
                    end
         | 
| 34 26 | 
             
                end
         | 
| 35 27 |  | 
| 36 28 | 
             
                SCHEMES ||= Schemes.new
         | 
    
        data/lib/engine2/type_info.rb
    CHANGED
    
    | @@ -209,8 +209,8 @@ module Engine2 | |
| 209 209 | 
             
                            info[:multiple] = multiple
         | 
| 210 210 | 
             
                            info[:table] = table
         | 
| 211 211 | 
             
                            info[:store] = store
         | 
| 212 | 
            -
                            info[:store][:upload] ||= "#{ | 
| 213 | 
            -
                            info[:store][:files] ||= "#{ | 
| 212 | 
            +
                            info[:store][:upload] ||= "#{Engine2::app}/store/upload"
         | 
| 213 | 
            +
                            info[:store][:files] ||= "#{Engine2::app}/store/files"
         | 
| 214 214 | 
             
                            info[:transaction] = true
         | 
| 215 215 | 
             
                        end
         | 
| 216 216 | 
             
                    end
         | 
| @@ -265,9 +265,8 @@ module Engine2 | |
| 265 265 | 
             
                    end
         | 
| 266 266 |  | 
| 267 267 | 
             
                    def foreign_blob_store_field assoc_name, name, name_field, mime_field
         | 
| 268 | 
            -
                        assoc = @model. | 
| 269 | 
            -
                        raise E2Error.new(" | 
| 270 | 
            -
                        raise E2Error.new("Association '#{assoc_name}' in model '#{@mode}' is not of type many_to_one") unless assoc[:type] == :many_to_one
         | 
| 268 | 
            +
                        assoc = @model.many_to_one_associations[assoc_name]
         | 
| 269 | 
            +
                        raise E2Error.new("'many_to_one' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
         | 
| 271 270 | 
             
                        define_field :"#{assoc[:key]}_blob", :foreign_blob_store do |info|
         | 
| 272 271 | 
             
                            info[:assoc_name] = assoc_name
         | 
| 273 272 | 
             
                            info[:bytes_field] = name
         | 
| @@ -278,9 +277,8 @@ module Engine2 | |
| 278 277 | 
             
                    end
         | 
| 279 278 |  | 
| 280 279 | 
             
                    def many_to_one_field assoc_name
         | 
| 281 | 
            -
                        assoc = @model. | 
| 282 | 
            -
                        raise E2Error.new(" | 
| 283 | 
            -
                        raise E2Error.new("Association '#{assoc_name}' in model '#{@mode}' is not of type many_to_one") unless assoc[:type] == :many_to_one
         | 
| 280 | 
            +
                        assoc = @model.many_to_one_associations[assoc_name]
         | 
| 281 | 
            +
                        raise E2Error.new("'many_to_one' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
         | 
| 284 282 | 
             
                        keys = assoc[:keys]
         | 
| 285 283 | 
             
                        modify_field keys.first do |info|
         | 
| 286 284 | 
             
                            info[:type] = :many_to_one
         | 
| @@ -290,9 +288,8 @@ module Engine2 | |
| 290 288 | 
             
                    end
         | 
| 291 289 |  | 
| 292 290 | 
             
                    def star_to_many_field assoc_name
         | 
| 293 | 
            -
                        assoc = @model. | 
| 294 | 
            -
                        raise E2Error.new(" | 
| 295 | 
            -
                        raise E2Error.new("Association '#{assoc_name}' in model '#{@model}' is not of type *_to_many") unless [:one_to_many, :many_to_many].include?(assoc[:type])
         | 
| 291 | 
            +
                        assoc = @model.one_to_many_associations[assoc_name] || @model.many_to_many_associations[assoc_name]
         | 
| 292 | 
            +
                        raise E2Error.new("'*_to_many' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
         | 
| 296 293 | 
             
                        define_field assoc_name, :string do |info|
         | 
| 297 294 | 
             
                            info[:type] = :star_to_many_field
         | 
| 298 295 | 
             
                            info[:keys] = assoc[:keys]
         | 
| @@ -309,7 +306,7 @@ module Engine2 | |
| 309 306 | 
             
                                    # list.map{|k, v| {id: k, value: v}}
         | 
| 310 307 | 
             
                                    list.to_a
         | 
| 311 308 | 
             
                                else
         | 
| 312 | 
            -
                                    raise E2Error.new("type not supported for list_select modifier for field #{name}")
         | 
| 309 | 
            +
                                    raise E2Error.new("type '#{list.class}' not supported for list_select modifier for field #{name}")
         | 
| 313 310 | 
             
                            end
         | 
| 314 311 | 
             
                            info[:validations][:list_select] = true
         | 
| 315 312 | 
             
                        end
         | 
| @@ -317,7 +314,7 @@ module Engine2 | |
| 317 314 |  | 
| 318 315 | 
             
                    def decode name, dinfo = {form: {scaffold: true}, search: {scaffold: true}}
         | 
| 319 316 | 
             
                        modify_field name do |info|
         | 
| 320 | 
            -
                            raise E2Error.new("Field type of #{name} needs to be  | 
| 317 | 
            +
                            raise E2Error.new("Field type of '#{name}' in model '#{@model}' needs to be 'many_to_one'") unless info[:type] == :many_to_one
         | 
| 321 318 | 
             
                            dec = info[:decode] ||= {}
         | 
| 322 319 | 
             
                            dec[:search].clear if dinfo[:search] && dec[:search]
         | 
| 323 320 | 
             
                            dec[:form].clear if dinfo[:form] && dec[:form]
         | 
    
        data/lib/engine2/version.rb
    CHANGED
    
    
    
        data/views/engine2.coffee
    CHANGED
    
    | @@ -279,14 +279,14 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm | |
| 279 279 | 
             
                    error: (title, msg, html) ->
         | 
| 280 280 | 
             
                        body = if html then msg else "<div class='alert alert-danger'>#{msg}</div>"
         | 
| 281 281 | 
             
                        clazz = if html then "modal-huge" else "modal-large"
         | 
| 282 | 
            -
                        @show meta: panel: (panel_template: "close_m", template_string: body, title: title, class: clazz) # message: msg,
         | 
| 282 | 
            +
                        @show meta: panel: (panel_template: "close_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
         | 
| 283 283 |  | 
| 284 284 | 
             
                    confirm: (title, msg, action) ->
         | 
| 285 285 | 
             
                        body = "<div class='alert alert-warning'>#{msg}</div>"
         | 
| 286 286 | 
             
                        clazz = "modal-large"
         | 
| 287 287 | 
             
                        @show
         | 
| 288 288 | 
             
                            confirm: action,
         | 
| 289 | 
            -
                            meta: panel: (panel_template: "confirm_m", template_string: body, title: title, class: clazz) # message: msg,
         | 
| 289 | 
            +
                            meta: panel: (panel_template: "confirm_m", template_string: body, title: title, class: clazz, footer: true) # message: msg,
         | 
| 290 290 |  | 
| 291 291 | 
             
            .directive 'e2Modal', ($e2Modal) ->
         | 
| 292 292 | 
             
                restrict: 'E'
         | 
| @@ -301,7 +301,7 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm | |
| 301 301 | 
             
                            return if ev.defaultPrevented
         | 
| 302 302 | 
             
                            ev.preventDefault()
         | 
| 303 303 |  | 
| 304 | 
            -
                            panel = panel_template: attrs.panelTemplate, title: attrs.title, class: attrs.clazz
         | 
| 304 | 
            +
                            panel = panel_template: attrs.panelTemplate, title: attrs.title, class: attrs.clazz, footer: true
         | 
| 305 305 | 
             
                            if obody then panel.template_string = obody.outerHTML else panel.template = attrs.template
         | 
| 306 306 | 
             
                            action = meta: (panel: panel), scope: -> scope
         | 
| 307 307 | 
             
                            _.assign(action, args)
         | 
| @@ -386,12 +386,16 @@ angular.module('Engine2', ['ngRoute', 'ngSanitize', 'ngAnimate', 'ngCookies', 'm | |
| 386 386 | 
             
                        selection = scope.action.selection
         | 
| 387 387 | 
             
                        out = ''
         | 
| 388 388 | 
             
                        _.each scope.action.entries, (e, i) ->
         | 
| 389 | 
            -
                            out += if selection then "<tr ng-class='action.selected_class(#{i})' class='tr_hover' ng-click='action.select(#{i}, $event)'>" else | 
| 389 | 
            +
                            out += if selection then "<tr ng-class='action.selected_class(#{i})' class='tr_hover' ng-click='action.select(#{i}, $event)'>" else
         | 
| 390 | 
            +
                                row_cls = e.$row_info?.class
         | 
| 391 | 
            +
                                if row_cls then "<tr class=\"#{row_cls}\">" else "<tr>"
         | 
| 390 392 | 
             
                            out += "<td>"
         | 
| 391 | 
            -
                            out += "<div e2-button-set='action.meta.menus.item_menu' index='#{i}'></div>" if meta.config.show_item_menu | 
| 393 | 
            +
                            out += "<div e2-button-set='action.meta.menus.item_menu' index='#{i}'></div>" if meta.config.show_item_menu
         | 
| 392 394 | 
             
                            out += "</td>"
         | 
| 393 | 
            -
                             | 
| 394 | 
            -
             | 
| 395 | 
            +
                            _.each meta.fields, (f) ->
         | 
| 396 | 
            +
                                out += if col_cls = meta.info[f].column_class then "<td class='#{col_cls}'>" else "<td>"
         | 
| 397 | 
            +
                                out += scope.action.list_cell(e, f) ? ''
         | 
| 398 | 
            +
                                out += "</td>"
         | 
| 395 399 | 
             
                            out += "</tr>"
         | 
| 396 400 |  | 
| 397 401 | 
             
                        elem.empty()
         | 
    
        data/views/engine2actions.coffee
    CHANGED
    
    | @@ -128,9 +128,11 @@ angular.module('Engine2') | |
| 128 128 |  | 
| 129 129 | 
             
                    pre_invoke: ->
         | 
| 130 130 | 
             
                        @parent().action_pending = true
         | 
| 131 | 
            +
                        @action_pending = true
         | 
| 131 132 | 
             
                        # @parent().parent().action_pending = true if @parent().parent()
         | 
| 132 133 | 
             
                    post_invoke: ->
         | 
| 133 134 | 
             
                        delete @parent().action_pending # = false
         | 
| 135 | 
            +
                        delete @action_pending
         | 
| 134 136 | 
             
                        # @parent().parent().action_pending = false if @parent().parent()
         | 
| 135 137 | 
             
                    invoke: ->
         | 
| 136 138 | 
             
                        args = arguments
         | 
| @@ -282,7 +284,7 @@ angular.module('Engine2') | |
| 282 284 |  | 
| 283 285 | 
             
                    traverse: (routes) ->
         | 
| 284 286 | 
             
                        menu_tmpl = _.template("<li><a href='{{href}}'>{{icon}}{{aicon}} {{loc}}</a></li>")
         | 
| 285 | 
            -
                        menu_sub_tmpl = _.template("<li e2-drop-down='{{dropdown}}'><a href='javascript://'>{{icon}}{{aicon}}{{loc}}<span class='caret'></span></a></li>")
         | 
| 287 | 
            +
                        menu_sub_tmpl = _.template("<li e2-drop-down='{{dropdown}}'><a href='javascript://'>{{icon}}{{aicon}} {{loc}}<span class='caret'></span></a></li>")
         | 
| 286 288 | 
             
                        out = routes.map (route, i) ->
         | 
| 287 289 | 
             
                            if route.menu
         | 
| 288 290 | 
             
                                menu_sub_tmpl
         | 
| @@ -565,6 +567,7 @@ angular.module('Engine2') | |
| 565 567 | 
             
                        super()
         | 
| 566 568 | 
             
                        @decode_field = @scope().f
         | 
| 567 569 | 
             
                        @dinfo = @parentp().meta.info[@decode_field]
         | 
| 570 | 
            +
                        throw "Primary and foreign key list lengths dont match: [#{@meta.primary_fields}] and [#{@dinfo.fields}]" unless @meta.primary_fields.length == @dinfo.fields.length
         | 
| 568 571 | 
             
                        @scope().$on "search_reset", => @clean()
         | 
| 569 572 |  | 
| 570 573 | 
             
                    if_fk_values: (f) ->
         | 
    
        data/views/infra/inspect.slim
    CHANGED
    
    
    
        data/views/modals/close_m.slim
    CHANGED
    
    
    
        data/views/modals/confirm_m.slim
    CHANGED
    
    
    
        data/views/modals/empty_m.slim
    CHANGED
    
    
    
        data/views/modals/menu_m.slim
    CHANGED
    
    
    
        data/views/modals/yes_no_m.slim
    CHANGED
    
    
    
        data/views/panels/menu_m.slim
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 | 
             
                h4.modal-title ng-bind-html="action.meta.panel.title"
         | 
| 4 4 | 
             
              .panel-body
         | 
| 5 5 | 
             
                | modal-content-to-replace
         | 
| 6 | 
            -
              .panel-footer
         | 
| 6 | 
            +
              .panel-footer ng-if="::action.meta.panel.footer"
         | 
| 7 7 | 
             
                // .loader.pull-left: img src="img/ajax-loader.gif"
         | 
| 8 8 | 
             
                div e2-button-set="action.meta.menus.panel_menu"
         | 
| 9 9 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: engine2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - lopex
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-05-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              requirement: !ruby/object:Gem::Requirement
         |