icfs 0.2.0 → 0.3.0

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.
@@ -169,6 +169,7 @@ class Client
169
169
  when 'case_edit'; return _call_case_edit(env)
170
170
  when 'entry_edit'; return _call_entry_edit(env)
171
171
  when 'index_edit'; return _call_index_edit(env)
172
+ when 'action_edit'; return _call_action_edit(env)
172
173
  when 'config_edit'; return _call_config_edit(env)
173
174
 
174
175
  # view
@@ -304,6 +305,7 @@ class Client
304
305
  ['tags', :tags, :string].freeze,
305
306
  ['caseid', :caseid, :string].freeze,
306
307
  ['action', :action, :integer].freeze,
308
+ ['index', :index, :integer].freeze,
307
309
  ['after', :after, :time].freeze,
308
310
  ['before', :before, :time].freeze,
309
311
  ['stat', :stat, :string].freeze,
@@ -322,7 +324,7 @@ class Client
322
324
  [:action, :current].freeze,
323
325
  [:time, :entry].freeze,
324
326
  [:tags, nil].freeze,
325
- [:index, :entry].freeze,
327
+ [:indexes, nil].freeze,
326
328
  [:files, nil].freeze,
327
329
  [:stats, nil].freeze,
328
330
  [:title, :entry].freeze,
@@ -336,6 +338,7 @@ class Client
336
338
  ['after', :after, :time].freeze,
337
339
  ['before', :before, :time].freeze,
338
340
  ['user', :user, :string].freeze,
341
+ ['case_edit', :case_edit, :boolean].freeze,
339
342
  ['entry', :entry, :integer].freeze,
340
343
  ['index', :index, :integer].freeze,
341
344
  ['action', :action, :integer].freeze,
@@ -355,6 +358,7 @@ class Client
355
358
  [:entry, :log].freeze,
356
359
  [:action, :log].freeze,
357
360
  [:index, :log].freeze,
361
+ [:case, :log].freeze,
358
362
  ].freeze
359
363
 
360
364
 
@@ -541,9 +545,9 @@ class Client
541
545
  tpl = api.case_read(tid)
542
546
  tpl['title'] = ''
543
547
  parts = [
544
- _form_entry(env, tid, nil),
545
548
  _form_create(env),
546
549
  _form_case(env, tpl),
550
+ _form_entry(env, tid, nil),
547
551
  ]
