cpee-model-management 1.0.10 → 1.0.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9be3465ba484376cc2be761b4d4af2882bfdb5b64d13cb4630e33919682054d4
4
- data.tar.gz: e34f9311c42ff440cc4a8e00f082027b6810d17446e431e1f556e510455a39f1
3
+ metadata.gz: eb4c3a55fe08f20e52d1908aa0285f9783d8413a470bd0b034829569d7d39620
4
+ data.tar.gz: f0eeae82d2bc796f2976375113f0bd8616cb59e9b4e95541f3175f9cbd6565d1
5
5
  SHA512:
6
- metadata.gz: 907fff8cc59838e2c9272368ef4606d11324fcb5dcf9f9218e67c0c9a30f0ce462a920f56e9d5d5da19854eb73b7eec6670868672a1cca7c4022a49429776563
7
- data.tar.gz: 9039e345f7f75f631d0485702db06aba021fa4412623793ca8a628c31efcee9841c732debb65943ef9d8b88b9f07bc97a8542119086b9a493900e53ec76728ec
6
+ metadata.gz: dce3271b164de9f31aa0aef4dde102501c448a93067f0259d787446facbc72a119e617f35c09a02778e20114a07acdb08a9b76493a297ac05130c7ad0b542786
7
+ data.tar.gz: 1eac23abe60a8d110ff7e2b154502b4756629576b7d6c2a225360160ab31288fcb4d9e4ba58eed489261fcd21334fac96d9b18aab355e8b60d5b2374cfea5d60
@@ -1,13 +1,13 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-model-management"
3
- s.version = "1.0.10"
3
+ s.version = "1.0.16"
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."
7
7
 
8
8
  s.description = "see http://cpee.org"
9
9
 
10
- s.files = Dir['{server/*,tools/**/*,lib/**/*}'] + %w(LICENSE Rakefile cpee-model-management.gemspec README.md AUTHORS)
10
+ s.files = Dir['{server/*,tools/**/*,lib/**/*,ui/**/*}'] + %w(LICENSE Rakefile cpee-model-management.gemspec README.md AUTHORS)
11
11
  s.require_path = 'lib'
12
12
  s.extra_rdoc_files = ['README.md']
13
13
  s.bindir = 'tools'
@@ -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
@@ -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
@@ -40,9 +41,7 @@ module CPEE
40
41
  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv "#{told}" "#{tnew}" 2>/dev/null`
41
42
  `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active'}" 2>/dev/null`
42
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`
43
- `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv "#{told + '.author'}" "#{tnew + '.author'}" 2>/dev/null`
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`
44
+ `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple mv "#{told + '.attrs'}" "#{tnew + '.author'}" 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}.author" 2>/dev/null`
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 + '.author',fnname + '.author') rescue nil
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 + '.author',fnname + '.author') rescue nil
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 + '.author') rescue nil
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
- { :op => op, :type => :dir, :name => File.basename(f), :creator => File.read(f + '.creator'), :date => File.mtime(f).xmlschema }
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
- fstage = File.read(f + '.stage').strip rescue 'draft'
178
- { :op => op, :type => :file, :name => f.sub(Regexp.compile(File.join(models,'/')),''), :creator => File.read(f + '.creator'), :author => File.read(f + '.author'), :stage => fstage, :date => File.mtime(f).xmlschema }
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
- { :type => :dir, :name => File.basename(f), :creator => File.read(f + '.creator'), :date => File.mtime(f).xmlschema }
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
- fstage = File.read(f + '.stage').strip rescue 'draft'
200
- { :type => :file, :name => File.basename(f), :creator => File.read(f + '.creator'), :author => File.read(f + '.author'), :stage => fstage, :date => File.mtime(f).xmlschema } if stage.include?(fstage)
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
- { :type => :file, :name => File.join(File.basename(File.dirname(f)),File.basename(f)), :creator => File.read(f + '.creator'), :date => File.mtime(f).xmlschema }
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
- fstage = File.read(f + '.stage').strip rescue 'draft'
217
- { :type => :file, :name => File.basename(f), :creator => File.read(f + '.creator'), :author => File.read(f + '.author'), :stage => fstage, :date => File.mtime(f).xmlschema } if stage.include?(fstage)
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 + '.author',author)
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 + '.author',author)
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,10 @@ module CPEE
312
315
 
