@nyaruka/temba-components 0.129.11 → 0.130.1

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +13 -4
  2. package/demo/components/flow/example.html +5 -1
  3. package/demo/data/flows/sample-flow.json +144 -80
  4. package/dist/temba-components.js +290 -346
  5. package/dist/temba-components.js.map +1 -1
  6. package/out-tsc/src/flow/CanvasNode.js +3 -35
  7. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  8. package/out-tsc/src/flow/NodeEditor.js +44 -11
  9. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  10. package/out-tsc/src/flow/actions/add_contact_groups.js +14 -2
  11. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  12. package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
  13. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  14. package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
  15. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  16. package/out-tsc/src/flow/actions/remove_contact_groups.js +1 -1
  17. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  18. package/out-tsc/src/flow/actions/send_email.js +9 -0
  19. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  20. package/out-tsc/src/flow/actions/send_msg.js +7 -8
  21. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  22. package/out-tsc/src/flow/actions/set_contact_channel.js +25 -4
  23. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  24. package/out-tsc/src/flow/actions/set_contact_field.js +51 -1
  25. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  26. package/out-tsc/src/flow/actions/set_contact_language.js +70 -2
  27. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  28. package/out-tsc/src/flow/actions/set_contact_name.js +27 -2
  29. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  30. package/out-tsc/src/flow/actions/set_contact_status.js +32 -2
  31. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  32. package/out-tsc/src/flow/actions/set_run_result.js +13 -11
  33. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  34. package/out-tsc/src/flow/actions/split_by_expression_example.js +4 -4
  35. package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -1
  36. package/out-tsc/src/flow/forms/index.js +2 -0
  37. package/out-tsc/src/flow/forms/index.js.map +1 -0
  38. package/out-tsc/src/flow/nodes/split_by_random.js +117 -0
  39. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  40. package/out-tsc/src/flow/nodes/split_by_ticket.js +0 -1
  41. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  42. package/out-tsc/src/flow/nodes/split_by_webhook.js +1 -3
  43. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  44. package/out-tsc/src/flow/types.js.map +1 -1
  45. package/out-tsc/src/form/ArrayEditor.js +9 -25
  46. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  47. package/out-tsc/src/form/FieldRenderer.js +6 -64
  48. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  49. package/out-tsc/src/form/select/Select.js +35 -58
  50. package/out-tsc/src/form/select/Select.js.map +1 -1
  51. package/out-tsc/src/utils.js +3 -0
  52. package/out-tsc/src/utils.js.map +1 -1
  53. package/out-tsc/test/nodes/split_by_random.test.js +0 -6
  54. package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
  55. package/out-tsc/test/temba-field-renderer.test.js +6 -3
  56. package/out-tsc/test/temba-field-renderer.test.js.map +1 -1
  57. package/out-tsc/test/utils.test.js +18 -0
  58. package/out-tsc/test/utils.test.js.map +1 -1
  59. package/package.json +1 -1
  60. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  61. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  62. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  63. package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
  64. package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
  65. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  66. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  67. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  68. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  69. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  70. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  71. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  72. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  73. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  74. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  75. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  76. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  77. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  78. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  79. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  80. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  81. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  82. package/screenshots/truth/editor/set_contact_language.png +0 -0
  83. package/screenshots/truth/editor/set_contact_name.png +0 -0
  84. package/screenshots/truth/editor/set_run_result.png +0 -0
  85. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  86. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  87. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  88. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  89. package/src/flow/CanvasNode.ts +2 -39
  90. package/src/flow/NodeEditor.ts +54 -13
  91. package/src/flow/actions/add_contact_groups.ts +17 -2
  92. package/src/flow/actions/add_contact_urn.ts +1 -1
  93. package/src/flow/actions/add_input_labels.ts +2 -1
  94. package/src/flow/actions/remove_contact_groups.ts +1 -1
  95. package/src/flow/actions/send_email.ts +11 -1
  96. package/src/flow/actions/send_msg.ts +20 -11
  97. package/src/flow/actions/set_contact_channel.ts +28 -5
  98. package/src/flow/actions/set_contact_field.ts +56 -2
  99. package/src/flow/actions/set_contact_language.ts +74 -3
  100. package/src/flow/actions/set_contact_name.ts +31 -3
  101. package/src/flow/actions/set_contact_status.ts +36 -3
  102. package/src/flow/actions/set_run_result.ts +13 -15
  103. package/src/flow/actions/split_by_expression_example.ts +4 -4
  104. package/src/flow/forms/index.ts +1 -0
  105. package/src/flow/nodes/split_by_random.ts +148 -0
  106. package/src/flow/nodes/split_by_ticket.ts +0 -1
  107. package/src/flow/nodes/split_by_webhook.ts +1 -3
  108. package/src/flow/types.ts +2 -1
  109. package/src/form/ArrayEditor.ts +6 -20
  110. package/src/form/FieldRenderer.ts +6 -65
  111. package/src/form/select/Select.ts +38 -66
  112. package/src/store/flow-definition.d.ts +6 -1
  113. package/src/utils.ts +4 -0
  114. package/static/api/fields.json +93 -1208
  115. package/static/api/workspace.json +23 -0
  116. package/test/nodes/split_by_random.test.ts +0 -7
  117. package/test/temba-field-renderer.test.ts +26 -13
  118. package/test/utils.test.ts +20 -0
  119. package/web-dev-server.config.mjs +2 -0
  120. package/web-test-runner.config.mjs +37 -0