548
552
  body = [
549
553
  _div_nav(env),
@@ -593,8 +597,8 @@ class Client
593
597
  if env['REQUEST_METHOD'] == 'GET'
594
598
  cse = api.case_read(cid)
595
599
  parts = [
596
- _form_entry(env, cid, nil),
597
600
  _form_case(env, cse),
601
+ _form_entry(env, cid, nil, {enable: false}),
598
602
  ]
599
603
  body = [
600
604
  _div_nav(env),
@@ -610,19 +614,18 @@ class Client
610
614
  # process
611
615
  cse = _post_case(env, para)
612
616
  ent = _post_entry(env, para)
613
- act = _post_action(env, para)
614
- if act.is_a?(Integer)
615
- ent['action'] = act if act != 0
616
- act = nil
617
- end
618
- ent['caseid'] = cid
617
+ cse['caseid'] = cid
619
618
  cse_old = api.case_read(cid)
620
619
  cse['template'] = cse_old['template']
621
- api.record(ent, act, nil, cse)
620
+ api.record(ent, nil, nil, cse)
622
621
 
623
622
  # display the case
624
- body = _div_nav(env) + _div_case(env, cse)
625
- return _resp_success(env, body)
623
+ body = [
624
+ _div_nav(env),
625
+ _div_case(env, cse),
626
+ ]
627
+ body << _div_entry(env, ent) if ent
628
+ return _resp_success(env, body.join(''))
626
629
  end
627
630
  end # def _call_case_edit()
628
631
 
@@ -660,16 +663,14 @@ class Client
660
663
  end
661
664
 
662
665
  # build form
663
- parts = [ _form_entry(env, cid, ent) ]
664
- if !ent &&
665
- (act || api.access_list(cid).include?(ICFS::PermAction))
666
- parts << _form_action(env, cid, act, {edit: false})
667
- end
666
+ opts = {}
667
+ opts[:enable] = true if enum == 0
668
+ opts[:action] = anum if anum
669
+ parts = [ _form_entry(env, cid, ent, opts) ]
668
670
  body = [
669
671
  _div_nav(env),
670
672
  _div_desc(desc, ''),
671
- _div_form(env, '/entry_edit/', cid, parts,
672
- 'Record Entry'),
673
+ _div_form(env, '/entry_edit/', cid, parts, 'Record Entry'),
673
674
  ].join('')
674
675
  return _resp_success(env, body)
675
676
 
@@ -679,20 +680,15 @@ class Client
679
680
 
680
681
  # process
681
682
  ent = _post_entry(env, para)
682
- act = _post_action(env, para)
683
- if act.is_a?(Integer)
684
- ent['action'] = act if act != 0
685
- act = nil
686
- end
683
+ raise(Error::Values, 'Entry form not enabled') unless ent
687
684
  ent['caseid'] = cid
688
- api.record(ent, act, nil, nil)
685
+ api.record(ent, nil, nil, nil)
689
686
 
690
687
  # display the entry
691
688
  body = [
692
689
  _div_nav(env),
693
690
  _div_entry(env, ent)
694
691
  ]
695
- body << _div_action(env, act) if act
696
692
  return _resp_success(env, body.join(''))
697
693
  end
698
694
  end # def _call_entry_edit()
@@ -719,8 +715,8 @@ class Client
719
715
  xnum = _util_num(env, 2)
720
716
  idx = api.index_read(cid, xnum) if xnum != 0
721
717
  parts = [
722
- _form_entry(env, cid, nil),
723
718
  _form_index(env, cid, idx),
719
+ _form_entry(env, cid, nil, {enable: false}),
724
720
  ]
725
721
  desc = idx ? 'Edit Index' : 'New Index'
726
722
  body = [
@@ -737,24 +733,76 @@ class Client
737
733
 
738
734
  # process
739
735
  ent = _post_entry(env, para)
740
- act = _post_action(env, para)
741
736
  idx = _post_index(env, para)
742
- if act.is_a?(Integer)
743
- ent['action'] = act if act != 0
744
- act = nil
745
- end
746
- ent['caseid'] = cid
747
- api.record(ent, act, idx, nil)
737
+ idx['caseid'] = cid
738
+ api.record(ent, nil, idx, nil)
748
739
 
749
740
  # display the index
750
741
  body = [
751
742
  _div_nav(env),
752
- _div_entry(env, ent),
753
- _div_index(env, idx)
743
+ _div_index(env, idx),
744
+ ]
745
+ body << _div_entry(env, ent) if ent
746
+ return _resp_success(env, body.join(''))
747
+ end
748
+ end # def _call_index_edit()
749
+
750
+
751
+ ###############################################
752
+ # Edit an Action
753
+ #
754
+ def _call_action_edit(env)
755
+ env['icfs.page'] = 'Action Edit'
756
+ api = env['icfs']
757
+ _verb_getpost(env)
758
+
759
+ cid = _util_case(env)
760
+
761
+ # get the form
762
+ if env['REQUEST_METHOD'] == 'GET'
763
+ anum = _util_num(env, 2)
764
+
765
+ # see if editing is possible
766
+ unless( api.access_list(cid).include?(ICFS::PermAction) ||
767
+ ((anum != 0) && api.tasked?(cid, anum)) )
768
+ raise(Error::Perms, 'Not able to edit this action.')
769
+ end
770
+
771
+ act = api.action_read(cid, anum) if anum != 0
772
+ opts = {enable: false}
773
+ opts[:action] = anum if act
774
+ parts = [
775
+ _form_action(env, cid, act),
776
+ _form_entry(env, cid, nil, opts),
777
+ ]
778
+ desc = act ? 'Edit Action' : 'New Action'
779
+ body = [
780
+ _div_nav(env),
781
+ _div_desc(desc, ''),
782
+ _div_form(env, '/action_edit/', cid, parts,
783
+ 'Record Action'),
754
784
  ].join('')
755
785
  return _resp_success(env, body)
786
+
787
+ # post the form
788
+ elsif env['REQUEST_METHOD'] == 'POST'
789
+ para = _util_post(env)
790
+
791
+ # process
792
+ ent = _post_entry(env, para)
793
+ act = _post_action(env, para)
794
+ act['caseid'] = cid
795
+ api.record(ent, act, nil, nil)
796
+
797
+ # display the index
798
+ body = [
799
+ _div_nav(env),
800
+ _div_action(env, act),
801
+ ]
802
+ body << _div_entry(env, ent) if ent
803
+ return _resp_success(env, body.join(''))
756
804
  end
757
- end # def _call_index_edit()
805
+ end # def _call_action_edit()
758
806
 
759
807
 
760
808
  ###############################################
@@ -819,17 +867,15 @@ class Client
819
867
  cid = _util_case(env)
820
868
  lnum = _util_num(env, 2)
821
869
  cse = api.case_read(cid, lnum)
822
- if lnum != 0
823
- msg = 'This is a historical version of this Case'
824
- else
825
- msg = ''
826
- end
870
+ ent = api.entry_read(cid, cse['entry']) if cse['entry']
871
+ msg = (lnum != 0) ? 'This is a historical version of this Case' : ''
827
872
  body = [
828
873
  _div_nav(env),
829
874
  _div_desc('Case Information', msg),
830
875
  _div_case(env, cse),
831
- ].join('')
832
- return _resp_success(env, body)
876
+ ]
877
+ body << _div_entry(env, ent) if ent
878
+ return _resp_success(env, body.join(''))
833
879
  end # def _call_case()
834
880
 
835
881
 
@@ -891,31 +937,37 @@ class Client
891
937
  lnum = _util_num(env, 3)
892
938
  raise(Error::Interface, 'No Action requested') if anum == 0
893
939
 
894
- # get the action
895
940
  act = api.action_read(cid, anum, lnum)
941
+ ent = api.entry_read(cid, act['entry']) if act['entry']
942
+ ent_div = _div_entry(env, ent) if ent
943
+
944
+ # historical
896
945
  if lnum != 0
897
946
  msg = 'This is a historical version of this Action'
947
+ list_div = ''
948
+
949
+ # current
898
950
  else
899
951
  msg = ''
952
+ query = {
953
+ caseid: cid,
954
+ action: anum,
955
+ purpose: 'Action Entries',
956
+ }
957
+ resp = api.entry_search(query)
958
+ list_div = _div_list(env, resp, ListEntry) +
959
+ _div_page(resp){|qu, txt| _a_entry_search(env, qu, txt)}
900
960
  end
901
961
 
902
- # get the entries
903
- query = {
904
- caseid: cid,
905
- action: anum,
906
- purpose: 'Action Entries',
907
- }
908
- resp = api.entry_search(query)
909
-
910
962
  # display
911
963
  body = [
912
964
  _div_nav(env),
913
965
  _div_desc('View Action', msg),
914
966
  _div_action(env, act),
915
- _div_list(env, resp, ListEntry),
916
- _div_page(resp){|qu, txt| _a_entry_search(env, qu, txt)},
917
- ].join('')
918
- return _resp_success(env, body)
967
+ ent_div,
968
+ list_div
969
+ ]
970
+ return _resp_success(env, body.join(''))
919
971
  end # def _call_action()
920
972
 
921
973
 
@@ -931,30 +983,37 @@ class Client
931
983
  lnum = _util_num(env, 3)
932
984
  raise(Error::Interface, 'No Index requested') if xnum == 0
933
985
 
934
- # get the index
986
+
935
987
  idx = api.index_read(cid, xnum, lnum)
988
+ ent = api.entry_read(cid, idx['entry']) if idx['entry']
989
+ ent_div = ent ? _div_entry(env, ent) : ''
990
+
991
+ # historical index
936
992
  if lnum != 0
937
993
  msg = 'This is a historical version of this Index'
994
+ list_div = ''
995
+
996
+ # current index
938
997
  else
939
998
  msg = ''
999
+ query = {
1000
+ caseid: cid,
1001
+ index: xnum
1002
+ }
1003
+ resp = api.entry_search(query)
1004
+ list_div = _div_list(env, resp, ListEntry) +
1005
+ _div_page(resp){|qu, txt| _a_entry_search(env, qu, txt)}
940
1006
  end
941
1007
 
942
- # get the entries
943
- query = {
944
- caseid: cid,
945
- index: xnum
946
- }
947
- resp = api.entry_search(query)
948
-
949
1008
  # display
950
1009
  body = [
951
- _div_nav(env) +
1010
+ _div_nav(env),
952
1011
  _div_desc('View Index', msg),
953
1012
  _div_index(env, idx),
954
- _div_list(env, resp, ListEntry),
955
- _div_page(resp){|qu, txt| _a_entry_search(env, qu, txt)},
956
- ].join('')
957
- return _resp_success(env, body)
1013
+ ent_div,
1014
+ list_div
1015
+ ]
1016
+ return _resp_success(env, body.join(''))
958
1017
  end # def _call_index()
