cpee-model-management 1.0.12 → 1.0.17
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/cpee-model-management.gemspec +2 -1
- data/lib/cpee-model-management/commit.rb +1 -3
- data/lib/cpee-model-management/implementation.rb +83 -46
- data/server/model.xml +4 -0
- data/server/moma.conf +1 -0
- data/server/testset.xml +4 -0
- data/tools/cpee-moma +26 -4
- data/ui/css/design.css +12 -0
- data/ui/design.js +239 -0
- data/ui/index.html +21 -4
- data/ui/js/design.js +45 -14
- metadata +24 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d3a70760a747bb5dd295cac87766307d1d3775767af440e3090d2e108757837d
         | 
| 4 | 
            +
              data.tar.gz: ed59f63e220bb3c6fb8e096ce21ee41f5542c59fff051e48c0d04ff7ee8ccd79
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fd9497631d3a6d95a98b0f829211aa13712626bf1aac340a4bdb19eb80ee1b26e624bfa3e5766d1f8cceeb37d215f75b8c05478566802daf667a297eb4c4b075
         | 
| 7 | 
            +
              data.tar.gz: 04c947de228d452fa277b01213c0a4a5deaa8d47bd3b357a94593c350c1ae15a728c470a38023a4298d9a2db808580bfe187cb1fe19dcf9bd4b634819a25a0a2
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name             = "cpee-model-management"
         | 
| 3 | 
            -
              s.version          = "1.0. | 
| 3 | 
            +
              s.version          = "1.0.17"
         | 
| 4 4 | 
             
              s.platform         = Gem::Platform::RUBY
         | 
| 5 5 | 
             
              s.license          = "LGPL-3.0"
         | 
| 6 6 | 
             
              s.summary          = "(Lifecycle) manage your process models in a directory or git repo."
         | 
| @@ -22,4 +22,5 @@ Gem::Specification.new do |s| | |
| 22 22 |  | 
| 23 23 | 
             
              s.add_runtime_dependency 'riddl', '~> 0.99'
         | 
| 24 24 | 
             
              s.add_runtime_dependency 'json', '~> 2.1'
         | 
| 25 | 
            +
              s.add_runtime_dependency 'cpee', '~> 2.1', '>= 2.1.7'
         | 
| 25 26 | 
             
            end
         | 
| @@ -7,8 +7,6 @@ new = File.basename(new) | |
| 7 7 | 
             
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}"             2>/dev/null`
         | 
| 8 8 | 
             
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}.active"      2>/dev/null`
         | 
| 9 9 | 
             
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}.active-uuid" 2>/dev/null`
         | 
| 10 | 
            -
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}. | 
| 11 | 
            -
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}.creator"     2>/dev/null`
         | 
| 12 | 
            -
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}.stage"       2>/dev/null`
         | 
| 10 | 
            +
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple add "#{new}.attrs"      2>/dev/null`
         | 
| 13 11 | 
             
            `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple commit -m "#{author.gsub(/"/,"'")}"`
         | 
| 14 12 | 
             
            `GIT_TERMINAL_PROMPT=0 git push` rescue nil
         | 
| @@ -24,6 +24,7 @@ require 'riddl/protocols/utils' | |
| 24 24 | 
             
            require 'fileutils'
         | 
| 25 25 | 
             
            require 'pathname'
         | 
| 26 26 | 
             
            require 'shellwords'
         | 
| 27 | 
            +
            require 'securerandom'
         | 
| 27 28 |  | 
| 28 29 | 
             
            module CPEE
         | 
| 29 30 | 
             
              module ModelManagement
         | 
| @@ -37,12 +38,10 @@ module CPEE | |
| 37 38 | 
             
                  p2 = Pathname.new(File.dirname(new))
         | 
| 38 39 | 
             
                  told = File.basename(old)
         | 
| 39 40 | 
             
                  tnew = File.join(p1.relative_path_from(p1).to_s,File.basename(new))
         | 
| 40 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told}"                      "#{tnew}" | 
| 41 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active'}" | 
| 42 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active-uuid'}" | 
| 43 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told + '. | 
| 44 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told + '.creator'}"         "#{tnew + '.creator'}" 2>/dev/null`
         | 
| 45 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told + '.stage'}"           "#{tnew + '.stage'}"   2>/dev/null`
         | 
| 41 | 
            +
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told}"                      "#{tnew}"            2>/dev/null`
         | 
| 42 | 
            +
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active'}"                               2>/dev/null`
         | 
| 43 | 
            +
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active-uuid'}"                          2>/dev/null`
         | 
| 44 | 
            +
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv     "#{told + '.attrs'}"          "#{tnew + '.attrs'}"  2>/dev/null`
         | 
| 46 45 | 
             
                  Dir.chdir(cdir)
         | 
| 47 46 | 
             
                  CPEE::ModelManagement::fs_mv(models,old,new) # fallback
         | 
| 48 47 | 
             
                end
         | 
| @@ -54,9 +53,7 @@ module CPEE | |
| 54 53 | 
             
                   FileUtils.rm_rf(tnew)
         | 
| 55 54 | 
             
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}.active"      2>/dev/null`
         | 
| 56 55 | 
             
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}.active-uuid" 2>/dev/null`
         | 
| 57 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}. | 
| 58 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}.creator"     2>/dev/null`
         | 
| 59 | 
            -
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}.stage"       2>/dev/null`
         | 
| 56 | 
            +
                  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{tnew}.attrs"      2>/dev/null`
         | 
| 60 57 | 
             
                  Dir.chdir(cdir)
         | 
| 61 58 | 
             
                  CPEE::ModelManagement::fs_rm(models,new) # fallback
         | 
| 62 59 | 
             
                end
         | 
| @@ -80,9 +77,7 @@ module CPEE | |
| 80 77 | 
             
                  FileUtils.mv(fname,fnname) rescue nil
         | 
| 81 78 | 
             
                  File.delete(fname + '.active',fnname + '.active') rescue nil
         | 
| 82 79 | 
             
                  File.delete(fname + '.active-uuid',fnname + '.active-uuid') rescue nil
         | 
