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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f01249cf02b86d83022b913a2b81ebcfd06e48f19eb307bcf8645c619260da7
4
- data.tar.gz: '08805c52f1143242b9e2f675886ab894d33fe28f5a05cc4408e0563eac592937'
3
+ metadata.gz: d3a70760a747bb5dd295cac87766307d1d3775767af440e3090d2e108757837d
4
+ data.tar.gz: ed59f63e220bb3c6fb8e096ce21ee41f5542c59fff051e48c0d04ff7ee8ccd79
5
5
  SHA512:
6
- metadata.gz: 4ea1643623a79c0ad75814965d0ed339591767f7c7d423c4d5f0a15dd88eb4f2626c0246b3f4e72a24989aff9dc8eb6cca2f5f72bea0751f6f0831ee437e5db7
7
- data.tar.gz: a36b6d9995c293f6ed8c2eca53ed0231c74cf1a44b07a3e53bd50e6c958349612fd71ce586e1cba65989a334148e35ae7752ca0eaddcd615bfc812ddf9d8084f
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.12"
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}.author" 2>/dev/null`
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}" 2>/dev/null`
41
- `git -c user.name='Christine Ashcreek' -c user.email=dev@null.com -c push.default=simple rm -rf "#{told + '.active'}" 2>/dev/null`
42
- `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`
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}.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,23 @@ 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))
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
- File.write(fname + '.creator',creator)
342
- File.write(fname + '.author',creator)
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
- stage = File.read(source + '.stage') if stage.nil? && File.exists?(source + '.stage')
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 + '.creator',creator)
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 + '.author',author)
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
@@ -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
@@ -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.modify(f) do |doc|
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-behind ></ui-behind>
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 data-class='creator'></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 data-class='creator'></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.12
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-05-27 00:00:00.000000000 Z
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.1.6
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."