959
1018
 
960
1019
 
@@ -1177,17 +1236,19 @@ class Client
1177
1236
  entry: 'list-int',
1178
1237
  action: 'list-int',
1179
1238
  index: 'list-int',
1239
+ indexes: 'list-int-sm',
1240
+ case: 'list-int',
1180
1241
  log: 'list-int',
1181
- tags: 'list-int',
1242
+ tags: 'list-int-sm',
1182
1243
  tag: 'list-tag',
1183
- stats: 'list-int',
1244
+ stats: 'list-int-sm',
1184
1245
  time: 'list-time',
1185
1246
  title: 'list-title',
1186
1247
  caseid: 'list-caseid',
1187
1248
  stat: 'list-stat',
1188
1249
  sum: 'list-float',
1189
1250
  count: 'list-int',
1190
- files: 'list-int',
1251
+ files: 'list-int-sm',
1191
1252
  user: 'list-usergrp',
1192
1253
  }.freeze
1193
1254
 
@@ -1218,6 +1279,10 @@ class Client
1218
1279
  end
1219
1280
  head = DivListHead % hcols.join('')
1220
1281
 
1282
+ # do we do relative times?
1283
+ cfg = env['icfs'].config
1284
+ rel_time = cfg.get('rel_time')
1285
+
1221
1286
  # search results into rows
1222
1287
  rows = resp[:list].map do |sr|
1223
1288
  obj = sr[:object]
@@ -1226,6 +1291,7 @@ class Client
1226
1291
  cols = list.map do |sym, opt|
1227
1292
  it = obj[sym]
1228
1293
  cc = ListColClass[sym]
1294
+ ct = nil
1229
1295
 
1230
1296
  # snippets are special non-column, not in the object itself
1231
1297
  if sym == :snippet
@@ -1257,7 +1323,7 @@ class Client
1257
1323
  when :current
1258
1324
  cd = _a_entry(env, cid, it, 0, it.to_s)
1259
1325
  when :log
1260
- cd = _a_entry(env, cid, it, obj[:log], it.to_s)
1326
+ cd = (it != 0) ? _a_entry(env, cid, it, obj[:log], it.to_s) : ''
1261
1327
  else
1262
1328
  cd = it.to_s
1263
1329
  end
@@ -1268,11 +1334,7 @@ class Client
1268
1334
  when :current
1269
1335
  cd = (it == 0) ? '' : _a_action(env, cid, it, 0, it.to_s)
1270
1336
  when :log