313
316
  dn = CPEE::ModelManagement::get_dn @h['DN']
314
317
  author = dn['GN'] + ' ' + dn['SN']
315
- File.write(fname + '.author',author)
318
+
319
+ attrs = JSON::load File.open(fname + '.attrs')
320
+ attrs['author'] = author
321
+ File.write(fname + '.attrs',JSON::pretty_generate(attrs))
316
322
 
317
323
  CPEE::ModelManagement::op author, 'mv', models, File.join(nname + '.dir'), File.join(name + '.dir')
318
324
  CPEE::ModelManagement::notify conns, 'rename', models, fnname, fname
@@ -338,8 +344,11 @@ module CPEE
338
344
 
339
345
  Dir.mkdir(fname)
340
346
  FileUtils.touch(File.join(fname,'.gitignore'))
341
- File.write(fname + '.creator',creator)
342
- File.write(fname + '.author',creator)
347
+
348
+ attrs = JSON::load File.open(fname + '.attrs')
349
+ attrs['creator'] = creator
350
+ attrs['author'] = creator
351
+ File.write(fname + '.attrs',JSON::pretty_generate(attrs))
343
352
 
344
353
  CPEE::ModelManagement::op creator, 'add', models, name + '.dir'
345
354
  CPEE::ModelManagement::notify conns, 'create', models, fname
@@ -363,7 +372,8 @@ module CPEE
363
372
  source = @p[1] ? File.join(models,where,@p[1].value) : (templates[stage] ? templates[stage] : 'testset.xml')
364
373
  fname = File.join(models,where,name + '.xml')
365
374
 
366
- stage = File.read(source + '.stage') if stage.nil? && File.exists?(source + '.stage')
375
+ attrs = JSON::load File.open(fname + '.attrs') rescue {}
376
+ stage = attrs['design_stage'] if stage.nil? && attrs['design_stage']
367
377
  stage = views[stage] if views && views[stage]
368
378
 
369
379
  counter = 0
@@ -375,6 +385,7 @@ module CPEE
375
385
  dn = CPEE::ModelManagement::get_dn @h['DN']
376
386
  creator = dn['GN'] + ' ' + dn['SN']
377
387
  FileUtils.cp(source,fname)
388
+ attrs = {}
378
389
  XML::Smart::modify(fname) do |doc|
379
390
  doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
380
391
  doc.find('/p:testset/p:attributes/p:info').each do |ele|
@@ -389,15 +400,19 @@ module CPEE
389
400
  doc.find('/p:testset/p:attributes/p:design_dir').each do |ele|
390
401
  ele.text = where
391
402
  end
403
+ doc.find('/p:testset/p:attributes/p:model_uuid').each do |ele|
404
+ ele.text = SecureRandom.uuid
405
+ end
392
406
  if stage
393
407
  doc.find('/p:testset/p:attributes/p:design_stage').each do |ele|
394
408
  ele.text = stage
395
409
  end
396
410
  end
411
+ attrs = doc.find('/p:testset/p:attributes/*').map do |e|
412
+ [e.qname.name,e.text]
413
+ end.to_h
397
414
  end
398
- File.write(fname + '.creator',creator)
399
- File.write(fname + '.author',creator)
400
- File.write(fname + '.stage',stage)
415
+ File.write(fname + '.attrs',JSON::pretty_generate(attrs))
401
416
 
402
417
  CPEE::ModelManagement::op creator, 'add', models, File.join('.', where, name + '.xml')
403
418
  CPEE::ModelManagement::notify conns, 'create', models, fname
@@ -492,13 +507,17 @@ module CPEE
492
507
  dn = CPEE::ModelManagement::get_dn @h['DN']
