|
24 | 24 | (function () { |
25 | 25 | goog.provide("gn_date_picker_directive"); |
26 | 26 |
|
27 | | - var module = angular.module("gn_date_picker_directive", []); |
| 27 | + const module = angular.module("gn_date_picker_directive", []); |
28 | 28 |
|
29 | 29 | /** |
30 | 30 | * Create a widget to handle date composed of |
|
73 | 73 | templateUrl: |
74 | 74 | "../../catalog/components/edit/datepicker/partials/" + "datepicker.html", |
75 | 75 | link: function (scope, element, attrs) { |
| 76 | + // Define DATE_MODE constant |
| 77 | + const DATE_MODE = { |
| 78 | + DATE: "date", |
| 79 | + DATETIME: "datetime", |
| 80 | + MONTH: "month", |
| 81 | + YEAR: "year" |
| 82 | + }; |
| 83 | + // Expose DATE_MODE to scope |
| 84 | + scope.DATE_MODE = DATE_MODE; |
| 85 | + |
| 86 | + const coerceBool = function(val) { |
| 87 | + return val !== 'false' && !!val; |
| 88 | + }; |
| 89 | + |
76 | 90 | // Check if browser support date type or not to |
77 | 91 | // HTML date and time input types. |
78 | 92 | // If not datetimepicker.js is used (it will not |
79 | 93 | // support year or month only mode in this case) |
80 | 94 | scope.dateTypeSupported = Modernizr.inputtypes.date; |
81 | 95 | scope.isValidDate = true; |
82 | | - scope.hideTime = scope.hideTime == "true"; |
| 96 | + scope.hideTime = coerceBool(scope.hideTime); |
83 | 97 | // Hide the date mode picker: date / datetime / month-year / year |
84 | | - scope.hideDateMode = scope.hideDateMode == "true"; |
| 98 | + scope.hideDateMode = coerceBool(scope.hideDateMode); |
85 | 99 |
|
86 | | - var getTimeZoneOffset = function (timeZone) { |
87 | | - var actualTz = timeZone; |
88 | | - if ( |
89 | | - timeZone && |
90 | | - timeZone !== null && |
91 | | - timeZone.trim().toLowerCase() === "browser" |
92 | | - ) { |
| 100 | + // Watch for external changes and re-coerce |
| 101 | + scope.$watch('hideTime', function(newVal) { |
| 102 | + const coerced = coerceBool(newVal); |
| 103 | + if (newVal !== coerced) { |
| 104 | + scope.hideTime = coerced; |
| 105 | + } |
| 106 | + }); |
| 107 | + scope.$watch('hideDateMode', function(newVal) { |
| 108 | + const coerced = coerceBool(newVal); |
| 109 | + if (newVal !== coerced) { |
| 110 | + scope.hideTime = coerced; |
| 111 | + } |
| 112 | + }); |
| 113 | + |
| 114 | + const userTimezone = moment.tz.guess(); |
| 115 | + const uiTimezone = gnGlobalSettings.gnCfg.mods.global.timezone; |
| 116 | + const serverTimezone = gnConfig["system.server.timeZone"]; |
| 117 | + const datePattern = new RegExp( |
| 118 | + "^\\d{4}$|" + |
| 119 | + "^\\d{4}-\\d{2}$|" + |
| 120 | + "^\\d{4}-\\d{2}-\\d{2}$|" + |
| 121 | + "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$" |
| 122 | + ); |
| 123 | + |
| 124 | + const getTimeZoneOffset = function (timeZone) { |
| 125 | + let actualTz = timeZone; |
| 126 | + if (timeZone && timeZone.trim().toLowerCase() === "browser") { |
93 | 127 | actualTz = userTimezone; |
94 | 128 | } |
95 | 129 | return moment |
|
98 | 132 | .replace(/([+-]?[0-9]{2})([0-9]{2})/, "$1:$2"); |
99 | 133 | }; |
100 | 134 |
|
101 | | - scope.timezone = |
102 | | - getTimeZoneOffset(gnGlobalSettings.gnCfg.mods.global.timezone) || |
103 | | - gnConfig["system.server.timeZone"] || |
104 | | - ""; |
105 | | - scope.uiTimeZoneEqualToServer = |
106 | | - gnConfig["system.server.timeZone"] === |
107 | | - gnGlobalSettings.gnCfg.mods.global.timezone; |
| 135 | + scope.timezone = getTimeZoneOffset(uiTimezone) || serverTimezone || ""; |
| 136 | + scope.uiTimeZoneEqualToServer = serverTimezone === uiTimezone; |
108 | 137 | scope.hideTimezone = scope.uiTimeZoneEqualToServer; |
109 | | - var datePattern = new RegExp( |
110 | | - "^\\d{4}$|" + |
111 | | - "^\\d{4}-\\d{2}$|" + |
112 | | - "^\\d{4}-\\d{2}-\\d{2}$|" + |
113 | | - "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$" |
114 | | - ); |
| 138 | + |
115 | 139 | // Format date when datetimepicker is used. |
116 | 140 | scope.formatFromDatePicker = function (date) { |
117 | | - var format = "YYYY-MM-DDTHH:mm:ss"; |
118 | | - var dateTime = moment(date); |
| 141 | + const format = "YYYY-MM-DDTHH:mm:ss"; |
| 142 | + const dateTime = moment(date); |
119 | 143 | scope.dateInput = dateTime.format(format); |
120 | 144 | }; |
121 | 145 |
|
122 | | - var userTimezone = moment.tz.guess(); |
123 | | - |
| 146 | + // Define timezone options |
124 | 147 | scope.timezoneNames = [ |
125 | | - { name: $translate.instant("NoTimezone"), offset: "" }, |
126 | 148 | { |
127 | | - name: $translate.instant("YourTimezone") + " " + userTimezone, |
| 149 | + // No timezone |
| 150 | + name: $translate.instant("NoTimezone"), |
| 151 | + offset: "" |
| 152 | + }, |
| 153 | + { |
| 154 | + // User timezone |
| 155 | + name: |
| 156 | + $translate.instant("YourTimezone") + |
| 157 | + (userTimezone ? " " + userTimezone : ""), |
128 | 158 | offset: getTimeZoneOffset(userTimezone) |
| 159 | + }, |
| 160 | + { |
| 161 | + // Server timezone |
| 162 | + name: |
| 163 | + $translate.instant("CatalogTimezone") + |
| 164 | + (serverTimezone ? " " + serverTimezone : ""), |
| 165 | + offset: getTimeZoneOffset(serverTimezone) |
| 166 | + }, |
| 167 | + { |
| 168 | + // Recommended timezone (browser timezone) |
| 169 | + name: |
| 170 | + $translate.instant("CatalogUiTimezone") + |
| 171 | + (uiTimezone ? " " + uiTimezone : ""), |
| 172 | + offset: getTimeZoneOffset(uiTimezone) |
| 173 | + }, |
| 174 | + { |
| 175 | + // Add separator between predefined timezones and all others |
| 176 | + name: "----", |
| 177 | + offset: "" |
129 | 178 | } |
130 | 179 | ]; |
131 | | - // Add server timezone |
132 | | - scope.timezoneNames.push({ |
133 | | - name: |
134 | | - $translate.instant("CatalogTimezone") + |
135 | | - " " + |
136 | | - gnConfig["system.server.timeZone"], |
137 | | - offset: getTimeZoneOffset(gnConfig["system.server.timeZone"]) |
138 | | - }); |
139 | | - // UI preferred timezone |
140 | | - scope.timezoneNames.push({ |
141 | | - name: |
142 | | - $translate.instant("CatalogUiTimezone") + |
143 | | - " " + |
144 | | - gnGlobalSettings.gnCfg.mods.global.timezone, |
145 | | - offset: getTimeZoneOffset(gnGlobalSettings.gnCfg.mods.global.timezone) |
146 | | - }); |
147 | | - scope.timezoneNames.push({ name: "----", offset: "" }); |
148 | | - _.forEach(moment.tz.names(), function (tz, index, list) { |
| 180 | + // Add all available timezones |
| 181 | + _.forEach(moment.tz.names(), function (tz) { |
149 | 182 | scope.timezoneNames.push({ |
150 | 183 | name: tz, |
151 | 184 | offset: getTimeZoneOffset(tz) |
152 | 185 | }); |
153 | 186 | }); |
154 | 187 |
|
155 | | - scope.mode = |
156 | | - scope.year = |
| 188 | + scope.year = |
157 | 189 | scope.month = |
158 | 190 | scope.time = |
159 | 191 | scope.date = |
160 | 192 | scope.dateDropDownInput = |
161 | 193 | ""; |
| 194 | + scope.mode = DATE_MODE.DATE; // Default mode is date only |
162 | 195 | scope.withIndeterminatePosition = attrs.indeterminatePosition !== undefined; |
163 | 196 |
|
164 | 197 | // Default date is empty |
|
168 | 201 | scope.value = ""; |
169 | 202 | } else if (scope.value.length === 4) { |
170 | 203 | scope.year = parseInt(scope.value); |
171 | | - scope.mode = "year"; |
| 204 | + scope.mode = DATE_MODE.YEAR; |
172 | 205 | scope.hideTimezone = true; |
173 | 206 | } else if (scope.value.length === 7) { |
174 | 207 | scope.month = moment(scope.value, "YYYY-MM").toDate(); |
175 | | - scope.mode = "month"; |
| 208 | + scope.mode = DATE_MODE.MONTH; |
176 | 209 | scope.hideTimezone = true; |
177 | 210 | } else { |
178 | | - var isDateTime = scope.value.indexOf("T") !== -1; |
179 | | - var tokens = scope.value.split("T"); |
| 211 | + // Value is a date or datetime |
| 212 | + const isDateTime = scope.value.indexOf("T") !== -1; |
| 213 | + const tokens = scope.value.split("T"); |
180 | 214 |
|
181 | 215 | // Default to empty string and prevent 'Invalid Date' string to xmlSnippet |
182 | 216 | scope.date = ""; |
|
188 | 222 | ); |
189 | 223 | } |
190 | 224 |
|
191 | | - var time = tokens[1]; |
192 | | - |
193 | | - if (time != undefined) { |
| 225 | + // Process time part (if defined) |
| 226 | + let time = tokens[1]; |
| 227 | + if (time !== undefined) { |
194 | 228 | scope.time = isDateTime ? moment(time, "HH:mm:ss").toDate() : undefined; |
195 | | - |
196 | | - scope.timezone = time.substr(8); |
| 229 | + console.log("parsed time:", scope.time); |
| 230 | + scope.timezone = time.slice(8); |
197 | 231 | scope.hideTimezone = |
198 | 232 | scope.uiTimeZoneEqualToServer && |
199 | | - getTimeZoneOffset(gnGlobalSettings.gnCfg.mods.global.timezone) === |
| 233 | + getTimeZoneOffset(uiTimezone) === |
200 | 234 | scope.timezone; |
| 235 | + scope.mode = DATE_MODE.DATETIME; |
201 | 236 | } else { |
202 | 237 | scope.time = ""; |
203 | 238 | scope.timezone = ""; |
204 | 239 | scope.hideTimezone = scope.uiTimeZoneEqualToServer; |
205 | 240 | } |
206 | 241 | } |
207 | | - if (scope.dateTypeSupported !== true) { |
| 242 | + if (!scope.dateTypeSupported) { |
208 | 243 | scope.dateInput = scope.value; |
209 | 244 | scope.dateDropDownInput = scope.value; |
210 | 245 | } |
211 | 246 |
|
212 | 247 | scope.setMode = function (mode) { |
| 248 | + // Called when user changes date mode |
213 | 249 | scope.mode = mode; |
214 | | - scope.hideTimezone = mode === "year" || mode === "month"; |
| 250 | + scope.hideTimezone = mode === DATE_MODE.YEAR || mode === DATE_MODE.MONTH; |
215 | 251 | }; |
216 | 252 |
|
217 | | - var resetDateIfNeeded = function () { |
218 | | - // Reset date if indeterminate position is now |
219 | | - // or unknows. |
| 253 | + const resetDateIfNeeded = function () { |
| 254 | + // Reset date if indeterminate position is now or unknown |
220 | 255 | if ( |
221 | 256 | scope.withIndeterminatePosition && |
222 | 257 | (scope.indeterminatePosition === "now" || |
|
232 | 267 | }; |
233 | 268 |
|
234 | 269 | // Build xml snippet based on input date. |
235 | | - var buildDate = function () { |
236 | | - var tag = scope.tagName !== undefined ? scope.tagName : "gco:Date"; |
237 | | - var namespace = tag.split(":")[0]; |
| 270 | + const buildDate = function () { |
| 271 | + let tag = scope.tagName !== undefined ? scope.tagName : "gco:Date"; |
| 272 | + const namespace = tag.split(":")[0]; |
238 | 273 |
|
239 | | - if (scope.dateTypeSupported !== true) { |
| 274 | + if (!scope.dateTypeSupported) { |
240 | 275 | // Check date against simple date pattern |
241 | 276 | // to add a css class to highlight error. |
242 | 277 | // Input will be saved anyway. |
|
253 | 288 | : "gco:DateTime"; |
254 | 289 | } |
255 | 290 | scope.dateTime = scope.dateInput; |
256 | | - } else if (scope.mode === "year") { |
| 291 | + } else if (scope.mode === DATE_MODE.YEAR) { |
257 | 292 | scope.dateTime = scope.year; |
258 | | - } else if (scope.mode === "month") { |
| 293 | + } else if (scope.mode === DATE_MODE.MONTH) { |
259 | 294 | scope.dateTime = $filter("date")(scope.month, "yyyy-MM"); |
260 | | - } else if (scope.time) { |
| 295 | + } else if (scope.mode === DATE_MODE.DATETIME && scope.time) { |
261 | 296 | tag = scope.tagName !== undefined ? scope.tagName : "gco:DateTime"; |
262 | | - var time = $filter("date")(scope.time, "HH:mm:ss"); |
| 297 | + let time = $filter("date")(scope.time, "HH:mm:ss"); |
263 | 298 | // TODO: Set seconds, Timezone ? |
264 | 299 | scope.dateTime = $filter("date")(scope.date, "yyyy-MM-dd"); |
265 | 300 | scope.dateTime += "T" + time + scope.timezone; |
|
269 | 304 | if (tag === "") { |
270 | 305 | scope.xmlSnippet = scope.dateTime; |
271 | 306 | } else { |
272 | | - var attribute = ""; |
| 307 | + let attribute = ""; |
273 | 308 | if (scope.withIndeterminatePosition && scope.indeterminatePosition !== "") { |
274 | 309 | attribute = |
275 | 310 | ' indeterminatePosition="' + scope.indeterminatePosition + '"'; |
|
306 | 341 | scope.$watch("indeterminatePosition", resetDateIfNeeded); |
307 | 342 | scope.$watch("xmlSnippet", function () { |
308 | 343 | if (scope.id) { |
309 | | - // This is required on init to have the optionnaly |
| 344 | + // This is required on init to have the optionally |
310 | 345 | // templateFieldDirective initialized first so |
311 | 346 | // that the template is properly computed. |
312 | 347 | $timeout(function () { |
|
0 commit comments