voom-presenters 2.1.0 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,7 @@ import appConfig from '../config';
7
7
  export function initDateTime(e) {
8
8
  console.debug('\tDateTime');
9
9
  hookupComponents(e, '.v-datetime', VDateTime, MDCTextField);
10
+ hookupComponents(e, '.v-date-text', VDateText, MDCTextField);
10
11
  }
11
12
 
12
13
  export class VDateTime extends VTextField {
@@ -71,33 +72,115 @@ export class VDateTime extends VTextField {
71
72
  this.fp.toggle();
72
73
  }
73
74
 
74
- // checkDefaults() {
75
- // if(this.fp.config.mode = 'range'){
76
- // if(this.fp.selectedDates[1]){
77
- // // If we are in range mode and the endDate is defined as the beginning of the day, default it to be the
78
- // // end of the day.
79
- // let endDate = this.fp.selectedDates[1];
80
- // if(endDate.getHours() == 0 && endDate.getMinutes() == 0 && endDate.getSeconds() == 0 && endDate.getMilliseconds() == 0){
81
- // endDate.setHours(23);
82
- // endDate.setMinutes(59);
83
- // endDate.setSeconds(59);
84
- // endDate.getMilliseconds(9999);
85
- // this.fp.setDate(this.fp.selectedDates)
86
- // }
87
- // }
88
- // }
89
- // }
90
-
91
75
  isDirty() {
92
76
  if (!this.dirtyable) {
93
77
  return false;
94
78
  }
95
-
96
79
  const currVal = new Date(this.fp.input.value);
97
80
  const prevVal = new Date(this.originalValue);
81
+ return currVal.getTime() !== prevVal.getTime();
82
+ }
83
+ }
84
+
85
+ export class VDateText extends VTextField {
86
+ constructor(element, mdcComponent) {
87
+ super(element, mdcComponent);
88
+ element.addEventListener('input', this.createInputHandler(element.vComponent));
89
+ element.vComponent.input.addEventListener('blur', () => this.validate(null));
90
+ }
91
+
92
+ createInputHandler(component) {
93
+ return function(e) {
94
+ let input = component.value();
95
+
96
+ // Add a leading zero if input is like 1/ or 01 / 1/
97
+ if (/^\d\/$/.test(input)) input = '0' + input;
98
+ if (/^\d{2}\s\/\s\d\/$/.test(input)) input = input.slice(0,4) + '0' + input.slice(5,6);
99
+
100
+ // Parse and format input
101
+ if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
102
+ let values = input.split('/').map(function(v) {
103
+ return v.replace(/\D/g, '')
104
+ });
105
+ if (values[0]) values[0] = checkValue(values[0], 12);
106
+ if (values[1]) values[1] = checkValue(values[1], 31);
107
+ const output = values.map(function(v, i) {
108
+ return v.length === 2 && i < 2 ? v + ' / ' : v;
109
+ });
110
+ component.setValue(output.join('').substr(0, 14));
111
+ }
112
+ }
113
+
114
+ validate(formData) {
115
+ const input = this.element.vComponent.value();
116
+ if (this.isValidDate(input)) {
117
+ if (this.origHelperText !== '') {
118
+ this.helperDisplay.innerHTML = this.origHelperText;
119
+ this.helperDisplay.classList.remove('mdc-text-field-helper-text--validation-msg');
120
+ this.element.classList.remove('mdc-text-field--invalid');
121
+ }
122
+ else {
123
+ this.helperDisplay.classList.add('v-hidden');
124
+ }
125
+ return true;
126
+ }
127
+
128
+ const message = this.helperDisplay.dataset.validationError ?
129
+ this.helperDisplay.dataset.validationError :
130
+ this.input.validationMessage;
131
+
132
+ this.helperDisplay.innerHTML = message;
133
+ this.helperDisplay.classList.add('mdc-text-field-helper-text--validation-msg');
134
+ this.element.classList.add('mdc-text-field--invalid');
135
+
136
+ const errorMessage = {};
137
+ errorMessage[this.element.id] = [message];
138
+ return errorMessage;
139
+ }
140
+
141
+ isValidDate(dateString) {
142
+ dateString = dateString.replace(/\s+/g, '');
143
+ if (dateString === '' && !this.input.required) {
144
+ return true
145
+ }
146
+ if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString)) {
147
+ return false;
148
+ }
149
+
150
+ const parts = dateString.split("/");
151
+ const day = parseInt(parts[1], 10);
152
+ const month = parseInt(parts[0], 10);
153
+ const year = parseInt(parts[2], 10);
154
+
155
+ if (year < 1000 || year > 3000 || month === 0 || month > 12) {
156
+ return false;
157
+ }
158
+
159
+ const monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
160
+ if(year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0)) {
161
+ monthLength[1] = 29;
162
+ }
163
+
164
+ return day > 0 && day <= monthLength[month - 1];
165
+ };
98
166
 
