cpee-model-management 1.0.9 → 1.0.15

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: ff58402244bdf7eadbd79cebb7c4ef42f302b45354da3bc1634bd866ba273eec
4
- data.tar.gz: 3dc2729da1856011a97a42c487117fe2cc7f4e6587e6e54934559bccc68b7148
3
+ metadata.gz: ce614812f4658c4e62170443af46efcd32843661fefc6f65d22be139e16cb5e4
4
+ data.tar.gz: 2e15d839338f8be623e9b536b067778d452e68a7b3e50359672099d7db382ef7
5
5
  SHA512:
6
- metadata.gz: 130154f25420d1901fa5dd8e83f15e2eecb6609660d7fd2e30f43e202b7a1a25fbc02e408bcf0575e5d4de6dffad5cdd2561926a4824a6127b9a72c2854e0267
7
- data.tar.gz: 6be4a1c311486e3364ce6e96192ca4b654e625ae102204150b34989384ba617abe5b7ba77c40b9f59233f61dfa7185c3d88917dd685629cbd1355c2b87bc62b3
6
+ metadata.gz: 45fae847a02d31b3332ddb8394192eae4e107ec6cdbd4287f3b2408bdb46ab38e55ee27c558f7bbd04ada97db1cc74b82d3294343bb40f0b2a166a43aba47774
7
+ data.tar.gz: 67b92d5bfe550a32aab89999ef5709b4928d277d7b4ef6ca75d6cf3f032a19b266aae72004580897c85088d2e4ad4017cf2bb931b8450424b797a20d115ee4af
@@ -1,13 +1,13 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-model-management"
3
- s.version = "1.0.9"
3
+ s.version = "1.0.15"
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['resource_restriction'], :guarded_what => attrs['resource_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['resource_restriction'], :guarded_what => attrs['resource_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')
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
+ <resource_restriction>none</resource_restriction>
29
+ <resource_id></resource_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
+ <resource_restriction>none</resource_restriction>
22
+ <resource_id></resource_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,12 +86,29 @@ 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')
67
93
  creator = author = design_dir = design_stage = nil
68
94
 
95
+ if doc.find('/x:testset/x:attributes').length == 0
96
+ n = doc.root.add('x:attributes')
97
+ end
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
103
+ if doc.find('/x:testset/x:attributes/x:theme').length == 0
104
+ n = doc.find('/x:testset/x:attributes').first
105
+ n.add('x:theme','extended')
106
+ end
107
+ if doc.find('/x:testset/x:attributes/x:info').length == 0
108
+ n = doc.find('/x:testset/x:attributes').first
109
+ n.add('x:info',name)
110
+ end
111
+
69
112
  if (dt = doc.find('/x:testset/x:attributes/x:creator')).length > 0
70
113
  dt.each do |e|
71
114
  creator = e.text
@@ -76,7 +119,6 @@ elsif command == 'convert'
76
119
  e.add('x:creator',creator)
77
120
  end
78
121
  end
79
- File.write(f + '.creator',creator)
80
122
 
81
123
  if (dt = doc.find('/x:testset/x:attributes/x:author')).length > 0
82
124
  dt.each do |e|
@@ -88,7 +130,6 @@ elsif command == 'convert'
88
130
  e.add('x:author',author)
89
131
  end
90
132
  end
91
- File.write(f + '.author',author)
92
133
 
93
134
  if (dt = doc.find('/x:testset/x:attributes/x:design_stage')).length > 0
94
135
  dt.each do |e|
@@ -100,14 +141,15 @@ elsif command == 'convert'
100
141
  e.add('x:design_stage',design_stage)
101
142
  end
102
143
  end
103
- File.write(f + '.stage',design_stage)
104
144
 
145
+ dd = ENV['PWD'] || Dir.pwd
146
+ ma = dd.scan(/\/([^\/]+\.dir)/)
147
+ design_dir = ma.join('/')
105
148
  if (dt = doc.find('/x:testset/x:attributes/x:design_dir')).length > 0
106
149
  dt.each do |e|
107
- design_dir = e.text
150
+ e.text = design_dir
108
151
  end
109
152
  else
110
- design_dir = Dir.pwd.sub(/^.*?models\/?/,'')
111
153
  doc.find('/x:testset/x:attributes').each do |e|
112
154
  e.add('x:design_dir',design_dir)
113
155
  end
@@ -118,9 +160,28 @@ elsif command == 'convert'
118
160
  e.text = name
119
161
  end
120
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
121
173
  end
122
174
  end
123
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
124
185
  elsif command == 'new'
125
186
  if !File.exists?(p1)
126
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/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,240 @@
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
+ console.log(data);
89
+ $('[data-class=guarded] abbr',clone).attr('title',data['guarded']);
90
+ $('[data-class=guarded] abbr',clone).text(data['guarded'].match(/none/i) ? '' : data['guarded'].charAt(0).toUpperCase());
91
+ $('[data-class=resource]',clone).text(data['guarded_what']);
92
+ }
93
+ $('[data-class=author]',clone).text(data['author']);
94
+ $('[data-class=date]',clone).text(new Date(data['date']).strftime('%Y-%m-%d, %H:%M:%S'));
95
+ $('#models tbody').append(clone);
96
+ });
97
+ }
98
+ });
99
+ }
100
+
101
+ function change_it(gdir,gstage) {
102
+ window.location.href = window.location.pathname + '?stage=' + gstage + '&dir=' + gdir;
103
+ }
104
+
105
+ $(document).ready(function() {
106
+ const queryString = window.location.search;
107
+ const urlParams = new URLSearchParams(queryString);
108
+
109
+ gstage = urlParams.get('stage') || 'draft';
110
+ gdir = urlParams.get('dir') ? (urlParams.get('dir') + '/').replace(/\/+/,'/') : '';
111
+
112
+ es_init(gdir,gstage);
113
+
114
+ var shifts = []
115
+ $.ajax({
116
+ type: "GET",
117
+ url: "server/",
118
+ data: { stages: 'stages' },
119
+ success: (r) => {
120
+ shifts = shifts.concat(r);
121
+ shifts = shifts.filter(item => item !== gstage);
122
+ }
123
+ });
124
+
125
+ $('input[name=stage]').val(gstage);
126
+ $('input[name=dir]').val(gdir);
127
+ $('ui-behind span').text(gstage);
128
+ $('ui-behind span').click((e) => {
129
+ if (shifts.length > 0) {
130
+ var menu = {};
131
+ menu['Change to'] = [];
132
+ shifts.forEach(ele => {
133
+ menu['Change to'].push(
134
+ {
135
+ 'label': ele,
136
+ 'function_call': change_it,
137
+ 'text_icon': '➔',
138
+ 'type': undefined,
139
+ 'class': 'capitalized',
140
+ 'params': [gdir,ele]
141
+ }
142
+ );
143
+ });
144
+ new CustomMenu(e).contextmenu(menu);
145
+ }
146
+ });
147
+
148
+ var dragged;
149
+ $('#models').on('drag','td[data-class=model]',false);
150
+ $('#models').on('dragstart','td[data-class=model]',(e) => {
151
+ dragged = $(e.currentTarget).parents('tr').find('td[data-class=name]').text();
152
+ });
153
+ $('#models').on('dragover','td[data-class=folder]',false);
154
+ $('#models').on('drop','td[data-class=folder]',(e) => {
155
+ e.preventDefault();
156
+ e.stopPropagation();
157
+ if (dragged) {
158
+ var todir = $(e.currentTarget).parents('tr').find('td[data-class=name]').text();
159
+ todir = todir.replace(/\./g,'');
160
+ if (todir != '') {
161
+ todir += '.dir';
162
+ }
163
+ move_it(dragged,todir);
164
+ dragged = undefined;
165
+ }
166
+ });
167
+ $('#models').on('click','td[data-class=ops]',(e) => {
168
+ var menu = {};
169
+ var name = $(e.currentTarget).parents('tr').find('td[data-class=name]').attr('data-full-name');
170
+ menu['Operations'] = [
171
+ {
172
+ 'label': 'Delete',
173
+ 'function_call': delete_it,
174
+ 'text_icon': '❌',
175
+ 'type': undefined,
176
+ 'params': [name]
177
+ },
178
+ {
179
+ 'label': 'Rename',
180
+ 'function_call': rename_it,
181
+ 'type': undefined,
182
+ 'text_icon': '📛',
183
+ 'params': [name]
184
+ }
185
+ ];
186
+ if (name.match(/\.xml$/)) {
187
+ menu['Operations'].unshift(
188
+ {
189
+ 'label': 'Duplicate',
190
+ 'function_call': duplicate_it,
191
+ 'text_icon': '➕',
192
+ 'type': undefined,
193
+ 'params': [name]
194
+ }
195
+ );
196
+ }
197
+ if (shifts.length > 0) {
198
+ menu['Shifting'] = [];
199
+ shifts.forEach(ele => {
200
+ menu['Shifting'].push(
201
+ {
202
+ 'label': 'Shift to ' + ele,
203
+ 'function_call': shift_it,
204
+ 'text_icon': '➔',
205
+ 'type': undefined,
206
+ 'params': [name,ele]
207
+ }
208
+ );
209
+ });
210
+ }
211
+ new CustomMenu(e).contextmenu(menu);
212
+ });
213
+
214
+ history.pushState({}, document.title, window.location.pathname + '?stage=' + gstage + '&dir=' + gdir);
215
+ paint(gdir,gstage);
216
+
217
+ $('#newmod').on('submit',(e) => {
218
+ $.ajax({
219
+ type: "POST",
220
+ url: "server/" + gdir,
221
+ data: { stage: gstage, new: $("#newmod input[name=new]").val() },
222
+ success: (r) => {
223
+ uidash_activate_tab($('ui-tab').first());
224
+ }
225
+ });
226
+ return false;
227
+ });
228
+
229
+ $('#newdir').on('submit',(e) => {
230
+ $.ajax({
231
+ type: "POST",
232
+ url: "server/",
233
+ data: { dir: $("#newdir input[name=newdir]").val() },
234
+ success: (r) => {
235
+ uidash_activate_tab($('ui-tab').first());
236
+ }
237
+ });
238
+ return false;
239
+ });
240
+ });
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.9
4
+ version: 1.0.15
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-06-22 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,9 @@ files:
60
80
  - server/moma.conf
61
81
  - server/testset.xml
62
82
  - tools/cpee-moma
83
+ - ui/css/design.css
84
+ - ui/index.html
85
+ - ui/js/design.js
63
86
  homepage: http://cpee.org/
64
87
  licenses:
65
88
  - LGPL-3.0
@@ -79,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
102
  - !ruby/object:Gem::Version
80
103
  version: '0'
81
104
  requirements: []
82
- rubygems_version: 3.1.4
105
+ rubygems_version: 3.1.6
83
106
  signing_key:
84
107
  specification_version: 4
85
108
  summary: "(Lifecycle) manage your process models in a directory or git repo."