493
508
  author = dn['GN'] + ' ' + dn['SN']
494
509
  if !File.exist?(File.join(models,to,name + '.xml'))
510
+ attrs = {}
495
511
  XML::Smart::modify(fname) do |doc|
496
512
  doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
497
513
  doc.find('/p:testset/p:attributes/p:design_dir').each do |ele|
498
514
  ele.text = to
499
515
  end
516
+ attrs = doc.find('/p:testset/p:attributes/*').map do |e|
517
+ [e.qname.name,e.text]
518
+ end.to_h
500
519
  end
501
- File.write(fname + '.author',author)
520
+ File.write(fname + '.attrs',JSON::pretty_generate(attrs))
502
521
 
503
522
  CPEE::ModelManagement::op author, 'mv', models, File.join('.', to, name + '.xml'), File.join('.', where, name + '.xml')
504
523
  CPEE::ModelManagement::notify conns, 'move', models, File.join(models,to,name + '.xml'), fname
@@ -518,20 +537,25 @@ module CPEE
518
537
 
519
538
  if File.exists?(fname)
520
539
  author = dn['GN'] + ' ' + dn['SN']
540
+ attrs = {}
521
541
  XML::Smart.string(cont) do |doc|
522
542
  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
543
  doc.find('/p:testset/p:attributes/p:author').each do |ele|
529
544
  ele.text = dn['GN'] + ' ' + dn['SN']
530
545
  end
546
+ if doc.find('/p:testset/p:attributes/p:design_stage').empty?
547
+ doc.find('/p:testset/p:attributes').first.add('p:design_stage','draft')
548
+ else
549
+ doc.find('/p:testset/p:attributes/p:design_stage').each do |ele|
550
+ ele.text = 'draft' if ele.text.strip == ''
551
+ end
552
+ end
553
+ attrs = doc.find('/p:testset/p:attributes/*').map do |e|
554
+ [e.qname.name,e.text]
555
+ end.to_h
531
556
  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
557
  end
558
+ File.write(fname + '.attrs',JSON::pretty_generate(attrs))
535
559
  CPEE::ModelManagement::op author, 'add', models, File.join('.', where, name + '.xml')
536
560
  CPEE::ModelManagement::notify conns, 'put', models, fname
537
561
  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
@@ -1,5 +1,6 @@
1
1
  :port: 9316
2
2
  :models: models
3
+ :location: https://cpee.org/design/server/
3
4
  :instantiate: https://cpee.org/flow/start/
4
5
  :cockpit:
5
6
  draft: https://cpee.org/flow/model.html?monitor=
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
@@ -5,6 +5,9 @@ require 'optparse'
5
5
  require 'fileutils'
6
6
  require 'xml/smart'
7
7
  require 'zip'
8
+ require 'typhoeus'
9
+ require 'json'
10
+ require 'securerandom'
8
11
 
9
12
  def wrap(s, width=78, indent=18)
10
13
  lines = []
@@ -24,6 +27,29 @@ def wrap(s, width=78, indent=18)
24
27
  return lines.join "\n"
25
28
  end
26
29
 