1271
- if it != 0
1272
- cd = _a_action(env, cid, it, obj[:log], it.to_s)
1273
- else
1274
- cd = ''
1275
- end
1337
+ cd = (it != 0) ? _a_action(env, cid, it, obj[:log], it.to_s) : ''
1276
1338
  else
1277
1339
  cd = it == 0 ? '' : it.to_s
1278
1340
  end
@@ -1280,8 +1342,6 @@ class Client
1280
1342
  # index
1281
1343
  when :index
1282
1344
  case opt
1283
- when :entry
1284
- cd = (it == 0) ? '' : it.to_s
1285
1345
  when :current
1286
1346
  cd = _a_index(env, cid, it, 0, it.to_s)
1287
1347
  when :log
@@ -1294,8 +1354,21 @@ class Client
1294
1354
  cd = it.to_s
1295
1355
  end
1296
1356
 
1357
+ # case
1358
+ when :case
1359
+ case opt
1360
+ when :log
1361
+ cd = (it != 0) ? _a_case(env, cid, obj[:log], 'Y') : ''
1362
+ else
1363
+ cd = ''
1364
+ end
1365
+
1366
+ # indexes
1367
+ when :indexes
1368
+ cd = (it == 0) ? '' : it.to_s
1369
+
1297
1370
  # log
1298
- when :log
1371
+ when :log
1299
1372
  case opt
1300
1373
  when :link
1301
1374
  cd = _a_log(env, cid, it, it.to_s)
@@ -1332,13 +1405,20 @@ class Client
1332
1405
 
1333
1406
  # time
1334
1407
  when :time
1408
+ if rel_time
1409
+ tme = ICFS.time_relative(it)
1410
+ ct = ICFS.time_weekday(it, cfg)
1411
+ else
1412
+ tme = ICFS.time_weekday(it, cfg)
1413
+ end
1414
+
1335
1415
  case opt
1336
1416
  when :entry
1337
- cd = _a_entry(env, cid, obj[:entry], 0, _util_time(env, it))
1417
+ cd = _a_entry(env, cid, obj[:entry], 0, tme)
1338
1418
  when :log
1339
- cd = _a_log(env, cid, obj[:log], _util_time(env, it))
1419
+ cd = _a_log(env, cid, obj[:log], tme)
1340
1420
  else
1341
- cd = _util_time(env, it)
1421
+ cd = tme
1342
1422
  end
1343
1423
 
1344
1424
  # title
@@ -1400,7 +1480,15 @@ class Client
1400
1480
  raise NotImplementedError, sym.to_s
1401
1481
  end
1402
1482
 
1403
- cd ? (DivListItem % [cc, cd]) : ''
1483
+ if cd
1484
+ if ct
1485
+ DivListItemTitle % [cc, ct, cd]
1486
+ else
1487
+ DivListItem % [cc, cd]
1488
+ end
1489
+ else
1490
+ ''
1491
+ end
1404
1492
  end
1405
1493
 
1406
1494
  DivListRow % cols.join('')
@@ -1429,15 +1517,19 @@ class Client
1429
1517
  # Search results header items