167
+ isDirty() {
168
+ if (!this.dirtyable) {
169
+ return false;
170
+ }
171
+ const currVal = new Date(this.fp.input.value);
172
+ const prevVal = new Date(this.originalValue);
99
173
  return currVal.getTime() !== prevVal.getTime();
100
174
  }
101
175
  }
102
176
 
177
+ function checkValue(str, max) {
178
+ if (str.charAt(0) !== '0' || str === '00') {
179
+ let num = parseInt(str);
180
+ if (isNaN(num) || num <= 0 || num > max) num = 1;
181
+ str = num > parseInt(max.toString().charAt(0)) && num.toString().length === 1 ? '0' + num : num.toString();
182
+ }
183
+ return str;
184
+ }
185
+
103
186
 
@@ -3,6 +3,7 @@ import appConfig from '../../config';
3
3
  import {expandParams} from './action_parameter';
4
4
  import {encode} from './encode';
5
5
  import {getEventTarget} from '../get_event_target';
6
+ import {buildFormData} from '../../utils/form-data'
6
7
 
7
8
  // Replaces a given element with the contents of the call to the url.
8
9
  // parameters are appended.
@@ -41,9 +42,7 @@ export class VPosts extends VBase {
41
42
  }
42
43
 
43
44
  if (eventParams){
44
- for (const [name, value] of Object.entries(eventParams)) {
45
- formData.append(name, value);
46
- }
45
+ buildFormData(formData, eventParams);
47
46
  }
48
47
 
49
48
  // Add CSRF authenticity token if present
@@ -60,18 +59,13 @@ export class VPosts extends VBase {
60
59
  formData.append(name, encode(value));
61
60
  }
62
61
 
63
- const paramCount = Array.from(formData).length;
64
-
65
- if (paramCount < 1) {
62
+ if (this.paramCount(formData) < 1) {
66
63
  console.warn(
67
64
  'Creating request with no data!'
68
- + ' Are you sure you\'ve hooked everything up correctly?',
69
- );
65
+ + ' Are you sure you\'ve hooked everything up correctly?');
70
66
  }
71
67
 
72
68
  let errors = this.validate(formData);
73
- console.log('Validation errors');
74
- console.dir(errors);
75
69
  if (errors.length > 0) {
76
70
  return new Promise(function(_, reject) {
77
71
  results.push({
@@ -188,10 +182,17 @@ export class VPosts extends VBase {
188
182
  }
189
183
 
190
184
  // Send our FormData object; HTTP headers are set automatically
191
- httpRequest.send(formData);
185
+ // Rack 2.2 will throw an exception https://github.com/rack/rack/issues/1603
186
+ // if we set the header as multi-part form data with no data in the body
187
+ // So we set the body to null in this case.
188
+ httpRequest.send(this.paramCount(formData) < 1 ? null : formData);
192
189
  });
193
190
  }
194
191
 
192
+ paramCount(formData){
193
+ return Array.from(formData).length;
194
+ }
195
+
195
196
  isForm() {
196
197
  var parentElement = this.parentElement();
197
198
  return parentElement && parentElement.elements;
@@ -0,0 +1,12 @@
1
+ // Turns an Object into FormData. Note that a nested array will come out as a hash with numeric keys
2
+ // and will need to be handled accordingly server-side.
3
+ export function buildFormData(formData, data, parentKey) {
4
+ if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File) && !(data instanceof Blob)) {
5
+ Object.keys(data).forEach(key => {
6
+ buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key);
7
+ });
8
+ } else {
9
+ const value = data == null ? '' : data;
10
+ formData.append(parentKey, value);
11
+ }
12
+ }
@@ -1,10 +1,11 @@
1
1
  <%
2
2
  time_val = comp.value ? Array([comp.value]).join(', ') : nil
3
+ type_class = comp.picker ? 'v-datetime' : 'v-date-text'
3
4
  %>
4
5
  <div id="<%= comp.id %>"
5
6
  <% if comp.tag %>data-input-tag="<%= comp.tag %>"<% end %>
6
7
  <% if comp.dirtyable %>data-dirtyable<% end %>
7
- class="v-input v-datetime mdc-text-field mdc-text-field--outlined
8
+ class="v-input <%= type_class %> mdc-text-field mdc-text-field--outlined
8
9
  <%= 'mdc-text-field--with-trailing-icon' if comp.clear_icon %>
9
10
  <%= 'mdc-text-field--disabled' if comp.disabled %>"
10
11
  data-config='<%= snake_to_camel(to_hash(comp.config), except: %i(time_24hr)).to_json %>'
@@ -21,10 +22,12 @@
21
22
  <%= "pattern='#{comp.pattern}'" if comp.pattern %>
22
23
  list="<%= comp.id %>-list"
23
24
  <%= erb :"components/event", :locals => {comp: comp, events: comp.events, parent_id: "#{comp.id}-input"} %>>
