Commit | Line | Data |
---|---|---|
b396fc59 | 1 | (function(angular, $, _) { |
7947eac5 SL |
2 | // "YYYY-MM-DD hh:mm:ss" => Date() |
3 | function parseYmdHms(d) { | |
4 | var parts = d.split(/[\-: ]/); | |
5 | return new Date(parts[0], parts[1]-1, parts[2], parts[3], parts[4], parts[5]); | |
6 | } | |
7 | ||
8 | function isDateBefore(tgt, cutoff, tolerance) { | |
9 | var ad = parseYmdHms(tgt), bd = parseYmdHms(cutoff); | |
10 | // We'll allow a little leeway, where tgt is considered before cutoff | |
11 | // even if technically misses the cutoff by a little. | |
12 | return ad < bd-tolerance; | |
13 | } | |
14 | ||
b396fc59 TO |
15 | // Represent a datetime field as if it were a radio ('schedule.mode') and a datetime ('schedule.datetime'). |
16 | // example: <div crm-mailing-radio-date="mySchedule" ng-model="mailing.scheduled_date">...</div> | |
18a8653c | 17 | angular.module('crmMailing').directive('crmMailingRadioDate', function(crmUiAlert) { |
b396fc59 TO |
18 | return { |
19 | require: 'ngModel', | |
20 | link: function($scope, element, attrs, ngModel) { | |
2138186b | 21 | var lastAlert = null; |
b396fc59 TO |
22 | |
23 | var schedule = $scope[attrs.crmMailingRadioDate] = { | |
24 | mode: 'now', | |
25 | datetime: '' | |
26 | }; | |
27 | ||
28 | ngModel.$render = function $render() { | |
29 | var sched = ngModel.$viewValue; | |
30 | if (!_.isEmpty(sched)) { | |
31 | schedule.mode = 'at'; | |
32 | schedule.datetime = sched; | |
33 | } | |
34 | else { | |
35 | schedule.mode = 'now'; | |
36 | schedule.datetime = ''; | |
37 | } | |
38 | }; | |
39 | ||
40 | var updateParent = (function() { | |
41 | switch (schedule.mode) { | |
42 | case 'now': | |
43 | ngModel.$setViewValue(null); | |
44 | schedule.datetime = ''; | |
45 | break; | |
46 | case 'at': | |
47 | schedule.datetime = schedule.datetime || '?'; | |
48 | ngModel.$setViewValue(schedule.datetime); | |
49 | break; | |
50 | default: | |
51 | throw 'Unrecognized schedule mode: ' + schedule.mode; | |
52 | } | |
53 | }); | |
54 | ||
55 | element | |
56 | // Open datepicker when clicking "At" radio | |
57 | .on('click', ':radio[value=at]', function() { | |
58 | $('.crm-form-date', element).focus(); | |
59 | }) | |
60 | // Reset mode if user entered an invalid date | |
61 | .on('change', '.crm-hidden-date', function(e, context) { | |
62 | if (context === 'userInput' && $(this).val() === '' && $(this).siblings('.crm-form-date').val().length) { | |
63 | schedule.mode = 'at'; | |
64 | schedule.datetime = '?'; | |
18a8653c | 65 | } else { |
164c6d09 | 66 | var d = new Date(), |
18a8653c SL |
67 | month = '' + (d.getMonth() + 1), |
68 | day = '' + d.getDate(), | |
164c6d09 SL |
69 | year = d.getFullYear(), |
70 | hours = '' + d.getHours(), | |
71 | minutes = '' + d.getMinutes(); | |
72 | var submittedDate = $(this).val(); | |
18a8653c SL |
73 | if (month.length < 2) month = '0' + month; |
74 | if (day.length < 2) day = '0' + day; | |
53c453fc SL |
75 | if (hours.length < 2) hours = '0' + hours; |
76 | if (minutes.length < 2) minutes = '0' + minutes; | |
18a8653c | 77 | date = [year, month, day].join('-'); |
18a8653c SL |
78 | time = [hours, minutes, "00"].join(':'); |
79 | currentDate = date + ' ' + time; | |
7947eac5 | 80 | var isInPast = (submittedDate.length && submittedDate.match(/^[0-9\-]+ [0-9\:]+$/) && isDateBefore(submittedDate, currentDate, 4*60*60*1000)); |
2138186b SL |
81 | ngModel.$setValidity('dateTimeInThePast', !isInPast); |
82 | if (lastAlert && lastAlert.isOpen) { | |
83 | lastAlert.close(); | |
84 | } | |
85 | if (isInPast) { | |
86 | lastAlert = crmUiAlert({ | |
3bea5218 | 87 | text: ts('The scheduled date and time is in the past'), |
18a8653c SL |
88 | title: ts('Error') |
89 | }); | |
90 | } | |
b396fc59 TO |
91 | } |
92 | }); | |
93 | ||
94 | $scope.$watch(attrs.crmMailingRadioDate + '.mode', updateParent); | |
95 | $scope.$watch(attrs.crmMailingRadioDate + '.datetime', function(newValue, oldValue) { | |
96 | // automatically switch mode based on datetime entry | |
97 | if (typeof oldValue === 'undefined') { | |
98 | oldValue = ''; | |
99 | } | |
100 | if (typeof newValue === 'undefined') { | |
101 | newValue = ''; | |
102 | } | |
103 | if (oldValue !== newValue) { | |
104 | if (_.isEmpty(newValue)) { | |
105 | schedule.mode = 'now'; | |
106 | } | |
107 | else { | |
108 | schedule.mode = 'at'; | |
109 | } | |
110 | } | |
111 | updateParent(); | |
112 | }); | |
113 | } | |
114 | }; | |
115 | }); | |
116 | })(angular, CRM.$, CRM._); |