30
+ def js_libs(cockpit)
31
+ res = Typhoeus.get('https://cpee.org/js_libs/js_libs.zip')
32
+ if res.success?
33
+ File.write(File.join(cockpit,'js_libs.zip'),res.response_body)
34
+ Zip::File.open(File.join(cockpit,'js_libs.zip')) do |zip_file|
35
+ zip_file.each do |entry|
36
+ case entry.ftype
37
+ when :directory
38
+ Dir.mkdir(File.join(cockpit,entry.name)) rescue nil
39
+ when :file
40
+ File.write(File.join(cockpit,entry.name),entry.get_input_stream.read)
41
+ when :symlink
42
+ FileUtils.ln_s(File.join('.',entry.get_input_stream.read),File.join(cockpit,entry.name), force: true)
43
+ end
44
+ end
45
+ end
46
+ true
47
+ else
48
+ puts 'Internet access required to download javascript libs from "http://cpee.org/js_libs/js_libs.zip".'
49
+ false
50
+ end
51
+ end
52
+
27
53
  ARGV.options { |opt|
28
54
  opt.summary_indent = ' ' * 2
29
55
  opt.summary_width = 15
@@ -60,7 +86,7 @@ if command == 'cpui'
60
86
  js_libs(p1)
61
87
  elsif command == 'convert'
62
88
  Dir['*.xml'].each do |f|
63
- XML::Smart.modify(f) do |doc|
89
+ XML::Smart.open(f) do |doc|
64
90
  doc.register_namespace 'x', 'http://cpee.org/ns/properties/2.0'
65
91
  if doc.root.qname.name == 'testset'
66
92
  name = File.basename(f,'.xml')
@@ -70,6 +96,10 @@ elsif command == 'convert'
70
96
  n = doc.root.add('x:attributes')
71
97
  end
72
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
73
103
  if doc.find('/x:testset/x:attributes/x:theme').length == 0
74
104
  n = doc.find('/x:testset/x:attributes').first
75
105
  n.add('x:theme','extended')
@@ -89,7 +119,6 @@ elsif command == 'convert'
89
119
  e.add('x:creator',creator)
90
120
  end
91
121
  end
92
- File.write(f + '.creator',creator)
93
122
 
94
123
  if (dt = doc.find('/x:testset/x:attributes/x:author')).length > 0
95
124
  dt.each do |e|
@@ -101,7 +130,6 @@ elsif command == 'convert'
101
130
  e.add('x:author',author)
102
131
  end
103
132
  end
104
- File.write(f + '.author',author)
105
133
 
106
134
  if (dt = doc.find('/x:testset/x:attributes/x:design_stage')).length > 0
107
135
  dt.each do |e|
@@ -113,7 +141,6 @@ elsif command == 'convert'
113
141
  e.add('x:design_stage',design_stage)
114
142
  end
115
143
  end
116
- File.write(f + '.stage',design_stage)
117
144
 
118
145
  dd = ENV['PWD'] || Dir.pwd
119
146
  ma = dd.scan(/\/([^\/]+\.dir)/)
@@ -133,9 +160,28 @@ elsif command == 'convert'
133
160
  e.text = name
134
161
  end
135
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
136
173
  end
137
174
  end
138
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
139
185
  elsif command == 'new'
140
186
  if !File.exists?(p1)
141
187
  FileUtils.mkdir(File.join(p1)) rescue nil
data/ui/css/design.css ADDED
@@ -0,0 +1,62 @@
1
+ td {
2
+ padding-right: 1em;
3
+ }
4
+
5
+ td[data-class=model] {
6
+ font-size: 1.7em;
7
+ }
8
+ td[data-class=folder] {
9
+ font-size: 1.7em;
10
+ }
11
+ td[data-class=ops] {
12
+ cursor: pointer;
13
+ }
14
+
15
+ td[draggable] {
16
+ cursor: move;
17
+ }
18
+
19
+ form input {
20
+ width: 45em !important;
21
+ }
22
+
23
+ ui-behind {
24
+ text-transform: capitalize;
25
+ font-weight: bold;
26
+ color: #d0d0d0;
27
+ }
28
+
29
+ ui-behind span {
30
+ cursor: pointer;
31
+ }
32
+
33
+ [is="x-ui-"] table.ui-table {
34
+ border-collapse: collapse;
35
+ }
36
+ [is="x-ui-"] table.ui-table thead th {
37
+ font-weight: bold;
38
+ text-align: left;
39
+ padding: 0.3em 0.5em;
40
+ }
41
+ [is="x-ui-"] table.ui-table tbody td {
42
+ padding: 0.1em 0.5em;
43
+ }
44
+ [is="x-ui-"] table.ui-table tbody tr:nth-child(odd) td {
45
+ background-color: var(--x-ui-content-light-background);
46
+ }
47
+ [is="x-ui-"] table.ui-table tbody tr:hover td {
48
+ background-color: var(--x-ui-content-hover-background);
49
+ }
50
+
51
+ [is="x-ui-"] table.ui-table tbody tr:nth-child(odd) td[data-class=ops] {
52
+ background-color: #d0d0d0;
53
+ }
54
+ [is="x-ui-"] table.ui-table tbody tr:hover td[data-class=ops] {
55
+ background-color: #99cee6b0;
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 ADDED
@@ -0,0 +1,168 @@
1
+ <!--
2
+ This file is part of CPEE-MODEL-MANAGEMENT.
3
+
4
+ CPEE-MODEL-MANAGEMENT is free software: you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or (at your
7
+ option) any later version.
8
+
9
+ CPEE-MODEL-MANAGEMENT is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU General Public License along with
15
+ CPEE-MODEL-MANAGEMENT (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
19
+ <!DOCTYPE html>
20
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
21
+ <head>
22
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
23
+ <title>Design</title>
24
+
25
+ <!-- libs, do not modify. When local than load local libs. -->
26
+ <script type="text/javascript" src="/js_libs/jquery.min.js"></script>
27
+ <script type="text/javascript" src="/js_libs/jquery.browser.js"></script>
28
+ <script type="text/javascript" src="/js_libs/jquery.svg.min.js"></script>
29
+ <script type="text/javascript" src="/js_libs/jquery.svgdom.min.js"></script>
30
+ <script type="text/javascript" src="/js_libs/vkbeautify.js"></script>
31
+ <script type="text/javascript" src="/js_libs/util.js"></script>
32
+ <script type="text/javascript" src="/js_libs/printf.js"></script>
33
+ <script type="text/javascript" src="/js_libs/strftime.min.js"></script>
34
+ <script type="text/javascript" src="/js_libs/parsequery.js"></script>
35
+ <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
+ <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
+ <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+
39
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
40
+
41
+ <script type="text/javascript" src="/js_libs/relaxngui.js"></script>
42
+
43
+ <script type="text/javascript" src="/js_libs/uidash.js"></script>
44
+ <script type="text/javascript" src="/js_libs/custommenu.js"></script>
45
+
46
+ <link rel="stylesheet" href="/js_libs/custommenu.css" type="text/css"/>
47
+ <link rel="stylesheet" href="/js_libs/uidash.css" type="text/css"/>
48
+
49
+ <link rel="stylesheet" href="/global_ui/ui.css" type="text/css"/>
50
+
51
+ <link rel="stylesheet" href="/js_libs/relaxngui.css" type="text/css"/>
52
+
53
+ <!-- custom stuff, play arround -->
54
+ <link rel="stylesheet" href="css/design.css" type="text/css"/>
55
+ <script type="text/javascript" src="js/design.js"></script>
56
+ </head>
57
+ <body is="x-ui-">
58
+ <ui-rest id="main">
59
+ <ui-tabbar>
60
+ <ui-before ></ui-before>
61
+ <ui-tab class="" data-tab="models" >Models</ui-tab>
62
+ <ui-tab class="inactive" data-tab="newmodel">New Model</ui-tab>
63
+ <ui-tab class="inactive" data-tab="newdir" >New Dir</ui-tab>
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>
68
+ <ui-last ><a class="logo" href=".."></a></ui-last>
69
+ </ui-tabbar>
70
+ <ui-content class="noselect">
71
+ <ui-area data-belongs-to-tab="models">
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>
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>
85
+ <template id="up">
86
+ <tr>
87
+ <td data-class='folder' class="noselect">📁</td>
88
+ <td data-class='name' data-full-name=''><a href=''></a></td>
89
+ <td></td>
90
+ <td></td>
91
+ <td></td>
92
+ <td></td>
93
+ <td></td>
94
+ <td data-class='date'></td>
95
+ <td data-class=''></td>
96
+ </tr>
97
+ </template>
98
+ <template id="folder">
99
+ <tr>
100
+ <td data-class='folder' class="noselect">📁</td>
101
+ <td data-class='name' data-full-name=''><a href=''></a></td>
102
+ <td></td>
103
+ <td></td>
104
+ <td></td>
105
+ <td></td>
106
+ <td></td>
107
+ <td data-class='date'></td>
108
+ <td data-class='ops' class="noselect"><span>…</span></td>
109
+ </tr>
110
+ </template>
111
+ <template id="model">
112
+ <tr>
113
+ <td data-class='model' class="noselect" draggable="true" title='drag to folders to move'>𝌭</td>
114
+ <td data-class='name' data-full-name=''><a target='_blank' href=''></a></td>
115
+ <td data-class='force'>[<a target='_blank' href='' title='force new instance'>F</a>]</td>
116
+ <td data-class='raw'>[<a target='_blank' href='' title='link to model source'>M</a>]</td>
117
+ <td data-class='author'></td>
118
+ <td data-class='guarded'><abbr title=''></abbr></td>
119
+ <td data-class='resource'></td>
120
+ <td data-class='date'></td>
121
+ <td data-class='ops' class="noselect"><span>…</span></td>
122
+ </tr>
123
+ </template>
124
+ <tbody>
125
+ </tbody>
126
+ </table>
127
+ </ui-area>
128
+ <ui-area data-belongs-to-tab="newmodel" class="inactive">
129
+ <p>
130
+ Create an empty model. Beware, if a model of the same name already
131
+ exists in one of the categories (e.g. draft, development,
132
+ production, archive) it can not be created. To protect you from
133
+ getting confused and shooting yourself in the foot in your little
134
+ modelling world we allow only unique names. Better safe than sorry.
135
+ </p>
136
+ <form id="newmod">
137
+ <input type="hidden" name="stage" value=""/>
138
+ <input type="hidden" name="dir" value=""/>
139
+ <p>
140
+ <input type="text" name="new" required pattern="^[a-zA-Z0-9öäüÖÄÜ _-]+" placeholder="Filename (no extension necessary). Only use characters, spaces, underlines and dashes."/>
141
+ </p>
142
+ <p>
143
+ <button>New Model</button>
144
+ </p>
145
+ </form>
146
+ </ui-area>
147
+ <ui-area data-belongs-to-tab="newdir" class="inactive">
148
+ <p>
149
+ Create an empty directory. Beware, if a directory of the same name
150
+ already exists in one of the categories (e.g. draft, development,
151
+ production, archive) it can not be created. To protect you from
152
+ getting confused and shooting yourself in the foot in your little
153
+ modelling world we allow only unique names. Better safe than sorry.
154
+ </p>
155
+ <form id="newdir">
156
+ <input type="hidden" name="stage" value=""/>
157
+ <p>
158
+ <input type="text" name="newdir" required pattern="^[a-zA-Z0-9öäüÖÄÜ _-]+" placeholder="Directory name. Only use characters, spaces, underlines and dashes."/>
159
+ </p>
160
+ <p>
161
+ <button>New Directory</button>
162
+ </p>
163
+ </id>
164
+ </ui-area>
165
+ </ui-content>
166
+ </ui-rest>
167
+ </body>
168
+ </html>
data/ui/js/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
+ });
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.10
4
+ version: 1.0.16
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-05-19 00:00:00.000000000 Z
11
+ date: 2021-07-01 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:
@@ -60,6 +80,10 @@ files:
60
80
  - server/moma.conf
61
81
  - server/testset.xml
62
82
  - tools/cpee-moma
83
+ - ui/css/design.css
84
+ - ui/design.js
85
+ - ui/index.html
86
+ - ui/js/design.js
63
87
  homepage: http://cpee.org/
64
88
  licenses:
65
89
  - LGPL-3.0
@@ -79,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
103
  - !ruby/object:Gem::Version
80
104
  version: '0'
81
105
  requirements: []
82
- rubygems_version: 3.1.4
106
+ rubygems_version: 3.1.6
83
107
  signing_key:
84
108
  specification_version: 4
85
109
  summary: "(Lifecycle) manage your process models in a directory or git repo."