1430
1518
  DivListHeadItems = {
1431
1519
  tags: '
1432
- <div class="list-int">Tags</div>',
1520
+ <div class="list-int-sm" title="Number of tags">#T</div>',
1433
1521
  tag: '
1434
1522
  <div class="list-tag">Tag</div>',
1435
1523
  entry: '
1436
1524
  <div class="list-int">Entry</div>',
1437
1525
  index: '
1438
1526
  <div class="list-int">Index</div>',
1527
+ indexes: '
1528
+ <div class="list-int-sm" title="Number of Indexes">#I</div>',
1439
1529
  action: '
1440
1530
  <div class="list-int">Action</div>',
1531
+ case: '
1532
+ <div class="list-int">Case</div>',
1441
1533
  log: '
1442
1534
  <div class="list-int">Log</div>',
1443
1535
  title: '
@@ -1445,7 +1537,7 @@ class Client
1445
1537
  caseid: '
1446
1538
  <div class="list-caseid">Case ID</div>',
1447
1539
  stats: '
1448
- <div class="list-int">Stats</div>',
1540
+ <div class="list-int-sm" title="Number of stats">#S</div>',
1449
1541
  time: '
1450
1542
  <div class="list-time">Date/Time</div>',
1451
1543
  stat: '
@@ -1455,7 +1547,7 @@ class Client
1455
1547
  count: '
1456
1548
  <div class="list-int">Count</div>',
1457
1549
  files: '
1458
- <div class="list-int">Files</div>',
1550
+ <div class="list-int-sm" title="Number of files">#F</div>',
1459
1551
  user: '
1460
1552
  <div class="list-usergrp">User</div>',
1461
1553
  snippet: ''
@@ -1465,6 +1557,10 @@ class Client
1465
1557
  DivListItem = '
1466
1558
  <div class="%s">%s</div>'
1467
1559
 
1560
+ # search results item with title
1561
+ DivListItemTitle = '
1562
+ <div class="%s" title="%s">%s</div>'
1563
+
1468
1564
 
1469
1565
  ###############################################
1470
1566
  # Page description div
@@ -1779,7 +1875,8 @@ class Client
1779
1875
 
1780
1876
  # case links
1781
1877
  links = [
1782
- _a_log_search(env, {caseid: cid}, 'History of Case'),
1878
+ _a_log_search(env, {caseid: cid, case_edit: true}, 'History of Case'),
1879
+ _a_log_search(env, {caseid: cid}, 'All Logs'),
1783
1880
  ]
1784
1881
  if al.include?(ICFS::PermManage)
1785
1882
  links << _a_case_edit(env, cid, 'Edit This Case')
@@ -1793,13 +1890,14 @@ class Client
1793
1890
  if al.include?(ICFS::PermAction)
1794
1891
  now = Time.now.to_i
1795
1892
  actions = [
1893
+ _a_action_edit(env, cid, 0, 'New Action'),
1796
1894
  _a_action_search(env, {
1797
1895
  caseid: cid,
1798
1896
  assigned: ICFS::UserCase,
1799
1897
  status: true,
1800
1898
  flag: true,
1801
1899
  purpose: 'Flagged Actions',
1802
- }, 'flagged'),
1900
+ }, 'List flagged'),
1803
1901
  _a_action_search(env, {
1804
1902
  caseid: cid,
1805
1903
  assigned: ICFS::UserCase,
@@ -1807,7 +1905,7 @@ class Client
1807
1905
  before: now,
1808
1906
  sort: 'time_asc',
1809
1907
  purpose: 'Actions - Past Date',
1810
- }, 'past'),
1908
+ }, 'List past'),
1811
1909
  _a_action_search(env, {
1812
1910
  caseid: cid,
1813
1911
  assigned: ICFS::UserCase,
@@ -1815,19 +1913,19 @@ class Client
1815
1913
  after: now,
1816
1914
  sort: 'time_desc',
1817
1915
  purpose: 'Actions - Future Date',
1818
- }, 'future'),
1916
+ }, 'List future'),
1819
1917
  _a_action_search(env, {
1820
1918
  caseid: cid,
1821
1919
  assigned: ICFS::UserCase,
1822
1920
  status: true,
1823
1921
  purpose: 'Open Actions',
1824
- }, 'all open'),
1922
+ }, 'List open'),
1825
1923
  _a_action_tags(env, {
1826
1924
  caseid: cid,
1827
1925
  assigned: ICFS::UserCase,
1828
1926
  status: true,
1829
1927
  purpose: 'Open Action Tags',
1830
- }, 'tags'),
1928
+ }, 'Action tags'),
1831
1929
  ].map{|lk| DivCaseLink % lk}
1832
1930
  actions = DivCaseActions % actions.join('')
1833
1931
  else
@@ -2051,7 +2149,7 @@ class Client
2051
2149
  action,
2052
2150
  links.map{|lk| DivEntryLink % lk }.join(''),
2053
2151
  Rack::Utils.escape_html(ent['title']),
2054
- _util_time(env, ent['time']),
2152
+ ICFS.time_weekday(ent['time'], api.config),
2055
2153
  Rack::Utils.escape_html(ent['content']),
2056
2154
  tags.join("\n"),
2057
2155
  index,
@@ -2181,19 +2279,26 @@ class Client
2181
2279
  def _div_log(env, log)
2182
2280
  cid = log['caseid']
2183
2281
  lnum = log['log']
2184
- enum = log['entry']['num']
2185
2282
 
2186
2283
  navp = (lnum == 1) ? 'prev' : _a_log(env, cid, lnum-1, 'prev')
2187
2284
  navn = _a_log(env, cid, lnum + 1, 'next')
2188
2285
 
2189
- time = _util_time(env, log['time'])
2190
-
2191
- if log['case_hash']
2192
- chash = DivLogCase % _a_case(env, cid, lnum, log['case_hash'])
2286
+ if log['case']
2287
+ chash = DivLogCase % _a_case(env, cid, lnum, log['case']['hash'])
2193
2288
  else
2194
2289
  chash = ''
2195
2290
  end
2196
2291
 
2292
+ if log['entry']
2293
+ enum = log['entry']['num']
2294
+ entry = DivLogEntry % [
2295
+ _a_entry(env, cid, enum, lnum, log['entry']['hash']),
2296
+ enum
2297
+ ]
2298
+ else
2299
+ entry = ''
2300
+ end
2301
+
2197
2302
  if log['action']