| 83 | 
            -
                  FileUtils.mv(fname + '. | 
| 84 | 
            -
                  FileUtils.mv(fname + '.creator',fnname + '.creator') rescue nil
         | 
| 85 | 
            -
                  FileUtils.mv(fname + '.stage',fnname + '.stage') rescue nil
         | 
| 80 | 
            +
                  FileUtils.mv(fname + '.attrs',fnname + '.attrs') rescue nil
         | 
| 86 81 | 
             
                end
         | 
| 87 82 | 
             
                def self::fs_cp(models,old,new)
         | 
| 88 83 | 
             
                  fname = File.join(models,old)
         | 
| @@ -90,18 +85,14 @@ module CPEE | |
| 90 85 | 
             
                  FileUtils.cp(fname,fnname)
         | 
| 91 86 | 
             
                  File.delete(fname + '.active',fnname + '.active') rescue nil
         | 
| 92 87 | 
             
                  File.delete(fname + '.active-uuid',fnname + '.active-uuid') rescue nil
         | 
| 93 | 
            -
                  FileUtils.cp(fname + '. | 
| 94 | 
            -
                  FileUtils.cp(fname + '.creator',fnname + '.creator') rescue nil
         | 
| 95 | 
            -
                  FileUtils.cp(fname + '.stage',fnname + '.stage') rescue nil
         | 
| 88 | 
            +
                  FileUtils.cp(fname + '.attrs',fnname + '.attrs') rescue nil
         | 
| 96 89 | 
             
                end
         | 
| 97 90 | 
             
                def self::fs_rm(models,new)
         | 
| 98 91 | 
             
                  fname = File.join(models,new)
         | 
| 99 92 | 
             
                  FileUtils.rm_rf(fname)
         | 
| 100 93 | 
             
                  File.delete(fname + '.active') rescue nil
         | 
| 101 94 | 
             
                  File.delete(fname + '.active-uuid') rescue nil
         | 
| 102 | 
            -
                  File.delete(fname + '. | 
| 103 | 
            -
                  File.delete(fname + '.creator') rescue nil
         | 
| 104 | 
            -
                  File.delete(fname + '.stage') rescue nil
         | 
| 95 | 
            +
                  File.delete(fname + '.attrs') rescue nil
         | 
| 105 96 | 
             
                end
         | 
| 106 97 | 
             
                def self::fs_shift(models,new)
         | 
| 107 98 | 
             
                  fname = File.join(models,new)
         | 
| @@ -168,14 +159,16 @@ module CPEE | |
| 168 159 | 
             
                    if  op == 'delete'
         | 
| 169 160 | 
             
                      { :op => op, :type => :dir, :name => File.basename(f) }
         | 
| 170 161 | 
             
                    else
         | 
| 171 | 
            -
                       | 
| 162 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 163 | 
            +
                      { :op => op, :type => :dir, :name => File.basename(f), :creator => attrs['creator'], :date => File.mtime(f).xmlschema }
         | 
| 172 164 | 
             
                    end
         | 
| 173 165 | 
             
                  else
         | 
| 174 166 | 
             
                    if  op == 'delete'
         | 
| 175 167 | 
             
                      { :op => op, :type => :file, :name => f.sub(Regexp.compile(File.join(models,'/')),'') }
         | 
| 176 168 | 
             
                    else
         | 
| 177 | 
            -
                       | 
| 178 | 
            -
                       | 
| 169 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 170 | 
            +
                      fstage = attrs['design_stage'] rescue 'draft'
         | 
| 171 | 
            +
                      { :op => op, :type => :file, :name => f.sub(Regexp.compile(File.join(models,'/')),''), :creator => attrs['creator'], :author => attrs['author'], :stage => fstage, :date => File.mtime(f).xmlschema }
         | 
| 179 172 | 
             
                    end
         | 
| 180 173 | 
             
                  end
         | 
| 181 174 | 
             
                  what[:source] = s.sub(/models\//,'') unless s.nil?
         | 
| @@ -192,12 +185,13 @@ module CPEE | |
| 192 185 | 
             
                    stage = [@p[0]&.value] || ['draft']
         | 
| 193 186 | 
             
                    stage << views[stage[0]] if views && views[stage[0]]
         | 
| 194 187 |  | 
| 195 | 
            -
             | 
| 196 188 | 
             
                    names = Dir.glob(File.join(models,where,'*.dir')).map do |f|
         | 
| 197 | 
            -
                       | 
| 189 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 190 | 
            +
                      { :type => :dir, :name => File.basename(f), :creator => attrs['creator'], :date => File.mtime(f).xmlschema }
         | 
| 198 191 | 
             
                    end.compact.uniq.sort_by{ |e| e[:name] } + Dir.glob(File.join(models,where,'*.xml')).map do |f|
         | 
| 199 | 
            -
                       | 
| 200 | 
            -
                       | 
| 192 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 193 | 
            +
                      fstage = attrs['design_stage'] rescue 'draft'
         | 
| 194 | 
            +
                      { :type => :file, :name => File.basename(f), :creator => attrs['creator'], :author => attrs['author'], :guarded => attrs['guarded'], :guarded_id => attrs['guarded_id'], :stage => fstage, :date => File.mtime(f).xmlschema } if stage.include?(fstage)
         | 
| 201 195 | 
             
                    end.compact.uniq.sort_by{ |e| e[:name] }
         | 
| 202 196 |  | 
| 203 197 | 
             
                    Riddl::Parameter::Complex.new('list','application/json',JSON::pretty_generate(names))
         | 
| @@ -211,10 +205,12 @@ module CPEE | |
| 211 205 | 
             
                    stage << views[stage[0]] if views && views[stage[0]]
         | 
| 212 206 |  | 
| 213 207 | 
             
                    names = Dir.glob(File.join(models,'*.dir/*.xml')).map do |f|
         | 
| 214 | 
            -
                       | 
| 208 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 209 | 
            +
                      { :type => :file, :name => File.join(File.basename(File.dirname(f)),File.basename(f)), :creator => attrs['creator'], :date => File.mtime(f).xmlschema }
         | 
| 215 210 | 
             
                    end.compact.uniq.sort_by{ |e| e[:name] } + Dir.glob(File.join(models,'*.xml')).map do |f|
         | 
| 216 | 
            -
                       | 
| 217 | 
            -
                       | 
| 211 | 
            +
                      attrs = JSON::load File.open(f + '.attrs')
         | 
| 212 | 
            +
                      fstage = attrs['design_stage'] rescue 'draft'
         | 
| 213 | 
            +
                      { :type => :file, :name => File.basename(f), :creator => attrs['creator'], :author => attrs['author'], :guarded => attrs['guarded'], :guarded_id => attrs['guarded_id'], :stage => fstage, :date => File.mtime(f).xmlschema } if stage.include?(fstage)
         | 
| 218 214 | 
             
                    end.compact.uniq.sort_by{ |e| e[:name] }
         | 
| 219 215 |  | 
| 220 216 | 
             
                    Riddl::Parameter::Complex.new('list','application/json',JSON::pretty_generate(names))
         | 
| @@ -240,6 +236,7 @@ module CPEE | |
| 240 236 | 
             
                    dn = CPEE::ModelManagement::get_dn @h['DN']
         | 
| 241 237 | 
             
                    author = dn['GN'] + ' ' + dn['SN']
         | 
| 242 238 |  | 
| 239 | 
            +
                    attrs = {}
         | 
| 243 240 | 
             
                    XML::Smart::modify(fname) do |doc|
         | 
| 244 241 | 
             
                      doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 245 242 | 
             
                      doc.find('/p:testset/p:attributes/p:author').each do |ele|
         | 
| @@ -251,9 +248,11 @@ module CPEE | |
| 251 248 | 
             
                      doc.find('/p:testset/p:attributes/p:theme').each do |ele|
         | 
| 252 249 | 
             
                        ele.text = themes[nstage] || 'model'
         | 
| 253 250 | 
             
                      end
         | 
| 251 | 
            +
                      attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 252 | 
            +
                        [e.qname.name,e.text]
         | 
| 253 | 
            +
                      end.to_h
         | 
| 254 254 | 
             
                    end
         | 
| 255 | 
            -
                    File.write(fname + '. | 
| 256 | 
            -
                    File.write(fname + '.stage',nstage)
         | 
| 255 | 
            +
                    File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 257 256 |  | 
| 258 257 | 
             
                    CPEE::ModelManagement::op author, 'shift', models, File.join('.', where, name + '.xml'), File.join('.', where, name + '.xml')
         | 
| 259 258 | 
             
                    CPEE::ModelManagement::notify conns, 'shift', models, fname, fname
         | 
| @@ -280,6 +279,7 @@ module CPEE | |
| 280 279 | 
             
                    dn = CPEE::ModelManagement::get_dn @h['DN']
         | 
| 281 280 | 
             
                    author = dn['GN'] + ' ' + dn['SN']
         | 
| 282 281 |  | 
| 282 | 
            +
                    attrs = {}
         | 
| 283 283 | 
             
                    XML::Smart::modify(fname) do |doc|
         | 
| 284 284 | 
             
                      doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 285 285 | 
             
                      doc.find('/p:testset/p:attributes/p:info').each do |ele|
         | 
| @@ -288,8 +288,11 @@ module CPEE | |
| 288 288 | 
             
                      doc.find('/p:testset/p:attributes/p:author').each do |ele|
         | 
| 289 289 | 
             
                        ele.text = author
         | 
| 290 290 | 
             
                      end
         | 
| 291 | 
            +
                      attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 292 | 
            +
                        [e.qname.name,e.text]
         | 
| 293 | 
            +
                      end.to_h
         | 
| 291 294 | 
             
                    end
         | 
| 292 | 
            -
                    File.write(fname + '. | 
| 295 | 
            +
                    File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 293 296 |  | 
| 294 297 | 
             
                    CPEE::ModelManagement::op author, 'mv', models, File.join('.', where, nname + '.xml'), File.join('.', where, name + '.xml')
         | 
| 295 298 | 
             
                    CPEE::ModelManagement::notify conns, 'rename', models, fnname, fname
         | 
| @@ -312,7 +315,23 @@ module CPEE | |
| 312 315 |  | 
| 313 316 | 
             
                    dn = CPEE::ModelManagement::get_dn @h['DN']
         | 
| 314 317 | 
             
                    author = dn['GN'] + ' ' + dn['SN']
         | 
| 315 | 
            -
             | 
| 318 | 
            +
             | 
| 319 | 
            +
                    attrs = JSON::load File.open(fname + '.attrs')
         | 
| 320 | 
            +
                    attrs['author'] = author
         | 
| 321 | 
            +
                    File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 322 | 
            +
             | 
| 323 | 
            +
                    Dir.glob(File.join(fname + '/*.xml')).each do |f|
         | 
| 324 | 
            +
                      XML::Smart::modify(f) do |doc|
         | 
| 325 | 
            +
                        doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 326 | 
            +
                        doc.find('/p:testset/p:attributes/p:design_dir').each do |ele|
         | 
| 327 | 
            +
                          ele.text = nname + '.dir'
         | 
| 328 | 
            +
                        end
         | 
| 329 | 
            +
                        attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 330 | 
            +
                          [e.qname.name,e.text]
         | 
| 331 | 
            +
                        end.to_h
         | 
| 332 | 
            +
                      end
         | 
| 333 | 
            +
                      File.write(f + '.attrs',JSON::pretty_generate(attrs))
         | 
| 334 | 
            +
                    end
         | 
| 316 335 |  | 
| 317 336 | 
             
                    CPEE::ModelManagement::op author, 'mv', models, File.join(nname + '.dir'), File.join(name + '.dir')
         | 
| 318 337 | 
             
                    CPEE::ModelManagement::notify conns, 'rename', models, fnname, fname
         | 
| @@ -338,8 +357,11 @@ module CPEE | |
| 338 357 |  | 
| 339 358 | 
             
                    Dir.mkdir(fname)
         | 
| 340 359 | 
             
                    FileUtils.touch(File.join(fname,'.gitignore'))
         | 
| 341 | 
            -
             | 
| 342 | 
            -
                    File. | 
| 360 | 
            +
             | 
| 361 | 
            +
                    attrs = JSON::load File.open(fname + '.attrs')
         | 
| 362 | 
            +
                    attrs['creator'] = creator
         | 
| 363 | 
            +
                    attrs['author'] = creator
         | 
| 364 | 
            +
                    File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 343 365 |  | 
| 344 366 | 
             
                    CPEE::ModelManagement::op creator, 'add', models, name + '.dir'
         | 
| 345 367 | 
             
                    CPEE::ModelManagement::notify conns, 'create', models, fname
         | 
| @@ -363,7 +385,8 @@ module CPEE | |
| 363 385 | 
             
                    source = @p[1] ? File.join(models,where,@p[1].value) : (templates[stage] ? templates[stage] : 'testset.xml')
         | 
| 364 386 | 
             
                    fname = File.join(models,where,name + '.xml')
         | 
| 365 387 |  | 
| 366 | 
            -
                     | 
| 388 | 
            +
                    attrs = JSON::load File.open(fname + '.attrs') rescue {}
         | 
| 389 | 
            +
                    stage = attrs['design_stage'] if stage.nil? && attrs['design_stage']
         | 
| 367 390 | 
             
                    stage = views[stage] if views && views[stage]
         | 
| 368 391 |  | 
| 369 392 | 
             
                    counter = 0
         | 
| @@ -375,6 +398,7 @@ module CPEE | |
| 375 398 | 
             
                    dn = CPEE::ModelManagement::get_dn @h['DN']
         | 
| 376 399 | 
             
                    creator = dn['GN'] + ' ' + dn['SN']
         | 
| 377 400 | 
             
                    FileUtils.cp(source,fname)
         | 
| 401 | 
            +
                    attrs = {}
         | 
| 378 402 | 
             
                    XML::Smart::modify(fname) do |doc|
         | 
| 379 403 | 
             
                      doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 380 404 | 
             
                      doc.find('/p:testset/p:attributes/p:info').each do |ele|
         | 
| @@ -389,15 +413,19 @@ module CPEE | |
| 389 413 | 
             
                      doc.find('/p:testset/p:attributes/p:design_dir').each do |ele|
         | 
| 390 414 | 
             
                        ele.text = where
         | 
| 391 415 | 
             
                      end
         | 
| 416 | 
            +
                      doc.find('/p:testset/p:attributes/p:model_uuid').each do |ele|
         | 
| 417 | 
            +
                        ele.text = SecureRandom.uuid
         | 
| 418 | 
            +
                      end
         | 
| 392 419 | 
             
                      if stage
         | 
| 393 420 | 
             
                        doc.find('/p:testset/p:attributes/p:design_stage').each do |ele|
         | 
| 394 421 | 
             
                          ele.text = stage
         | 
| 395 422 | 
             
                        end
         | 
| 396 423 | 
             
                      end
         | 
| 424 | 
            +
                      attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 425 | 
            +
                        [e.qname.name,e.text]
         | 
| 426 | 
            +
                      end.to_h
         | 
| 397 427 | 
             
                    end
         | 
| 398 | 
            -
                    File.write(fname + '. | 
| 399 | 
            -
                    File.write(fname + '.author',creator)
         | 
| 400 | 
            -
                    File.write(fname + '.stage',stage)
         | 
| 428 | 
            +
                    File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 401 429 |  | 
| 402 430 | 
             
                    CPEE::ModelManagement::op creator, 'add', models, File.join('.', where, name + '.xml')
         | 
| 403 431 | 
             
                    CPEE::ModelManagement::notify conns, 'create', models, fname
         | 
| @@ -492,13 +520,17 @@ module CPEE | |
| 492 520 | 
             
                    dn = CPEE::ModelManagement::get_dn @h['DN']
         | 
| 493 521 | 
             
                    author = dn['GN'] + ' ' + dn['SN']
         | 
| 494 522 | 
             
                    if !File.exist?(File.join(models,to,name + '.xml'))
         | 
| 523 | 
            +
                      attrs = {}
         | 
| 495 524 | 
             
                      XML::Smart::modify(fname) do |doc|
         | 
| 496 525 | 
             
                        doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 497 526 | 
             
                        doc.find('/p:testset/p:attributes/p:design_dir').each do |ele|
         | 
| 498 527 | 
             
                          ele.text = to
         | 
| 499 528 | 
             
                        end
         | 
| 529 | 
            +
                        attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 530 | 
            +
                          [e.qname.name,e.text]
         | 
| 531 | 
            +
                        end.to_h
         | 
| 500 532 | 
             
                      end
         | 
| 501 | 
            -
                      File.write(fname + '. | 
| 533 | 
            +
                      File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 502 534 |  | 
| 503 535 | 
             
                      CPEE::ModelManagement::op author, 'mv', models, File.join('.', to, name + '.xml'), File.join('.', where, name + '.xml')
         | 
| 504 536 | 
             
                      CPEE::ModelManagement::notify conns, 'move', models, File.join(models,to,name + '.xml'), fname
         | 
| @@ -518,20 +550,25 @@ module CPEE | |
| 518 550 |  | 
| 519 551 | 
             
                    if File.exists?(fname)
         | 
| 520 552 | 
             
                      author = dn['GN'] + ' ' + dn['SN']
         | 
| 553 | 
            +
                      attrs = {}
         | 
| 521 554 | 
             
                      XML::Smart.string(cont) do |doc|
         | 
| 522 555 | 
             
                        doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
         | 
| 523 | 
            -
                        unless File.exists?(File.join(models,where,name + '.xml.creator'))
         | 
| 524 | 
            -
                          doc.find('/p:testset/p:attributes/p:author').each do |ele|
         | 
| 525 | 
            -
                            File.write(File.join(models,where,name + '.xml.creator'),ele.text)
         | 
| 526 | 
            -
                          end
         | 
| 527 | 
            -
                        end
         | 
| 528 556 | 
             
                        doc.find('/p:testset/p:attributes/p:author').each do |ele|
         | 
| 529 557 | 
             
                          ele.text = dn['GN'] + ' ' + dn['SN']
         | 
| 530 558 | 
             
                        end
         | 
| 559 | 
            +
                        if doc.find('/p:testset/p:attributes/p:design_stage').empty?
         | 
| 560 | 
            +
                          doc.find('/p:testset/p:attributes').first.add('p:design_stage','draft')
         | 
| 561 | 
            +
                        else
         | 
| 562 | 
            +
                          doc.find('/p:testset/p:attributes/p:design_stage').each do |ele|
         | 
| 563 | 
            +
                            ele.text = 'draft' if ele.text.strip == ''
         | 
| 564 | 
            +
                          end
         | 
| 565 | 
            +
                        end
         | 
| 566 | 
            +
                        attrs = doc.find('/p:testset/p:attributes/*').map do |e|
         | 
| 567 | 
            +
                          [e.qname.name,e.text]
         | 
| 568 | 
            +
                        end.to_h
         | 
| 531 569 | 
             
                        File.write(fname,doc.to_s)
         | 
| 532 | 
            -
                        File.write(fname + '.author',author)
         | 
| 533 | 
            -
                        File.write(fname + '.stage',doc.find('string(/p:testset/p:attributes/p:design_stage)').sub(/^$/,'draft'))
         | 
| 534 570 | 
             
                      end
         | 
| 571 | 
            +
                      File.write(fname + '.attrs',JSON::pretty_generate(attrs))
         | 
| 535 572 | 
             
                      CPEE::ModelManagement::op author, 'add', models, File.join('.', where, name + '.xml')
         | 
| 536 573 | 
             
                      CPEE::ModelManagement::notify conns, 'put', models, fname
         | 
| 537 574 | 
             
                    else
         | 
    
        data/server/model.xml
    CHANGED
    
    | @@ -25,6 +25,10 @@ | |
| 25 25 | 
             
                <info>none</info>
         | 
| 26 26 | 
             
                <creator>Juergen Mangler</creator>
         | 
| 27 27 | 
             
                <author>Juergen Mangler</author>
         | 
| 28 | 
            +
                <guarded>none</guarded>
         | 
| 29 | 
            +
                <guarded_id></guarded_id>
         | 
| 30 | 
            +
                <model_uuid></model_uuid>
         | 
| 31 | 
            +
                <model_version></model_version>
         | 
| 28 32 | 
             
                <modeltype>CPEE</modeltype>
         | 
| 29 33 | 
             
                <theme>model</theme>
         | 
| 30 34 | 
             
                <design_dir></design_dir>
         | 
    
        data/server/moma.conf
    CHANGED
    
    
    
        data/server/testset.xml
    CHANGED
    
    | @@ -18,6 +18,10 @@ | |
| 18 18 | 
             
                <creator>Juergen Mangler</creator>
         | 
| 19 19 | 
             
                <author>Juergen Mangler</author>
         | 
| 20 20 | 
             
                <modeltype>CPEE</modeltype>
         | 
| 21 | 
            +
                <guarded>none</guarded>
         | 
| 22 | 
            +
                <guarded_id></guarded_id>
         | 
| 23 | 
            +
                <model_uuid></model_uuid>
         | 
| 24 | 
            +
                <model_version></model_version>
         | 
| 21 25 | 
             
                <theme>extended</theme>
         | 
| 22 26 | 
             
                <design_dir></design_dir>
         | 
| 23 27 | 
             
                <design_stage>draft</design_stage>
         | 
    
        data/tools/cpee-moma
    CHANGED
    
    | @@ -6,6 +6,8 @@ require 'fileutils' | |
| 6 6 | 
             
            require 'xml/smart'
         | 
| 7 7 | 
             
            require 'zip'
         | 
| 8 8 | 
             
            require 'typhoeus'
         | 
| 9 | 
            +
            require 'json'
         | 
| 10 | 
            +
            require 'securerandom'
         | 
| 9 11 |  | 
| 10 12 | 
             
            def wrap(s, width=78, indent=18)
         | 
| 11 13 | 
             
            	lines = []
         | 
| @@ -84,7 +86,7 @@ if command == 'cpui' | |
| 84 86 | 
             
                js_libs(p1)
         | 
| 85 87 | 
             
            elsif command == 'convert'
         | 
| 86 88 | 
             
              Dir['*.xml'].each do |f|
         | 
| 87 | 
            -
                XML::Smart. | 
| 89 | 
            +
                XML::Smart.open(f) do |doc|
         | 
| 88 90 | 
             
                  doc.register_namespace 'x', 'http://cpee.org/ns/properties/2.0'
         | 
| 89 91 | 
             
                  if doc.root.qname.name == 'testset'
         | 
| 90 92 | 
             
                    name = File.basename(f,'.xml')
         | 
| @@ -94,6 +96,10 @@ elsif command == 'convert' | |
| 94 96 | 
             
                      n = doc.root.add('x:attributes')
         | 
| 95 97 | 
             
                    end
         | 
| 96 98 |  | 
| 99 | 
            +
                    if doc.find('/x:testset/x:attributes/x:model_uuid').length == 0
         | 
| 100 | 
            +
                      n = doc.find('/x:testset/x:attributes').first
         | 
| 101 | 
            +
                      n.add('x:model_uuid',SecureRandom.uuid)
         | 
| 102 | 
            +
                    end
         | 
| 97 103 | 
             
                    if doc.find('/x:testset/x:attributes/x:theme').length == 0
         | 
| 98 104 | 
             
                      n = doc.find('/x:testset/x:attributes').first
         | 
| 99 105 | 
             
                      n.add('x:theme','extended')
         | 
| @@ -113,7 +119,6 @@ elsif command == 'convert' | |
| 113 119 | 
             
                        e.add('x:creator',creator)
         | 
| 114 120 | 
             
                      end
         | 
| 115 121 | 
             
                    end
         | 
| 116 | 
            -
                    File.write(f + '.creator',creator)
         | 
| 117 122 |  | 
| 118 123 | 
             
                    if (dt = doc.find('/x:testset/x:attributes/x:author')).length > 0
         | 
| 119 124 | 
             
                      dt.each do |e|
         | 
| @@ -125,7 +130,6 @@ elsif command == 'convert' | |
| 125 130 | 
             
                        e.add('x:author',author)
         | 
| 126 131 | 
             
                      end
         | 
| 127 132 | 
             
                    end
         | 
| 128 | 
            -
                    File.write(f + '.author',author)
         | 
| 129 133 |  | 
| 130 134 | 
             
                    if (dt = doc.find('/x:testset/x:attributes/x:design_stage')).length > 0
         | 
| 131 135 | 
             
                      dt.each do |e|
         | 
| @@ -137,7 +141,6 @@ elsif command == 'convert' | |
| 137 141 | 
             
                        e.add('x:design_stage',design_stage)
         | 
| 138 142 | 
             
                      end
         | 
| 139 143 | 
             
                    end
         | 
| 140 | 
            -
                    File.write(f + '.stage',design_stage)
         | 
| 141 144 |  | 
| 142 145 | 
             
                    dd = ENV['PWD'] || Dir.pwd
         | 
| 143 146 | 
             
                    ma = dd.scan(/\/([^\/]+\.dir)/)
         | 
| @@ -157,9 +160,28 @@ elsif command == 'convert' | |
| 157 160 | 
             
                        e.text = name
         | 
| 158 161 | 
             
                      end
         | 
| 159 162 | 
             
                    end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
             | 
| 165 | 
            +
                    attrs = doc.find('/x:testset/x:attributes/*').map do |e|
         | 
| 166 | 
            +
                      [e.qname.name,e.text]
         | 
| 167 | 
            +
                    end.to_h
         | 
| 168 | 
            +
                    File.write(f + '.attrs',JSON::pretty_generate(attrs))
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                    File.unlink(f + '.creator') rescue nil
         | 
| 171 | 
            +
                    File.unlink(f + '.author') rescue nil
         | 
| 172 | 
            +
                    File.unlink(f + '.stage') rescue nil
         | 
| 160 173 | 
             
                  end
         | 
| 161 174 | 
             
                end
         | 
| 162 175 | 
             
              end
         | 
| 176 | 
            +
              Dir['*.dir'].each do |f|
         | 
| 177 | 
            +
                attrs = JSON::load File.open(f + '.attrs') rescue {}
         | 
| 178 | 
            +
                attrs['creator'] = File.read(f + '.creator') if File.exists?(f + '.creator')
         | 
| 179 | 
            +
                attrs['author'] = File.read(f + '.author') if File.exists?(f + '.author')
         | 
| 180 | 
            +
                File.write(f + '.attrs',JSON::pretty_generate(attrs))
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                File.unlink(f + '.creator') rescue nil
         | 
| 183 | 
            +
                File.unlink(f + '.author') rescue nil
         | 
| 184 | 
            +
              end
         | 
| 163 185 | 
             
            elsif command == 'new'
         | 
| 164 186 | 
             
              if !File.exists?(p1)
         | 
| 165 187 | 
             
                FileUtils.mkdir(File.join(p1)) rescue nil
         | 
    
        data/ui/css/design.css
    CHANGED
    
    | @@ -22,6 +22,12 @@ form input { | |
| 22 22 |  | 
| 23 23 | 
             
            ui-behind {
         | 
| 24 24 | 
             
              text-transform: capitalize;
         | 
| 25 | 
            +
              font-weight: bold;
         | 
| 26 | 
            +
              color: #d0d0d0;
         | 
| 27 | 
            +
            }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            ui-behind span {
         | 
| 30 | 
            +
              cursor: pointer;
         | 
| 25 31 | 
             
            }
         | 
| 26 32 |  | 
| 27 33 | 
             
            [is="x-ui-"] table.ui-table {
         | 
| @@ -48,3 +54,9 @@ ui-behind { | |
| 48 54 | 
             
            [is="x-ui-"] table.ui-table tbody tr:hover td[data-class=ops] {
         | 
| 49 55 | 
             
              background-color: #99cee6b0;
         | 
| 50 56 | 
             
            }
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            [is="x-ui-"] ui-rest > ui-content > ui-area { padding: 1em; }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            tr.contextmenuitem .capitalized {
         | 
| 61 | 
            +
              text-transform: capitalize;
         | 
| 62 | 
            +
            }
         | 
    
        data/ui/design.js
    ADDED
    
    | @@ -0,0 +1,239 @@ | |
| 1 | 
            +
            var gstage;
         | 
| 2 | 
            +
            var gdir;
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            function move_it(name,todir) {
         | 
| 5 | 
            +
              $.ajax({
         | 
| 6 | 
            +
                type: "PUT",
         | 
| 7 | 
            +
                url: "server/" + gdir + name,
         | 
| 8 | 
            +
                data: { dir: todir }
         | 
| 9 | 
            +
              });
         | 
| 10 | 
            +
            }
         | 
| 11 | 
            +
            function shift_it(name,to) {
         | 
| 12 | 
            +
              $.ajax({
         | 
| 13 | 
            +
                type: "PUT",
         | 
| 14 | 
            +
                url: "server/" + gdir + name,
         | 
| 15 | 
            +
                data: { stage: to }
         | 
| 16 | 
            +
              });
         | 
| 17 | 
            +
            }
         | 
| 18 | 
            +
            function rename_it(name) {
         | 
| 19 | 
            +
              var newname;
         | 
| 20 | 
            +
              if (newname = prompt('New name please!',name.replace(/\.xml$/,'').replace(/\.dir$/,''))) {
         | 
| 21 | 
            +
                $.ajax({
         | 
| 22 | 
            +
                  type: "PUT",
         | 
| 23 | 
            +
                  url: "server/" + gdir + name,
         | 
| 24 | 
            +
                  data: { new: newname }
         | 
| 25 | 
            +
                });
         | 
| 26 | 
            +
              }
         | 
| 27 | 
            +
            }
         | 
| 28 | 
            +
            function duplicate_it(name) {
         | 
| 29 | 
            +
              var newname;
         | 
| 30 | 
            +
              if (newname = prompt('New name please!',name.replace(/\.xml$/,'').replace(/\.dir$/,''))) {
         | 
| 31 | 
            +
                $.ajax({
         | 
| 32 | 
            +
                  type: "POST",
         | 
| 33 | 
            +
                  url: "server/" + gdir,
         | 
| 34 | 
            +
                  data: { new: newname, old: name }
         | 
| 35 | 
            +
                });
         | 
| 36 | 
            +
              }
         | 
| 37 | 
            +
            }
         | 
| 38 | 
            +
            function delete_it(name) {
         | 
| 39 | 
            +
              if (confirm('Are you really, really, REALLY sure!')) {
         | 
| 40 | 
            +
                $.ajax({
         | 
| 41 | 
            +
                  type: "DELETE",
         | 
| 42 | 
            +
                  url: "server/" + gdir + name
         | 
| 43 | 
            +
                });
         | 
| 44 | 
            +
              }
         | 
| 45 | 
            +
            }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            function es_init(gdir,gstage) {
         | 
| 48 | 
            +
              var es = new EventSource('server/');
         | 
| 49 | 
            +
              es.onopen = function() {
         | 
| 50 | 
            +
                console.log('es open');
         | 
| 51 | 
            +
              };
         | 
| 52 | 
            +
              es.onmessage = function(e) {
         | 
| 53 | 
            +
                paint(gdir,gstage);
         | 
| 54 | 
            +
              };
         | 
| 55 | 
            +
              es.onerror = function() {
         | 
| 56 | 
            +
                console.log('es error');
         | 
| 57 | 
            +
                // es_init();
         | 
| 58 | 
            +
              };
         | 
| 59 | 
            +
            }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            function paint(gdir,gstage) {
         | 
| 62 | 
            +
              $('#models tbody').empty();
         | 
| 63 | 
            +
              if (gdir && gdir != '') {
         | 
| 64 | 
            +
                var clone = document.importNode(document.querySelector('#up').content,true);
         | 
| 65 | 
            +
                $('[data-class=name] a',clone).text('..');
         | 
| 66 | 
            +
                $('[data-class=name] a',clone).attr('href',window.location.pathname + '?stage=' + gstage + '&dir=');
         | 
| 67 | 
            +
                $('#models tbody').append(clone);
         | 
| 68 | 
            +
              }
         | 
| 69 | 
            +
              $.ajax({
         | 
| 70 | 
            +
                type: "GET",
         | 
| 71 | 
            +
                url: "server/" + gdir,
         | 
| 72 | 
            +
                data: { stage: gstage },
         | 
| 73 | 
            +
                success: function(res) {
         | 
| 74 | 
            +
                  $(res).each(function(k,data) {
         | 
| 75 | 
            +
                    if (data.type == 'dir') {
         | 
| 76 | 
            +
                      var clone = document.importNode(document.querySelector('#folder').content,true);
         | 
| 77 | 
            +
                      $('[data-class=name] a',clone).text(data['name'].replace(/\.dir$/,''));
         | 
| 78 | 
            +
                      $('[data-class=name]',clone).attr('data-full-name',data['name']);
         | 
| 79 | 
            +
                      $('[data-class=name] a',clone).attr('href',window.location.pathname + '?stage=' + gstage + '&dir=' + data['name']);
         | 
| 80 | 
            +
                    } else {
         | 
| 81 | 
            +
                      var clone = document.importNode(document.querySelector('#model').content,true);
         | 
| 82 | 
            +
                      $('[data-class=name] a',clone).text(data['name']);
         | 
| 83 | 
            +
                      $('[data-class=name]',clone).attr('data-full-name',data['name']);
         | 
| 84 | 
            +
                      $('[data-class=name] a',clone).attr('href','server/' + gdir + data['name'] + '/open?stage=' + gstage);
         | 
| 85 | 
            +
                      $('[data-class=force] a',clone).attr('href','server/' + gdir + data['name'] + '/open-new?stage=' + gstage);
         | 
| 86 | 
            +
                      $('[data-class=raw] a',clone).attr('href','server/' + gdir + data['name']);
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      $('[data-class=guarded] abbr',clone).attr('title',data['guarded'] || '');
         | 
| 89 | 
            +
                      $('[data-class=guarded] abbr',clone).text((data['guarded'] || '').match(/none/i) ? '' : (data['guarded'] || '').charAt(0).toUpperCase());
         | 
| 90 | 
            +
                      $('[data-class=resource]',clone).text(data['guarded_id'] || '');
         | 
| 91 | 
            +
                    }
         | 
| 92 | 
            +
                    $('[data-class=author]',clone).text(data['author']);
         | 
| 93 | 
            +
                    $('[data-class=date]',clone).text(new Date(data['date']).strftime('%Y-%m-%d, %H:%M:%S'));
         | 
| 94 | 
            +
                    $('#models tbody').append(clone);
         | 
| 95 | 
            +
                  });
         | 
| 96 | 
            +
                }
         | 
| 97 | 
            +
              });
         | 
| 98 | 
            +
            }
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            function change_it(gdir,gstage) {
         | 
| 101 | 
            +
              window.location.href = window.location.pathname + '?stage=' + gstage + '&dir=' + gdir;
         | 
| 102 | 
            +
            }
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            $(document).ready(function() {
         | 
| 105 | 
            +
              const queryString = window.location.search;
         | 
| 106 | 
            +
              const urlParams = new URLSearchParams(queryString);
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              gstage = urlParams.get('stage') || 'draft';
         | 
| 109 | 
            +
              gdir = urlParams.get('dir') ? (urlParams.get('dir') + '/').replace(/\/+/,'/') : '';
         | 
| 110 | 
            +
             | 
| 111 | 
            +
              es_init(gdir,gstage);
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              var shifts = []
         | 
| 114 | 
            +
              $.ajax({
         | 
| 115 | 
            +
                type: "GET",
         | 
| 116 | 
            +
                url: "server/",
         | 
| 117 | 
            +
                data: { stages: 'stages' },
         | 
| 118 | 
            +
                success: (r) => {
         | 
| 119 | 
            +
                  shifts = shifts.concat(r);
         | 
| 120 | 
            +
                  shifts = shifts.filter(item => item !== gstage);
         | 
| 121 | 
            +
                }
         | 
| 122 | 
            +
              });
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              $('input[name=stage]').val(gstage);
         | 
| 125 | 
            +
              $('input[name=dir]').val(gdir);
         | 
| 126 | 
            +
              $('ui-behind span').text(gstage);
         | 
| 127 | 
            +
              $('ui-behind span').click((e) => {
         | 
| 128 | 
            +
                if (shifts.length > 0) {
         | 
| 129 | 
            +
                  var menu = {};
         | 
| 130 | 
            +
                  menu['Change to'] = [];
         | 
| 131 | 
            +
                  shifts.forEach(ele => {
         | 
| 132 | 
            +
                    menu['Change to'].push(
         | 
| 133 | 
            +
                      {
         | 
| 134 | 
            +
                        'label': ele,
         | 
| 135 | 
            +
                        'function_call': change_it,
         | 
| 136 | 
            +
                        'text_icon': '➔',
         | 
| 137 | 
            +
                        'type': undefined,
         | 
| 138 | 
            +
                        'class': 'capitalized',
         | 
| 139 | 
            +
                        'params': [gdir,ele]
         | 
| 140 | 
            +
                      }
         | 
| 141 | 
            +
                    );
         | 
| 142 | 
            +
                  });
         | 
| 143 | 
            +
                  new CustomMenu(e).contextmenu(menu);
         | 
| 144 | 
            +
                }
         | 
| 145 | 
            +
              });
         | 
| 146 | 
            +
             | 
| 147 | 
            +
              var dragged;
         | 
| 148 | 
            +
              $('#models').on('drag','td[data-class=model]',false);
         | 
| 149 | 
            +
              $('#models').on('dragstart','td[data-class=model]',(e) => {
         | 
| 150 | 
            +
                dragged = $(e.currentTarget).parents('tr').find('td[data-class=name]').text();
         | 
| 151 | 
            +
              });
         | 
| 152 | 
            +
              $('#models').on('dragover','td[data-class=folder]',false);
         | 
| 153 | 
            +
              $('#models').on('drop','td[data-class=folder]',(e) => {
         | 
| 154 | 
            +
                e.preventDefault();
         | 
| 155 | 
            +
                e.stopPropagation();
         | 
| 156 | 
            +
                if (dragged) {
         | 
| 157 | 
            +
                  var todir = $(e.currentTarget).parents('tr').find('td[data-class=name]').text();
         | 
| 158 | 
            +
                  todir = todir.replace(/\./g,'');
         | 
| 159 | 
            +
                  if (todir != '') {
         | 
| 160 | 
            +
                    todir += '.dir';
         | 
| 161 | 
            +
                  }
         | 
| 162 | 
            +
                  move_it(dragged,todir);
         | 
| 163 | 
            +
                  dragged = undefined;
         | 
| 164 | 
            +
                }
         | 
| 165 | 
            +
              });
         | 
| 166 | 
            +
              $('#models').on('click','td[data-class=ops]',(e) => {
         | 
| 167 | 
            +
                var menu = {};
         | 
| 168 | 
            +
                var name = $(e.currentTarget).parents('tr').find('td[data-class=name]').attr('data-full-name');
         | 
| 169 | 
            +
                menu['Operations'] = [
         | 
| 170 | 
            +
                  {
         | 
| 171 | 
            +
                    'label': 'Delete',
         | 
| 172 | 
            +
                    'function_call': delete_it,
         | 
| 173 | 
            +
                    'text_icon': '❌',
         | 
| 174 | 
            +
                    'type': undefined,
         | 
| 175 | 
            +
                    'params': [name]
         | 
| 176 | 
            +
                  },
         | 
| 177 | 
            +
                  {
         | 
| 178 | 
            +
                    'label': 'Rename',
         | 
| 179 | 
            +
                    'function_call': rename_it,
         | 
| 180 | 
            +
                    'type': undefined,
         | 
| 181 | 
            +
                    'text_icon': '📛',
         | 
| 182 | 
            +
                    'params': [name]
         | 
| 183 | 
            +
                  }
         | 
| 184 | 
            +
                ];
         | 
| 185 | 
            +
                if (name.match(/\.xml$/)) {
         | 
| 186 | 
            +
                  menu['Operations'].unshift(
         | 
| 187 | 
            +
                    {
         | 
| 188 | 
            +
                      'label': 'Duplicate',
         | 
| 189 | 
            +
                      'function_call': duplicate_it,
         | 
| 190 | 
            +
                      'text_icon': '➕',
         | 
| 191 | 
            +
                      'type': undefined,
         | 
| 192 | 
            +
                      'params': [name]
         | 
| 193 | 
            +
                    }
         | 
| 194 | 
            +
                  );
         | 
| 195 | 
            +
                }
         | 
| 196 | 
            +
                if (shifts.length > 0) {
         | 
| 197 | 
            +
                  menu['Shifting'] = [];
         | 
| 198 | 
            +
                  shifts.forEach(ele => {
         | 
| 199 | 
            +
                    menu['Shifting'].push(
         | 
| 200 | 
            +
                      {
         | 
| 201 | 
            +
                        'label': 'Shift to ' + ele,
         | 
| 202 | 
            +
                        'function_call': shift_it,
         | 
| 203 | 
            +
                        'text_icon': '➔',
         | 
| 204 | 
            +
                        'type': undefined,
         | 
| 205 | 
            +
                        'params': [name,ele]
         | 
| 206 | 
            +
                      }
         | 
| 207 | 
            +
                    );
         | 
| 208 | 
            +
                  });
         | 
| 209 | 
            +
                }
         | 
| 210 | 
            +
                new CustomMenu(e).contextmenu(menu);
         | 
| 211 | 
            +
              });
         | 
| 212 | 
            +
             | 
| 213 | 
            +
              history.pushState({}, document.title, window.location.pathname + '?stage=' + gstage + '&dir=' + gdir);
         | 
| 214 | 
            +
              paint(gdir,gstage);
         | 
| 215 | 
            +
             | 
| 216 | 
            +
              $('#newmod').on('submit',(e) => {
         | 
| 217 | 
            +
                $.ajax({
         | 
| 218 | 
            +
                  type: "POST",
         | 
| 219 | 
            +
                  url: "server/" + gdir,
         | 
| 220 | 
            +
                  data: { stage: gstage, new: $("#newmod input[name=new]").val() },
         | 
| 221 | 
            +
                  success: (r) => {
         | 
| 222 | 
            +
                    uidash_activate_tab($('ui-tab').first());
         | 
| 223 | 
            +
                  }
         | 
| 224 | 
            +
                });
         | 
| 225 | 
            +
                return false;
         | 
| 226 | 
            +
              });
         | 
| 227 | 
            +
             | 
| 228 | 
            +
              $('#newdir').on('submit',(e) => {
         | 
| 229 | 
            +
                $.ajax({
         | 
| 230 | 
            +
                  type: "POST",
         | 
| 231 | 
            +
                  url: "server/",
         | 
| 232 | 
            +
                  data: { dir: $("#newdir input[name=newdir]").val() },
         | 
| 233 | 
            +
                  success: (r) => {
         | 
| 234 | 
            +
                    uidash_activate_tab($('ui-tab').first());
         | 
| 235 | 
            +
                  }
         | 
| 236 | 
            +
                });
         | 
| 237 | 
            +
                return false;
         | 
| 238 | 
            +
              });
         | 
| 239 | 
            +
            });
         | 
    
        data/ui/index.html
    CHANGED
    
    | @@ -61,20 +61,35 @@ | |
| 61 61 | 
             
                    <ui-tab class=""         data-tab="models"  >Models</ui-tab>
         | 
| 62 62 | 
             
                    <ui-tab class="inactive" data-tab="newmodel">New Model</ui-tab>
         | 
| 63 63 | 
             
                    <ui-tab class="inactive" data-tab="newdir"  >New Dir</ui-tab>
         | 
| 64 | 
            -
                    <ui- | 
| 64 | 
            +
                    <ui-space                                   ></ui-space>
         | 
| 65 | 
            +
                    <ui-tab class="inactive" data-tab="running" >Running</ui-tab>
         | 
| 66 | 
            +
                    <ui-tab class="inactive" data-tab="stopped" >Stopped</ui-tab>
         | 
| 67 | 
            +
                    <ui-behind                                  ><span></span></ui-behind>
         | 
| 65 68 | 
             
                    <ui-last                                    ><a class="logo" href=".."></a></ui-last>
         | 
| 66 69 | 
             
                  </ui-tabbar>
         | 
| 67 70 | 
             
                  <ui-content class="noselect">
         | 
| 68 71 | 
             
                    <ui-area data-belongs-to-tab="models">
         | 
| 69 72 | 
             
                      <p>Your Models are saved/versioned in <a target='_blank' href='https://git-scm.com/'>GIT</a>. So fret not. Just send an email to <a href="mail:helpdesk@acdp.at">helpdesk@acdp.at</a> if you are lost. And as always: <a target='_blank' href='https://www.youtube.com/watch?v=kkxj5xVLyj0&feature=youtu.be&t=56'>get dressed for success</a>.</p>
         | 
| 70 73 | 
             
                      <table id="models" class='ui-table'>
         | 
| 74 | 
            +
                        <thead>
         | 
| 75 | 
            +
                          <th></th>
         | 
| 76 | 
            +
                          <th>Name</th>
         | 
| 77 | 
            +
                          <th><abbr title='force new instance'>F</abbr></th>
         | 
| 78 | 
            +
                          <th><abbr title='link to model source'>M</abbr></th>
         | 
| 79 | 
            +
                          <th>Changed By</th>
         | 
| 80 | 
            +
                          <th><abbr title='Guarded'>G</abbr></th>
         | 
| 81 | 
            +
                          <th><abbr title='Resource'>R</abbr></th>
         | 
| 82 | 
            +
                          <th>Changed At</th>
         | 
| 83 | 
            +
                          <th><abbr title='Operations'>Op</abbr></th>
         | 
| 84 | 
            +
                        </thead>
         | 
| 71 85 | 
             
                        <template id="up">
         | 
| 72 86 | 
             
                          <tr>
         | 
| 73 87 | 
             
                            <td data-class='folder' class="noselect">📁</td>
         | 
| 74 88 | 
             
                            <td data-class='name' data-full-name=''><a href=''></a></td>
         | 
| 75 89 | 
             
                            <td></td>
         | 
| 76 90 | 
             
                            <td></td>
         | 
| 77 | 
            -
                            <td | 
| 91 | 
            +
                            <td></td>
         | 
| 92 | 
            +
                            <td></td>
         | 
| 78 93 | 
             
                            <td></td>
         | 
| 79 94 | 
             
                            <td data-class='date'></td>
         | 
| 80 95 | 
             
                            <td data-class=''></td>
         | 
| @@ -86,7 +101,8 @@ | |
| 86 101 | 
             
                            <td data-class='name' data-full-name=''><a href=''></a></td>
         | 
| 87 102 | 
             
                            <td></td>
         | 
| 88 103 | 
             
                            <td></td>
         | 
| 89 | 
            -
                            <td | 
| 104 | 
            +
                            <td></td>
         | 
| 105 | 
            +
                            <td></td>
         | 
| 90 106 | 
             
                            <td></td>
         | 
| 91 107 | 
             
                            <td data-class='date'></td>
         | 
| 92 108 | 
             
                            <td data-class='ops' class="noselect"><span>…</span></td>
         | 
| @@ -98,8 +114,9 @@ | |
| 98 114 | 
             
                            <td data-class='name' data-full-name=''><a target='_blank' href=''></a></td>
         | 
| 99 115 | 
             
                            <td data-class='force'>[<a target='_blank' href='' title='force new instance'>F</a>]</td>
         | 
| 100 116 | 
             
                            <td data-class='raw'>[<a target='_blank' href='' title='link to model source'>M</a>]</td>
         | 
| 101 | 
            -
                            <td data-class='creator'></td>
         | 
| 102 117 | 
             
                            <td data-class='author'></td>
         | 
| 118 | 
            +
                            <td data-class='guarded'><abbr title=''></abbr></td>
         | 
| 119 | 
            +
                            <td data-class='resource'></td>
         | 
| 103 120 | 
             
                            <td data-class='date'></td>
         | 
| 104 121 | 
             
                            <td data-class='ops' class="noselect"><span>…</span></td>
         | 
| 105 122 | 
             
                          </tr>
         | 
    
        data/ui/js/design.js
    CHANGED
    
    | @@ -84,8 +84,17 @@ function paint(gdir,gstage) { | |
| 84 84 | 
             
                      $('[data-class=name] a',clone).attr('href','server/' + gdir + data['name'] + '/open?stage=' + gstage);
         | 
| 85 85 | 
             
                      $('[data-class=force] a',clone).attr('href','server/' + gdir + data['name'] + '/open-new?stage=' + gstage);
         | 
| 86 86 | 
             
                      $('[data-class=raw] a',clone).attr('href','server/' + gdir + data['name']);
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      $('[data-class=guarded] abbr',clone).attr('title',data['guarded'] || '');
         | 
| 89 | 
            +
                      $('[data-class=guarded] abbr',clone).text((data['guarded'] || '').match(/none/i) ? '' : (data['guarded'] || '').charAt(0).toUpperCase());
         | 
| 90 | 
            +
                      $('[data-class=resource]',clone).text(data['guarded_id'] || '');
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                      if (data['guarded']) {
         | 
| 93 | 
            +
                        $('[data-class=guarded] abbr',clone).attr('title',data['guarded']);
         | 
| 94 | 
            +
                        $('[data-class=guarded] abbr',clone).text(data['guarded'].match(/none/i) ? '' : data['guarded'].charAt(0).toUpperCase());
         | 
| 95 | 
            +
                        $('[data-class=resource]',clone).text(data['guarded_what']);
         | 
| 96 | 
            +
                      }
         | 
| 87 97 | 
             
                    }
         | 
| 88 | 
            -
                    $('[data-class=creator]',clone).text(data['creator']);
         | 
| 89 98 | 
             
                    $('[data-class=author]',clone).text(data['author']);
         | 
| 90 99 | 
             
                    $('[data-class=date]',clone).text(new Date(data['date']).strftime('%Y-%m-%d, %H:%M:%S'));
         | 
| 91 100 | 
             
                    $('#models tbody').append(clone);
         | 
| @@ -94,6 +103,10 @@ function paint(gdir,gstage) { | |
| 94 103 | 
             
              });
         | 
| 95 104 | 
             
            }
         | 
| 96 105 |  | 
| 106 | 
            +
            function change_it(gdir,gstage) {
         | 
| 107 | 
            +
              window.location.href = window.location.pathname + '?stage=' + gstage + '&dir=' + gdir;
         | 
| 108 | 
            +
            }
         | 
| 109 | 
            +
             | 
| 97 110 | 
             
            $(document).ready(function() {
         | 
| 98 111 | 
             
              const queryString = window.location.search;
         | 
| 99 112 | 
             
              const urlParams = new URLSearchParams(queryString);
         | 
| @@ -103,9 +116,39 @@ $(document).ready(function() { | |
| 103 116 |  | 
| 104 117 | 
             
              es_init(gdir,gstage);
         | 
| 105 118 |  | 
| 119 | 
            +
              var shifts = []
         | 
| 120 | 
            +
              $.ajax({
         | 
| 121 | 
            +
                type: "GET",
         | 
| 122 | 
            +
                url: "server/",
         | 
| 123 | 
            +
                data: { stages: 'stages' },
         | 
| 124 | 
            +
                success: (r) => {
         | 
| 125 | 
            +
                  shifts = shifts.concat(r);
         | 
| 126 | 
            +
                  shifts = shifts.filter(item => item !== gstage);
         | 
| 127 | 
            +
                }
         | 
| 128 | 
            +
              });
         | 
| 129 | 
            +
             | 
| 106 130 | 
             
              $('input[name=stage]').val(gstage);
         | 
| 107 131 | 
             
              $('input[name=dir]').val(gdir);
         | 
| 108 | 
            -
              $('ui-behind').text(gstage);
         | 
| 132 | 
            +
              $('ui-behind span').text(gstage);
         | 
| 133 | 
            +
              $('ui-behind span').click((e) => {
         | 
| 134 | 
            +
                if (shifts.length > 0) {
         | 
| 135 | 
            +
                  var menu = {};
         | 
| 136 | 
            +
                  menu['Change to'] = [];
         | 
| 137 | 
            +
                  shifts.forEach(ele => {
         | 
| 138 | 
            +
                    menu['Change to'].push(
         | 
| 139 | 
            +
                      {
         | 
| 140 | 
            +
                        'label': ele,
         | 
| 141 | 
            +
                        'function_call': change_it,
         | 
| 142 | 
            +
                        'text_icon': '➔',
         | 
| 143 | 
            +
                        'type': undefined,
         | 
| 144 | 
            +
                        'class': 'capitalized',
         | 
| 145 | 
            +
                        'params': [gdir,ele]
         | 
| 146 | 
            +
                      }
         | 
| 147 | 
            +
                    );
         | 
| 148 | 
            +
                  });
         | 
| 149 | 
            +
                  new CustomMenu(e).contextmenu(menu);
         | 
| 150 | 
            +
                }
         | 
| 151 | 
            +
              });
         | 
| 109 152 |  | 
| 110 153 | 
             
              var dragged;
         | 
| 111 154 | 
             
              $('#models').on('drag','td[data-class=model]',false);
         | 
| @@ -117,7 +160,6 @@ $(document).ready(function() { | |
| 117 160 | 
             
                e.preventDefault();
         | 
| 118 161 | 
             
                e.stopPropagation();
         | 
| 119 162 | 
             
                if (dragged) {
         | 
| 120 | 
            -
                  console.log(dragged);
         | 
| 121 163 | 
             
                  var todir = $(e.currentTarget).parents('tr').find('td[data-class=name]').text();
         | 
| 122 164 | 
             
                  todir = todir.replace(/\./g,'');
         | 
| 123 165 | 
             
                  if (todir != '') {
         | 
| @@ -127,16 +169,6 @@ $(document).ready(function() { | |
| 127 169 | 
             
                  dragged = undefined;
         | 
| 128 170 | 
             
                }
         | 
| 129 171 | 
             
              });
         | 
| 130 | 
            -
              var shifts = []
         | 
| 131 | 
            -
              $.ajax({
         | 
| 132 | 
            -
                type: "GET",
         | 
| 133 | 
            -
                url: "server/",
         | 
| 134 | 
            -
                data: { stages: 'stages' },
         | 
| 135 | 
            -
                success: (r) => {
         | 
| 136 | 
            -
                  shifts = shifts.concat(r);
         | 
| 137 | 
            -
                  shifts = shifts.filter(item => item !== gstage);
         | 
| 138 | 
            -
                }
         | 
| 139 | 
            -
              });
         | 
| 140 172 | 
             
              $('#models').on('click','td[data-class=ops]',(e) => {
         | 
| 141 173 | 
             
                var menu = {};
         | 
| 142 174 | 
             
                var name = $(e.currentTarget).parents('tr').find('td[data-class=name]').attr('data-full-name');
         | 
| @@ -181,7 +213,6 @@ $(document).ready(function() { | |
| 181 213 | 
             
                    );
         | 
| 182 214 | 
             
                  });
         | 
| 183 215 | 
             
                }
         | 
| 184 | 
            -
                console.log(shifts);
         | 
| 185 216 | 
             
                new CustomMenu(e).contextmenu(menu);
         | 
| 186 217 | 
             
              });
         | 
| 187 218 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cpee-model-management
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.17
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Juergen eTM Mangler
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: tools
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-10-28 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: riddl
         | 
| @@ -38,6 +38,26 @@ dependencies: | |
| 38 38 | 
             
                - - "~>"
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 40 | 
             
                    version: '2.1'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: cpee
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '2.1'
         | 
| 48 | 
            +
                - - ">="
         | 
| 49 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 50 | 
            +
                    version: 2.1.7
         | 
| 51 | 
            +
              type: :runtime
         | 
| 52 | 
            +
              prerelease: false
         | 
| 53 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 54 | 
            +
                requirements:
         | 
| 55 | 
            +
                - - "~>"
         | 
| 56 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 57 | 
            +
                    version: '2.1'
         | 
| 58 | 
            +
                - - ">="
         | 
| 59 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 60 | 
            +
                    version: 2.1.7
         | 
| 41 61 | 
             
            description: see http://cpee.org
         | 
| 42 62 | 
             
            email: juergen.mangler@gmail.com
         | 
| 43 63 | 
             
            executables:
         | 
| @@ -61,6 +81,7 @@ files: | |
| 61 81 | 
             
            - server/testset.xml
         | 
| 62 82 | 
             
            - tools/cpee-moma
         | 
| 63 83 | 
             
            - ui/css/design.css
         | 
| 84 | 
            +
            - ui/design.js
         | 
| 64 85 | 
             
            - ui/index.html
         | 
| 65 86 | 
             
            - ui/js/design.js
         | 
| 66 87 | 
             
            homepage: http://cpee.org/
         | 
| @@ -82,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 82 103 | 
             
                - !ruby/object:Gem::Version
         | 
| 83 104 | 
             
                  version: '0'
         | 
| 84 105 | 
             
            requirements: []
         | 
| 85 | 
            -
            rubygems_version: 3. | 
| 106 | 
            +
            rubygems_version: 3.2.22
         | 
| 86 107 | 
             
            signing_key:
         | 
| 87 108 | 
             
            specification_version: 4
         | 
| 88 109 | 
             
            summary: "(Lifecycle) manage your process models in a directory or git repo."
         |