alchemy-form 0.1.7 → 0.1.8

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 0.1.8 (2022-06-29)
2
+
3
+ * Move the `alchemy-select` pagination checker initializer to a static function
4
+ * Prevent `alchemy-select` from keeping on loading remote data when last few results were empty
5
+ * Fix pagination breaking re-opening of `alchemy-select` dropdown
6
+ * Fix initial value of a `BelongsTo` `alchemy-select` element not loading
7
+ * Fix `alchemy-select` downward-arrow-icon being rendered over value content
8
+ * Use `alchemy-code-input` for HTML fields
9
+ * Allow manually setting a value on `alchemy-field` elements
10
+ * Try to let `Field` instances decide the representation of values in `alchemy-table` elements
11
+ * Don't open the `alchemy-table` contextmenu when clicking on anchors
12
+
1
13
  ## 0.1.7 (2022-06-12)
2
14
 
3
15
  * Fix `<alchemy-table>` code typo
@@ -102,7 +102,6 @@ alchemy-select {
102
102
  font-family: inherit;
103
103
  font-size: 13px;
104
104
  line-height: 18px;
105
- -webkit-font-smoothing: inherit;
106
105
  display: inline-block !important;
107
106
  padding: 0 !important;
108
107
  min-height: 0 !important;
@@ -113,11 +112,10 @@ alchemy-select {
113
112
  border: 0 none !important;
114
113
  background: none !important;
115
114
  line-height: inherit !important;
116
- -webkit-user-select: auto !important;
117
- -webkit-box-shadow: none !important;
118
115
  box-shadow: none !important;
119
116
  outline: none !important;
120
117
  flex: 0 1 auto;
118
+ margin-right: 20px !important;
121
119
  }
122
120
 
123
121
  .dropdown {
@@ -17,20 +17,23 @@ const FormApi = Function.inherits('Alchemy.Controller', 'FormApi');
17
17
  *
18
18
  * @author Jelle De Loecker <jelle@elevenways.be>
19
19
  * @since 0.1.0
20
- * @version 0.1.6
20
+ * @version 0.1.8
21
21
  *
22
22
  * @param {Conduit} conduit
23
23
  */
24
24
  FormApi.setAction(async function related(conduit) {
25
25
 
26
- const body = conduit.body;
26
+ const body = conduit.body || {},
27
+ config = body.config || {};
27
28
 
28
29
  const model = this.getModel(body.assoc_model);
29
30
  let crit = model.find();
30
31
  crit.limit(50);
31
32
  crit.setOption('scenario', 'related_data');
32
33
 
33
- if (body.config && body.config.search) {
34
+ if (config.value) {
35
+ crit.where(model.primary_key).equals(config.value);
36
+ } else if (config.search) {
34
37
  let display_fields = Array.cast(model.displayField);
35
38
 
36
39
  let or = crit.or();
@@ -45,6 +48,10 @@ FormApi.setAction(async function related(conduit) {
45
48
  }
46
49
  }
47
50
 
51
+ if (config.page) {
52
+ crit.page(config.page);
53
+ }
54
+
48
55
  let records = await model.find('all', crit);
49
56
 
50
57
  let result = {
@@ -133,7 +133,7 @@ Field.enforceProperty(function alchemy_field_schema(new_value, old_value) {
133
133
  *
134
134
  * @author Jelle De Loecker <jelle@elevenways.be>
135
135
  * @since 0.1.0
136
- * @version 0.1.4
136
+ * @version 0.1.8
137
137
  */
138
138
  Field.enforceProperty(function config(new_value, old_value) {
139
139
 
@@ -148,7 +148,7 @@ Field.enforceProperty(function config(new_value, old_value) {
148
148
 
149
149
  if (new_value && new_value.constructor && new_value.constructor.type_name) {
150
150
  this.field_type = new_value.constructor.type_name;
151
- } else {
151
+ } else if (new_value) {
152
152
  this.field_type = null;
153
153
  }
154
154
 
@@ -493,10 +493,14 @@ Field.setProperty(function wrapper_files() {
493
493
  *
494
494
  * @author Jelle De Loecker <jelle@elevenways.be>
495
495
  * @since 0.1.0
496
- * @version 0.1.4
496
+ * @version 0.1.8
497
497
  */
498
498
  Field.setProperty(function original_value() {
499
499
 
500
+ if (this.assigned_data.original_value != null) {
501
+ return this.assigned_data.original_value;
502
+ }
503
+
500
504
  let alchemy_field_schema = this.alchemy_field_schema,
501
505
  path = this.field_path_in_current_schema;
502
506
 
@@ -517,6 +521,8 @@ Field.setProperty(function original_value() {
517
521
  if (form && form.document) {
518
522
  return Object.path(form.document, path);
519
523
  }
524
+ }, function setOriginalValue(value) {
525
+ return this.assigned_data.original_value = value;
520
526
  });
521
527
 
522
528
  /**
@@ -551,7 +557,7 @@ Field.setProperty(function value_element() {
551
557
  *
552
558
  * @author Jelle De Loecker <jelle@elevenways.be>
553
559
  * @since 0.1.0
554
- * @version 0.1.3
560
+ * @version 0.1.8
555
561
  */
556
562
  Field.setProperty(function value() {
557
563
 
@@ -569,8 +575,9 @@ Field.setProperty(function value() {
569
575
 
570
576
  if (element) {
571
577
  element.value = value;
578
+ } else if (this.original_value == null) {
579
+ this.original_value = value;
572
580
  }
573
-
574
581
  });
575
582
 
576
583
  /**
@@ -5,9 +5,7 @@
5
5
  * @since 0.1.0
6
6
  * @version 0.1.0
7
7
  */
8
- var AlchemySelect = Function.inherits('Alchemy.Element.Form.Base', function Select() {
9
- Select.super.call(this);
10
- });
8
+ const AlchemySelect = Function.inherits('Alchemy.Element.Form.Base', 'Select');
11
9
 
12
10
  /**
13
11
  * The remote url attribute
@@ -389,14 +387,56 @@ AlchemySelect.setProperty(function loading_dropdown() {
389
387
  *
390
388
  * @author Jelle De Loecker <jelle@develry.be>
391
389
  * @since 0.1.0
392
- * @version 0.1.0
390
+ * @version 0.1.8
393
391
  */
394
392
  AlchemySelect.setProperty(function search_value() {
395
- var type_area = this.type_area;
393
+
394
+ let type_area = this.type_area,
395
+ result = '';
396
396
 
397
397
  if (type_area) {
398
- return type_area.value;
398
+ result = type_area.value;
399
399
  }
400
+
401
+ if (this.previous_search_value == null) {
402
+ this.previous_search_value = '';
403
+ }
404
+
405
+ // If the search value changed, nullify the last page result
406
+ if (this.previous_search_value != result) {
407
+ this.setLastSuccessfulLoadedPage(null);
408
+ }
409
+
410
+ this.previous_search_value = result;
411
+
412
+ return result;
413
+ });
414
+
415
+ /**
416
+ * Make sure the pagination watcher exists
417
+ *
418
+ * @author Jelle De Loecker <jelle@elevenways.be>
419
+ * @since 0.1.0
420
+ * @version 0.1.8
421
+ */
422
+ AlchemySelect.setStatic(function ensurePaginationChecker() {
423
+
424
+ if (AlchemySelect.has_paginator_viewer) {
425
+ return;
426
+ }
427
+
428
+ // Only ever add 1 viewer per page
429
+ AlchemySelect.has_paginator_viewer = true;
430
+
431
+ hawkejs.scene.appears('js-he-ais-pager', {live: true, padding: 10, throttle: 200}, function onInfinity(el) {
432
+
433
+ if (!el.parentElement || !el.parentElement.parentElement) {
434
+ return;
435
+ }
436
+
437
+ const alchemy_select_instance = el.parentElement.parentElement;
438
+ alchemy_select_instance.loadOptions(++alchemy_select_instance.loaded_page);
439
+ });
400
440
  });
401
441
 
402
442
  /**
@@ -420,7 +460,7 @@ AlchemySelect.setMethod(function rendered() {
420
460
  *
421
461
  * @author Jelle De Loecker <jelle@develry.be>
422
462
  * @since 0.1.0
423
- * @version 0.1.0
463
+ * @version 0.1.8
424
464
  */
425
465
  AlchemySelect.setMethod(function introduced() {
426
466
 
@@ -433,14 +473,7 @@ AlchemySelect.setMethod(function introduced() {
433
473
  this.makeSortable();
434
474
  }
435
475
 
436
- if (!AlchemySelect.has_paginator_viewer) {
437
- AlchemySelect.has_paginator_viewer = true;
438
-
439
- hawkejs.scene.appears('js-he-ais-pager', {live: true, padding: 10, throttle: 200}, function onInfinity(el) {
440
- var ais = el.parentElement.parentElement;
441
- ais.loadOptions(++ais.loaded_page);
442
- });
443
- }
476
+ AlchemySelect.ensurePaginationChecker();
444
477
 
445
478
  this.addEventListener('focus-without', function onFocusOut(e) {
446
479
  that.type_area.value = '';
@@ -462,8 +495,6 @@ AlchemySelect.setMethod(function introduced() {
462
495
 
463
496
  this.addEventListener('keydown', function onKeydown(e) {
464
497
 
465
- console.log('keydown:', e);
466
-
467
498
  // Only listen for keydowns on the alchemy-select itself
468
499
  if (e.target != that) {
469
500
  return;
@@ -829,11 +860,12 @@ AlchemySelect.setMethod(function _processPreloadedValues() {
829
860
  *
830
861
  * @author Jelle De Loecker <jelle@develry.be>
831
862
  * @since 0.1.0
832
- * @version 0.1.6
863
+ * @version 0.1.8
833
864
  *
834
865
  * @param {Object} response
866
+ * @param {Number} page The page, if it's via pagination
835
867
  */
836
- AlchemySelect.setMethod(function _processResponseData(response) {
868
+ AlchemySelect.setMethod(function _processResponseData(response, page) {
837
869
 
838
870
  if (!response) {
839
871
  response = {};
@@ -851,14 +883,48 @@ AlchemySelect.setMethod(function _processResponseData(response) {
851
883
  records = [];
852
884
  }
853
885
 
854
- for (record of records) {
886
+ this._processResponseList(records, page);
887
+
888
+ this.refreshResultAmount();
889
+ this._markSelectedItems();
890
+ });
891
+
892
+ /**
893
+ * Process the response list of a certain paige
894
+ *
895
+ * @author Jelle De Loecker <jelle@elevenways.be>
896
+ * @since 0.1.8
897
+ * @version 0.1.8
898
+ *
899
+ * @param {Array} list
900
+ * @param {Number} page
901
+ */
902
+ AlchemySelect.setMethod(function _processResponseList(list, page) {
903
+
904
+ let record,
905
+ item;
906
+
907
+ if (page == 1 && this.current_option && this.current_option.data) {
908
+ record = this.current_option.data;
909
+ item = this._makeOption(record._id || record.id, record);
910
+ this.addToDropdown(item);
911
+ }
912
+
913
+ for (record of list) {
855
914
  item = this._makeOption(record._id || record.id, record);
856
915
  this.addToDropdown(item);
857
916
  }
858
917
 
859
918
  this.loading_dropdown = false;
860
- this.refreshResultAmount();
861
- this._markSelectedItems();
919
+
920
+ // If there were values & they come from a page, record this as a succesful page
921
+ if (page != null && list.length) {
922
+ if (!this.last_page_result) {
923
+ this.setLastSuccessfulLoadedPage(page);
924
+ } else if (page > this.last_page_result) {
925
+ this.setLastSuccessfulLoadedPage(page);
926
+ }
927
+ }
862
928
  });
863
929
 
864
930
  /**
@@ -866,7 +932,7 @@ AlchemySelect.setMethod(function _processResponseData(response) {
866
932
  *
867
933
  * @author Jelle De Loecker <jelle@develry.be>
868
934
  * @since 0.1.0
869
- * @version 0.1.0
935
+ * @version 0.1.8
870
936
  *
871
937
  * @param {Number} page
872
938
  *
@@ -887,6 +953,10 @@ AlchemySelect.setMethod(function loadRemote(page) {
887
953
  return pledge;
888
954
  }
889
955
 
956
+ if (page == null) {
957
+ page = 1;
958
+ }
959
+
890
960
  const that = this;
891
961
 
892
962
  this.loading_dropdown = true;
@@ -906,11 +976,11 @@ AlchemySelect.setMethod(function loadRemote(page) {
906
976
  throw err;
907
977
  }
908
978
 
909
- if (page == null) {
979
+ if (page == null || page == 1) {
910
980
  Hawkejs.removeChildren(that.dropdown_content);
911
981
  }
912
982
 
913
- that._processResponseData(data);
983
+ that._processResponseData(data, page);
914
984
 
915
985
  pledge.resolve(true);
916
986
  };
@@ -1001,7 +1071,19 @@ AlchemySelect.setMethod(function _markSelectedItems() {
1001
1071
  }
1002
1072
  }
1003
1073
  }
1074
+ });
1004
1075
 
1076
+ /**
1077
+ * Set the last successful loaded page
1078
+ *
1079
+ * @author Jelle De Loecker <jelle@develry.be>
1080
+ * @since 0.1.8
1081
+ * @version 0.1.8
1082
+ *
1083
+ * @param {Number} page
1084
+ */
1085
+ AlchemySelect.setMethod(function setLastSuccessfulLoadedPage(page) {
1086
+ this.last_page_result = page;
1005
1087
  });
1006
1088
 
1007
1089
  /**
@@ -1009,15 +1091,13 @@ AlchemySelect.setMethod(function _markSelectedItems() {
1009
1091
  *
1010
1092
  * @author Jelle De Loecker <jelle@develry.be>
1011
1093
  * @since 0.1.0
1012
- * @version 0.1.0
1094
+ * @version 0.1.8
1013
1095
  *
1014
1096
  * @param {Number} page
1015
1097
  */
1016
1098
  AlchemySelect.setMethod(function loadOptions(page) {
1017
1099
 
1018
- var that = this,
1019
- model,
1020
- field;
1100
+ const that = this;
1021
1101
 
1022
1102
  if (this.total_item_count >= this.loaded_item_count) {
1023
1103
  if (this.dropdown_content.children.length == 0) {
@@ -1029,12 +1109,34 @@ AlchemySelect.setMethod(function loadOptions(page) {
1029
1109
  return;
1030
1110
  }
1031
1111
 
1112
+ // Prevent it from keeping on loading empty pages if the previous page was empty
1113
+ if (page && this.last_page_result) {
1114
+ let next_allowed_page = this.last_page_result + 1;
1115
+
1116
+ if (page > next_allowed_page) {
1117
+ return;
1118
+ }
1119
+ }
1120
+
1121
+ // Previous page will only be set to the last page that had items.
1122
+ // So if there are 0 results overall, it won't ever be set.
1123
+ // In that case: ignore any page load over 1.
1124
+ if (page > 1 && !this.last_page_result) {
1125
+ return;
1126
+ }
1127
+
1128
+ // If stuff has already been loaded and this is just re-opening the dropdown,
1129
+ // don't do anything yet
1130
+ if (page == null && this.last_page_result > 0) {
1131
+ return;
1132
+ }
1133
+
1032
1134
  // If an URL is provided, use that
1033
1135
  if (this.src || this.dataprovider) {
1034
1136
  return this.loadRemote(page);
1035
1137
  }
1036
1138
 
1037
- field = this.model_field;
1139
+ let field = this.model_field;
1038
1140
 
1039
1141
  if (!field) {
1040
1142
  return;
@@ -1042,7 +1144,7 @@ AlchemySelect.setMethod(function loadOptions(page) {
1042
1144
 
1043
1145
  this.loading_dropdown = true;
1044
1146
 
1045
- model = this.form.getModel(field.modelName);
1147
+ let model = this.form.getModel(field.modelName);
1046
1148
 
1047
1149
  model.find('all', {
1048
1150
  limit : 20,
@@ -1053,12 +1155,7 @@ AlchemySelect.setMethod(function loadOptions(page) {
1053
1155
  throw err;
1054
1156
  }
1055
1157
 
1056
- records.forEach(function eachRecord(record) {
1057
- var item = that._makeOption(record._id || record.id, record);
1058
- that.addToDropdown(item);
1059
- });
1060
-
1061
- that.loading_dropdown = false;
1158
+ that._processResponseList(records, page);
1062
1159
  });
1063
1160
  });
1064
1161
 
@@ -1699,9 +1796,10 @@ AlchemySelect.setMethod(function applyLocalFilter(query) {
1699
1796
  *
1700
1797
  * @author Jelle De Loecker <jelle@develry.be>
1701
1798
  * @since 0.1.0
1702
- * @version 0.1.0
1799
+ * @version 0.1.8
1703
1800
  */
1704
1801
  AlchemySelect.setMethod('refreshRemote', Fn.throttle(function refreshRemote() {
1802
+ this.loaded_page = 0;
1705
1803
  this.loadRemote();
1706
1804
  }, {
1707
1805
  minimum_wait : 350,
@@ -589,12 +589,49 @@ Table.setMethod(function showPagination() {
589
589
  pager.showPage(records.page, Math.ceil(records.available / records.page_size));
590
590
  });
591
591
 
592
+ /**
593
+ * Get a fieldset's preferred content view
594
+ *
595
+ * @author Jelle De Loecker <jelle@elevenways.be>
596
+ * @since 0.1.8
597
+ * @version 0.1.8
598
+ *
599
+ * @param {FieldConfig} field_config The config on how to display the field
600
+ * @param {Object} container The container where the field should be in
601
+ *
602
+ * @return
603
+ */
604
+ Table.setMethod(function getFieldConfigView(field_config, container) {
605
+
606
+ let value = field_config.getValueIn(container),
607
+ field = field_config.getFieldDefinition();
608
+
609
+ if (value == null && !field) {
610
+ return null;
611
+ }
612
+
613
+ // Fallback to simple text view
614
+ if (!field) {
615
+ let text = field_config.getDisplayValueIn(container);
616
+
617
+ return Hawkejs.createText(text);
618
+ }
619
+
620
+ let alchemy_field = this.createElement('alchemy-field');
621
+ alchemy_field.view_type = 'view_inline';
622
+ alchemy_field.field_name = field.name;
623
+ alchemy_field.config = field;
624
+ alchemy_field.original_value = value;
625
+
626
+ return alchemy_field;
627
+ });
628
+
592
629
  /**
593
630
  * Create a datarow
594
631
  *
595
632
  * @author Jelle De Loecker <jelle@elevenways.be>
596
633
  * @since 0.1.0
597
- * @version 0.1.6
634
+ * @version 0.1.8
598
635
  *
599
636
  * @param {Object} entry
600
637
  *
@@ -602,7 +639,7 @@ Table.setMethod(function showPagination() {
602
639
  */
603
640
  Table.setMethod(function createDataRow(entry) {
604
641
 
605
- let field,
642
+ let field_set_config,
606
643
  value,
607
644
  tr = this.createElement('tr'),
608
645
  td,
@@ -610,13 +647,13 @@ Table.setMethod(function createDataRow(entry) {
610
647
 
611
648
  tr.dataset.pk = id;
612
649
 
613
- for (field of this.fieldset) {
650
+ for (field_set_config of this.fieldset) {
614
651
  td = this.createElement('td');
615
652
 
616
- value = field.getDisplayValueIn(entry);
653
+ let element = this.getFieldConfigView(field_set_config, entry);
617
654
 
618
- if (value != null) {
619
- td.textContent = value;
655
+ if (element) {
656
+ td.append(element);
620
657
  }
621
658
 
622
659
  tr.append(td);
@@ -709,7 +746,7 @@ Table.setMethod(function getEntryActions(record, filter) {
709
746
  *
710
747
  * @author Jelle De Loecker <jelle@elevenways.be>
711
748
  * @since 0.1.6
712
- * @version 0.1.7
749
+ * @version 0.1.8
713
750
  *
714
751
  * @param {Object} entry
715
752
  */
@@ -745,6 +782,13 @@ Table.setMethod(function attachContextMenus() {
745
782
 
746
783
  tr.addEventListener('contextmenu', e => {
747
784
 
785
+ // Ignore right clicks on certain elements
786
+ if (e && e.target) {
787
+ if (e.target.closest('a')) {
788
+ return;
789
+ }
790
+ }
791
+
748
792
  this.selectRow(tr);
749
793
 
750
794
  let menu = this.createElement('he-context-menu');
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "alchemy-form",
3
3
  "description": "Form plugin for Alchemy",
4
- "version": "0.1.7",
4
+ "version": "0.1.8",
5
5
  "repository": {
6
6
  "type" : "git",
7
7
  "url" : "https://github.com/11ways/alchemy-form.git"
8
8
  },
9
9
  "peerDependencies": {
10
- "alchemymvc" : "~1.2.0"
10
+ "alchemymvc" : ">=1.2.0"
11
11
  },
12
12
  "license": "MIT",
13
13
  "engines": {
@@ -2,6 +2,6 @@
2
2
  class="alchemy-field-value"
3
3
  ><%
4
4
  $0.dataprovider = alchemy_field;
5
- $0.value = value;
6
5
  $0.name = path;
6
+ $0.value = value;
7
7
  %></alchemy-select>
@@ -0,0 +1,5 @@
1
+ <alchemy-code-input
2
+ class="alchemy-field-value"
3
+ form=<% form_id %>
4
+ name=<% path %>
5
+ >{{ value }}</alchemy-code-input>
@@ -0,0 +1 @@
1
+ <span class="alchemy-field-value">{{ value }}</span>
@@ -0,0 +1 @@
1
+ <span class="alchemy-field-value">{{ value }}</span>
@@ -0,0 +1 @@
1
+ <div data-he-name="field"></div>