2198
2303
  action = DivLogAction % [
2199
2304
  _a_action(env, cid, log['action']['num'], lnum, log['action']['hash']),
@@ -2231,11 +2336,10 @@ class Client
2231
2336
  log['log'],
2232
2337
  navp,
2233
2338
  navn,
2234
- _util_time(env, log['time']),
2339
+ ICFS.time_weekday(log['time'], env['icfs'].config),
2235
2340
  Rack::Utils.escape_html(log['user']),
2236
2341
  log['prev'],
2237
- _a_entry(env, cid, enum, lnum, log['entry']['hash']),
2238
- enum,
2342
+ entry,
2239
2343
  chash,
2240
2344
  action,
2241
2345
  index,
@@ -2275,14 +2379,18 @@ class Client
2275
2379
  <div class="list-row">
2276
2380
  <div class="list-label">Prev:</div>
2277
2381
  <div class="list-hash">%s</div>
2278
- </div>
2382
+ </div>%s%s%s%s%s
2383
+ </div>
2384
+ </div>'
2385
+
2386
+
2387
+ # log entry
2388
+ DivLogEntry = '
2279
2389
  <div class="list-row">
2280
2390
  <div class="list-label">Entry:</div>
2281
2391
  <div class="list-hash">%s</div>
2282
2392
  <div class="list-int">%d</div>
2283
- </div>%s%s%s%s
2284
- </div>
2285
- </div>'
2393
+ </div>'
2286
2394
 
2287
2395
 
2288
2396
  # log action
@@ -2344,7 +2452,7 @@ class Client
2344
2452
 
2345
2453
  links = []
2346
2454
  anum = act['action']
2347
- links << _a_entry_edit(env, cid, 0, anum, 'New Entry in Action')
2455
+ links << _a_action_edit(env, cid, anum, 'Edit this Action')
2348
2456
 
2349
2457
  lnum = act['log']
2350
2458
  links << _a_log_search(env, {
@@ -2353,6 +2461,8 @@ class Client
2353
2461
  'purpose' => 'Action History',
2354
2462
  }, 'History of Action')
2355
2463
 
2464
+ links << _a_entry_edit(env, cid, 0, anum, 'New Entry in Action')
2465
+
2356
2466
  # each task
2357
2467
  tasks = []
2358
2468
  ta = act['tasks']
@@ -2379,7 +2489,7 @@ class Client
2379
2489
  Rack::Utils.escape_html(tk['title']),
2380
2490
  tk['status'] ? 'Open' : 'Closed',
2381
2491
  tk['flag'] ? 'Raised' : 'Normal',
2382
- _util_time(env, tk['time']),
2492
+ ICFS.time_weekday(tk['time'], api.config),
2383
2493
  tags.join(''),
2384
2494
  ]
2385
2495
  end
@@ -2549,6 +2659,7 @@ class Client
2549
2659
  # Description div for queries
2550
2660
  #
2551
2661
  def _div_query(env, type, sup, query, disp=false)
2662
+ cfg = env['icfs'].config
2552
2663
 
2553
2664
  # query purpose
2554
2665
  if query[:purpose]
@@ -2571,7 +2682,7 @@ class Client
2571
2682
  when :integer
2572
2683
  para = val.to_s
2573
2684
  when :time
2574
- para = _util_time(env, val)
2685
+ para = ICFS.time_local(val, cfg)
2575
2686
  else
2576
2687
  raise NotImplementedError, pr.to_s
2577
2688
  end
@@ -2613,6 +2724,7 @@ class Client
2613
2724
  # Query form
2614
2725
  #
2615
2726
  def _form_query(env, sup, query, act, disp=false)
2727
+ cfg = env['icfs'].config
2616
2728
 
2617
2729
  # supported params
2618
2730
  inputs = sup.map do |txt, sym, pr|
@@ -2678,6 +2790,10 @@ class Client
2678
2790
  ilabel = 'Permission'
2679
2791
  iclass = 'form-perm'
2680
2792
  ihint = 'Filter for cases granting this permission.'
2793
+ when :case_edit
2794
+ ilabel = 'Case edited'
2795
+ iclass = 'form-boolean'
2796
+ ihint = 'Filter for logs recoding a case.'
2681
2797
  when :entry
2682
2798
  ilabel = 'Entry'
2683
2799
  iclass = 'form-int'
@@ -2726,7 +2842,7 @@ class Client
2726
2842
  ivalue = query[sym] ? query[sym].to_s : ''
2727
2843
  when :time
2728
2844
  itype = 'text'
2729
- ivalue = query[sym] ? _util_time(env, query[sym]) : ''
2845
+ ivalue = query[sym] ? ICFS.time_local(query[sym], cfg) : ''
2730
2846
  else
2731
2847
  raise NotImplementedError, pr.to_s
2732
2848
  end
@@ -2945,7 +3061,13 @@ class Client
2945
3061
  #############################################
2946
3062
  # New entry form
2947
3063
  #
2948
- def _form_entry(env, cid, ent=nil)
3064
+ # @param env [Hash] Rack enviornment
3065
+ # @param cid [String] caseid
3066
+ # @param ent [Hash] the Entry
3067
+ # @param opts [Hash] options
3068
+ #
3069
+ #
3070
+ def _form_entry(env, cid, ent=nil, opts={})
2949
3071
  api = env['icfs']
2950
3072
 
2951
3073
  # title
@@ -2957,11 +3079,20 @@ class Client
2957
3079
 
2958
3080
  # time
2959
3081
  if ent && ent['time']
2960
- time = _util_time(env, ent['time'])
3082
+ time = ICFS.time_local(ent['time'], api.config)
2961
3083
  else
2962
3084
  time = ''
2963
3085
  end
2964
3086
 
3087
+ # action
3088
+ if opts[:action]
3089
+ anum = opts[:action]
3090
+ elsif ent && ent['action']
3091
+ anum = ent['action']
3092
+ else
3093
+ anum = 0
3094
+ end
3095
+
2965
3096
  # content
2966
3097
  if ent && ent['content']
2967
3098
  content = Rack::Utils.escape_html(ent['content'])
@@ -3070,8 +3201,11 @@ class Client
3070
3201
  end
3071
3202
 