@@ -592,6 +592,7 @@ export class Select<T extends SelectOption> extends FieldElement {
592
592
  this.prepareOptionsDefault = this.prepareOptionsDefault.bind(this);
593
593
  this.isMatchDefault = this.isMatchDefault.bind(this);
594
594
  this.handleOrderChanged = this.handleOrderChanged.bind(this);
595
+ this.createArbitraryOption = this.createArbitraryOptionDefault.bind(this);
595
596
  }
596
597
 
597
598
  public prepareOptionsDefault(options: T[]): T[] {
@@ -701,20 +702,16 @@ export class Select<T extends SelectOption> extends FieldElement {
701
702
  );
702
703
  }
703
704
 
704
- public async createOptionPost(payload: any) {
705
- return postJSON(this.endpoint, payload).then((response) => {
706
- if (response.status >= 200 && response.status < 300) {
707
- return {
708
- json: response.json,
709
- payload
710
- };
711
- }
712
- });
713
- }
714
-
715
705
  public updated(changes: Map<string, any>) {
716
706
  super.updated(changes);
717
707
 
708
+ if (changes.has('createArbitraryOption')) {
709
+ if (!this.createArbitraryOption) {
710
+ this.createArbitraryOption =
711
+ this.createArbitraryOptionDefault.bind(this);
712
+ }
713
+ }
714
+
718
715
  if (changes.has('sorted')) {
719
716
  this.sortFunction = this.sorted ? this.alphaSort : null;
720
717
  }
@@ -727,60 +724,8 @@ export class Select<T extends SelectOption> extends FieldElement {
727
724
 
728
725
  if (changes.has('values')) {
729
726
  this.updateInputs();
730
-
731
727
  if (this.hasChanges(changes.get('values'))) {
732
- const materialized = [];
733
-
734
- // see if we need to materialize anything
735
- if (this.allowCreate) {
736
- // arbitrary values need to be posted
737
- const arbitraryValues = this.values.filter((value) => {
738
- return (value as any).arbitrary;
739
- });
740
-
741
- for (const value of arbitraryValues) {
742
- if ((value as any).arbitrary) {
743
- materialized.push(this.createOptionPost(value));
744
- }
745
- }
746
-
747
- // update our created values
748
- Promise.all(materialized).then((responses) => {
749
- for (const response of responses) {
750
- if (response) {
751
- // find the value that matches our payload
752
- const original = arbitraryValues.find((value) => {
753
- return value === response.payload;
754
- }) as any;
755
-
756
- if (original) {
757
- // remove our arbitrary flag
758
- delete original.arbitrary;
759
-
760
- // add in the new values from our respones.json
761
- if (response.json) {
762
- for (const key in response.json) {
763
- original[key] = response.json[key];
764
- }
765
- }
766
- }
767
- }
768
- }
769
-
770
- // remove any arbitrary values
771
- for (let i = this.values.length - 1; i >= 0; i--) {
772
- if ((this.values[i] as any).arbitrary) {
773
- this.values.splice(i, 1);
774
- }
775
- }
776
-
777
- // reset our cache
778
- this.cacheKey = new Date().getTime().toString();
779
- this.fireEvent('change');
780
- });
781
- } else {
782
- this.fireEvent('change');
783
- }
728
+ this.fireEvent('change');
784
729
  }
785
730
  }
786
731
 
@@ -955,19 +900,31 @@ export class Select<T extends SelectOption> extends FieldElement {
955
900
  }
956
901
 
957
902
  const selected = event.detail.selected;
903
+
958
904
  // check if we should post it
959
- if (selected.post && this.endpoint) {
905
+ if (selected.arbitrary && this.allowCreate && this.endpoint) {
906
+ this.resolving = true;
960
907
  postJSON(this.endpoint, selected).then((response) => {
961
908
  if (response.status >= 200 && response.status < 300) {
962
909
  this.setSelectedOption(response.json);
963
910
  this.lruCache = lru(20, 60000);
911
+ this.errors = [];
964
912
  } else {
965
- // TODO: find a way to share inline errors
913
+ this.setSelectedOption(selected);
914
+ setTimeout(() => {
915
+ this.errors = [
916
+ 'There was an error creating "' +
917
+ this.getNameInternal(selected) +
918
+ '"'
919
+ ];
920
+ }, 0);
966
921
  this.blur();
967
922
  }
923
+ this.resolving = false;
968
924
  });
969
925
  } else {
970
926
  this.setSelectedOption(selected);
927
+ this.errors = [];
971
928
  }
972
929
  }
973
930
 
@@ -1009,6 +966,21 @@ export class Select<T extends SelectOption> extends FieldElement {
1009
966
  public handleRemoveSelection(selectionToRemove: any): void {
1010
967
  this.removeValue(selectionToRemove);
1011
968
  this.visibleOptions = [];
969
+ this.errors = [];
970
+
971
+ // if we allow create, double check our values
972
+ if (this.allowCreate) {
973
+ const arbitrary = this.values.find((v) => v.arbitrary);
974
+ if (arbitrary) {
975
+ setTimeout(() => {
976
+ this.errors = [
977
+ 'There was an error creating "' +
978
+ this.getNameInternal(arbitrary) +
979
+ '"'
980
+ ];
981
+ }, 0);
982
+ }
983
+ }
1012
984
  }
1013
985
 
1014
986
  private createArbitraryOptionDefault(input: string, _options: any[]): any {
@@ -68,6 +68,11 @@ export interface NamedObject {
68
68
  name: string;
69
69
  }
70
70
 
71
+ export interface FieldReference {
72
+ key: string;
73
+ name: string;
74
+ }
75
+
71
76
  export interface Group extends NamedObject {
72
77
  status?: string;
73
78
  system?: boolean;
@@ -111,7 +116,7 @@ export interface RemoveFromGroup extends Action {
111
116
  }
112
117
 
113
118
  export interface SetContactField extends Action {
114
- field: NamedObject;
119
+ field: FieldReference;
115
120
  value: string;
116
121
  }
117
122
 
package/src/utils.ts CHANGED
@@ -1124,3 +1124,7 @@ export const createMultiCategoryRouter = (
1124
1124
  exits: exits
1125
1125
  };
1126
1126
  };
1127
+
1128
+ export const titleCase = (str: string) => {
1129
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
1130
+ };