24
- <%= erb :"components/icon", :locals => {comp: comp.clear_icon, class_name: 'mdc-text-field__icon', parent_id: "#{comp.id}-input"} %>
25
+ <%= erb :"components/icon", :locals => {comp: comp.clear_icon, class_name: 'mdc-text-field__icon', parent_id: "#{comp.id}-input"} if comp.picker %>
25
26
  <%= erb :"components/shared/input_label", :locals => {comp: comp} %>
26
- <datalist id="<%= comp.id %>-list">
27
- </datalist>
27
+ <% if comp.picker %>
28
+ <datalist id="<%= comp.id %>-list">
29
+ </datalist>
30
+ <% end %>
28
31
  </div>
29
32
  <%= erb :"components/shared/hint_error_display", :locals => {comp: comp} %>
30
33
  <%= erb :"components/tooltip", :locals => {comp: comp.tooltip, parent_id: comp.id} %>
@@ -3656,9 +3656,9 @@
3656
3656
  "dev": true
3657
3657
  },
3658
3658
  "dns-packet": {
3659
- "version": "1.3.1",
3660
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
3661
- "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
3659
+ "version": "1.3.4",
3660
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
3661
+ "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
3662
3662
  "dev": true,
3663
3663
  "requires": {
3664
3664
  "ip": "^1.1.0",
@@ -5524,9 +5524,9 @@
5524
5524
  "dev": true
5525
5525
  },
5526
5526
  "handlebars": {
5527
- "version": "4.7.6",
5528
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
5529
- "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
5527
+ "version": "4.7.7",
5528
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
5529
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
5530
5530
  "dev": true,
5531
5531
  "requires": {
5532
5532
  "minimist": "^1.2.5",
@@ -7969,9 +7969,9 @@
7969
7969
  }
7970
7970
  },
7971
7971
  "lodash": {
7972
- "version": "4.17.20",
7973
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
7974
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
7972
+ "version": "4.17.21",
7973
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
7974
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
7975
7975
  "dev": true
7976
7976
  },
7977
7977
  "lodash.camelcase": {
@@ -13066,9 +13066,9 @@
13066
13066
  "dev": true
13067
13067
  },
13068
13068
  "querystringify": {
13069
- "version": "2.1.0",
13070
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz",
13071
- "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg=="
13069
+ "version": "2.2.0",
13070
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
13071
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
13072
13072
  },
13073
13073
  "quill": {
13074
13074
  "version": "1.3.7",
@@ -14206,7 +14206,7 @@
14206
14206
  },
14207
14207
  "os-locale": {
14208
14208
  "version": "1.4.0",
14209
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
14209
+ "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
14210
14210
  "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
14211
14211
  "dev": true,
14212
14212
  "requires": {
@@ -14235,7 +14235,7 @@
14235
14235
  },
14236
14236
  "pify": {
14237
14237
  "version": "2.3.0",
14238
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
14238
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
14239
14239
  "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
14240
14240
  "dev": true
14241
14241
  },
@@ -15687,11 +15687,11 @@
15687
15687
  }
15688
15688
  },
15689
15689
  "url-parse": {
15690
- "version": "1.4.4",
15691
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz",
15692
- "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==",
15690
+ "version": "1.5.0",
15691
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.0.tgz",
15692
+ "integrity": "sha512-9iT6N4s93SMfzunOyDPe4vo4nLcSu1yq0IQK1gURmjm8tQNlM6loiuCRrKG1hHGXfB2EWd6H4cGi7tGdaygMFw==",
15693
15693
  "requires": {
15694
- "querystringify": "^2.0.0",
15694
+ "querystringify": "^2.1.1",
15695
15695
  "requires-port": "^1.0.0"
15696
15696
  }
15697
15697
  },
@@ -68,7 +68,7 @@
68
68
  "mdl-stepper": "^1.1.6",
69
69
  "npm": "^6.14.6",
70
70
  "quill": "^1.3.7",
71
- "url-parse": "^1.4.4"
71
+ "url-parse": "^1.5.0"
72
72
  },
73
73
  "bundleDependencies": [
74
74
  "@material/image-list"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voom-presenters
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Russell Edens
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-17 00:00:00.000000000 Z
11
+ date: 2021-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ice_nine
@@ -391,6 +391,7 @@ files:
391
391
  - app/demo/events/content_as_form.pom
392
392
  - app/demo/events/field_level.pom
393
393
  - app/demo/events/form_level.pom
394
+ - app/demo/events/halted.pom
394
395
  - app/demo/events/nav/drawer.pom
395
396
  - app/demo/events/parallel.pom
396
397
  - app/demo/events/tagged_input.pom
@@ -712,6 +713,7 @@ files:
712
713
  - views/mdc/assets/js/utils/compatibility.js
713
714
  - views/mdc/assets/js/utils/config.js
714
715
  - views/mdc/assets/js/utils/config.test.js
716
+ - views/mdc/assets/js/utils/form-data.js
715
717
  - views/mdc/assets/js/utils/urls.js
716
718
  - views/mdc/assets/js/wc.js
717
719
  - views/mdc/assets/scss/app.scss