3072
3203
  return FormEntry % [
3204
+ opts[:enable] ? 'true' : 'false',
3073
3205
  ent ? ent['entry'] : 0,
3074
- (ent && ent['action']) ? ent['action'] : 0,
3206
+ anum,
3207
+ opts[:enable] ? '' : FormEntryEnable,
3208
+ opts[:enable] ? '' : ' hidden',
3075
3209
  title, time, content,
3076
3210
  tags_cnt, tags,
3077
3211
  files_cnt, files,
@@ -3084,6 +3218,15 @@ class Client
3084
3218
  end # def _form_entry
3085
3219
 
3086
3220
 
3221
+ # entry toggle button
3222
+ FormEntryEnable = '
3223
+ <div class="sect-right">
3224
+ <button id="ent-ena-button" class="ent-ena" type="button"
3225
+ onclick="entEnable()">Toggle Edit
3226
+ </button>
3227
+ </div>'.freeze
3228
+
3229
+
3087
3230
  # entry edit form
3088
3231
  FormEntry = '
3089
3232
  <div class="sect">
@@ -3093,9 +3236,14 @@ class Client
3093
3236
  Describe the activity.
3094
3237
  </div></div>
3095
3238
  <div class="sect-fill"> </div>
3239
+ <input id="ent-ena" name="ent-ena" type="hidden" value="%s">
3096
3240
  <input name="ent-num" type="hidden" value="%d">
3097
- <input name="ent-act" type="hidden" value="%d">
3241
+ <input name="ent-act" type="hidden" value="%d">%s
3098
3242
  </div>
3243
+ </div>
3244
+ <div id="ent-body" class="ent-body%s">
3245
+
3246
+ <div class="sect">
3099
3247
  <div class="form-row">
3100
3248
  <div class="list-label">Title:</div>
3101
3249
  <input class="form-title" name="ent-title" type="text"
@@ -3210,6 +3358,7 @@ class Client
3210
3358
  <input type="hidden" name="ent-perm-cnt" id="ent-perm-cnt" value="%d">
3211
3359
  <div class="perms-list" id="ent-perm-list">%s
3212
3360
  </div>
3361
+ </div>
3213
3362
  </div>'
3214
3363
 
3215
3364
 
@@ -3295,8 +3444,9 @@ class Client
3295
3444
  ###############################################
3296
3445
  # Action form
3297
3446
  #
3298
- def _form_action(env, cid, act = nil, opt={})
3447
+ def _form_action(env, cid, act = nil)
3299
3448
  api = env['icfs']
3449
+ cfg = api.config
3300
3450
 
3301
3451
  # new action
3302
3452
  if !act
@@ -3324,17 +3474,6 @@ class Client
3324
3474
  ur.add api.user
3325
3475
  ur.merge api.roles
3326
3476
 
3327
- # editing
3328
- if opt[:edit]
3329
- ena_val = 'true'
3330
- ena_class_add = ''
3331
- ena_class_tasks = ''
3332
- else
3333
- ena_val = 'false'
3334
- ena_class_add = ' invisible'
3335
- ena_class_tasks = ' hidden'
3336
- end
3337
-
3338
3477
  # each task
3339
3478
  tasks = []
3340
3479
  ta.each_index do |ixr|
@@ -3361,7 +3500,7 @@ class Client
3361
3500
  flag = FormActionFlagEd % [
3362
3501
  ix, tk['flag'] ? ' checked' : '' ]
3363
3502
  if tk['time']
3364
- time = FormActionTimeEd % [ ix, _util_time(env, tk['time']) ]
3503
+ time = FormActionTimeEd % [ ix, ICFS.time_local(tk['time'], cfg) ]
3365
3504
  else
3366
3505
  time = FormActionTimeEd % [ix, '']
3367
3506
  end
@@ -3395,7 +3534,7 @@ class Client
3395
3534
  else
3396
3535
  flag = FormActionFlagEd % [ ix, '' ]
3397
3536
  end
3398
- esc = _util_time(env, tk['time'])
3537
+ esc = ICFS.time_local(tk['time'], cfg)
3399
3538
  time = FormActionTimeRo % [ ix, esc, esc ]
3400
3539
 
3401
3540
  tags_cnt = 0
@@ -3422,11 +3561,8 @@ class Client
3422
3561
 
3423
3562
  return FormAction % [
3424
3563
  act ? act['action'] : 0,
3425
- ena_class_add,
3426
- ena_val,
3427
3564
  tasks.size,
3428
3565
  act ? act['action'] : 0,
3429
- ena_class_tasks,
3430
3566
  tasks.join('')
3431
3567
  ]
3432
3568
  end # def _form_action()
@@ -3439,24 +3575,18 @@ class Client
3439
3575
  <div class="sect-label">Action</div>
3440
3576
  <div class="tip"><div class="tip-disp"></div><div class="tip-info">
3441
3577
  A unit of work, accomplished in a set of related real-world
3442
- and administrative activitires.
3578
+ and administrative activities.
3443
3579
  </div></div>
3444
3580
  <div class="sect-fill"> </div>
3445
3581
  <input name="act-num" type="hidden" value="%d">
3446
- <div class="sect-right">
3447
- <button id="act-ena-button" class="act-ena" type="button"
3448
- onclick="actEnable()">Toggle Edit
3449
- </button>
3450
- </div>
3451
- <div id="act-task-add" class="sect-right%s">
3582
+ <div id="act-task-add" class="sect-right">
3452
3583
  <button class="tsk-add" type="button" onclick="actAddTask()">+
3453
3584
  </button>
3454
3585
  </div>
3455
- <input id="act-ena" name="act-ena" type="hidden" value="%s">
3456
3586
  <input id="act-cnt" name="act-cnt" type="hidden" value="%d">
3457
3587
  <input type="hidden" name="act-num" value="%d">
3458
3588
  </div>
3459
- <div id="act-tasks" class="%s">%s
3589
+ <div id="act-tasks">%s
3460
3590
  </div>
3461
3591
  </div>'
3462
3592
 
@@ -3685,8 +3815,10 @@ class Client
3685
3815
  # Config Form
3686
3816
  #
3687
3817
  def _form_config(env)
3688
- tz = env['icfs'].config.get('tz')
3689
- return FormConfig % [tz]
3818
+ cfg = env['icfs'].config
3819
+ tz = cfg.get('tz')
3820
+ rel_time = cfg.get('rel_time') ? 'true' : 'false'
3821
+ return FormConfig % [tz, rel_time]
3690
3822
  end # def _form_config()
3691
3823
 
3692
3824
 
@@ -3707,6 +3839,13 @@ class Client
3707
3839
  Timezone to display date/times, format as +/-HH:MM.
3708
3840
  </div></div>
3709
3841
  </div>
3842
+ <div class="form-row">
3843
+ <div class="list-label">Rel. Time:</div>
3844
+ <input class="form-boolean" name="cfg-reltime" type="text" value="%s">
3845
+ <div class="tip"><div class="tip-disp"></div><div class="tip-info">
3846
+ Display relative times e.g. 3 days ago.
3847
+ </div></div>
3848
+ </div>
3710
3849
  </div>'
3711
3850
 
3712
3851
 
@@ -3800,6 +3939,8 @@ class Client
3800
3939
  # Entry edit
3801
3940
  #
3802
3941
  def _post_entry(env, para)
3942
+ return nil unless para['ent-ena'] == 'true'
3943
+
3803
3944
  api = env['icfs']
3804
3945
 
3805
3946
  # entry object
@@ -3933,17 +4074,12 @@ class Client
3933
4074
  # Action edit
3934
4075
  #
3935
4076
  def _post_action(env, para)
3936
-
3937
- # action object
3938
4077
  act = {}
3939
4078
 
3940
4079
  # action
3941
4080
  anum = para['act-num'].to_i
3942
4081
  act['action'] = anum if anum != 0
3943
4082
 
3944
- # any edit?
3945
- return anum unless para['act-ena'] == 'true'
3946
-
3947
4083
  # tasks
3948
4084
  tasks = []
3949
4085
  acnt = para['act-cnt'].to_i
@@ -3952,6 +4088,7 @@ class Client
3952
4088
  tx = 'act-%d' % [ix + 1]
3953
4089
 
3954
4090
  ug = para[tx + '-task']
4091
+ next if ug.nil? || ug.empty?
3955
4092
  title = para[tx + '-title']
3956
4093
  status = (para[tx + '-status'] == 'true') ? true : false
3957
4094
  flag = (para[tx + '-flag'] == 'true') ? true : false
@@ -4025,7 +4162,8 @@ class Client
4025
4162
  #
4026
4163
  def _post_config(env, para)
4027
4164
  cfg = {
4028
- 'tz' => para['cfg-tz']
4165
+ 'tz' => para['cfg-tz'],
4166
+ 'rel_time' => (para['cfg-reltime'].downcase == 'true' ? true : false),
4029
4167
  }
4030
4168
  return cfg
4031
4169
  end # def _post_config()
@@ -4212,6 +4350,19 @@ class Client
4212
4350
  end
4213
4351
 
4214
4352
 
4353
+ ###############################################
4354
+ # Link to Action edit
4355
+ #
4356
+ def _a_action_edit(env, cid, anum, txt)
4357
+ '<a href="%s/action_edit/%s/%d">%s</a>' % [
4358
+ env['SCRIPT_NAME'],
4359
+ Rack::Utils.escape(cid),
4360
+ anum,
4361
+ Rack::Utils.escape_html(txt)
4362
+ ]
4363
+ end
4364
+
4365
+
4215
4366
  ###############################################
4216
4367
  # Link to Config edit
4217
4368
  #
@@ -4377,15 +4528,6 @@ class Client
4377
4528
  end # def _util_num()
4378
4529
 
4379
4530
 
4380
- ###############################################
4381
- # Epoch time as local
4382
- #
4383
- def _util_time(env, time)
4384
- tz = env['icfs'].config.get('tz')
4385
- Time.at(time).getlocal(tz).strftime('%F %T')
4386
- end
4387
-
4388
-
4389
4531
  ###############################################
4390
4532
  # Parse a provided time string
4391
4533
  #
@@ -4429,7 +4571,7 @@ class Client
4429
4571
  when :array
4430
4572
  query[sym] = val.split(',').map{|aa| aa.strip}
4431
4573
  when :boolean
4432
- if val == 'true'
4574
+ if val.downcase == 'true'
4433
4575
  query[sym] = true
4434
4576
  elsif val == 'false'
4435
4577
  query[sym] = false