PageSourceSearch

https://kundportal.inera.se/app_com.modelUtil.jsdbx?c=20

js inera.se collected 2026-10-01 11:35:54 UTC 7,590 bytes, 245 lines download raw bytes

1angular.module("sn.app_common")
2	.service("modelUtil", ['SNAPI', 'TIME', '$rootScope', '$http', '$log', function(SNAPI, TIME, $rootScope, $http, $log) {
3		var modelUtil = this;
4		var DATE_RX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
5		var YMD_RX = /^\d{4}-\d{2}-\d{2}$/;
6		var DEFAULT_GLIDE_LIST_SEPARATOR = ", ";
7
8		// Mapping of legacy ambiguous time zones to equivalent. Taken from Java mappings
9		// See: https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html#SHORT_IDS
10		var SHORT_IDS = {
11			"ACT": "Australia/Darwin",
12			"AET": "Australia/Sydney",
13			"AGT": "America/Argentina/Buenos_Aires",
14			"ART": "Africa/Cairo",
15			"AST": "America/Anchorage",
16			"BET": "America/Sao_Paulo",
17			"BST": "Asia/Dhaka",
18			"CAT": "Africa/Harare",
19			"CNT": "America/St_Johns",
20			"CST": "America/Chicago",
21			"CTT": "Asia/Shanghai",
22			"EAT": "Africa/Addis_Ababa",
23			"ECT": "Europe/Paris",
24			"IET": "America/Indiana/Indianapolis",
25			"IST": "Asia/Kolkata",
26			"JST": "Asia/Tokyo",
27			"MIT": "Pacific/Apia",
28			"NET": "Asia/Yerevan",
29			"NST": "Pacific/Auckland",
30			"PLT": "Asia/Karachi",
31			"PNT": "America/Phoenix",
32			"PRT": "America/Puerto_Rico",
33			"PST": "America/Los_Angeles",
34			"SST": "Pacific/Guadalcanal",
35			"VST": "Asia/Ho_Chi_Minh"
36		};
37
38		/**
39		 * Returns a valid time zone name compensating for ambiguous time zones.
40		 * Defaults to UTC if an unsupported value is provided.
41		 */
42		modelUtil.checkTzName = function(tzName) {
43			if (!tzName)
44				return;
45			// Supported values
46			if (moment.tz.zone(tzName) != null)
47				return tzName;
48			// Ambiguous values
49			if (typeof SHORT_IDS[tzName] !== "undefined")
50				return SHORT_IDS[tzName];
51			// Unknown values
52			return "UTC";
53		};
54
55		var dstOffset = {};
56		/**
57		 * Get the DST offset for a timezone for a given timestamp.
58		 * Takes into account offsets which are not 1 hour, years/locals without DST etc.
59		 *
60		 * timestamp: UTC timestamp
61		 * tzName: name of the timezone.  Defaults to local zone if not present.
62		 */
63		modelUtil.getDSTOffset = function(timestamp, tzName) {
64			var year = new Date(timestamp).getFullYear();
65			tzName = this.checkTzName(tzName);
66
67			var tzKey = (tzName ? tzName : 'local') + "/" + year;
68			var jan = new Date(year, 0, 1);
69
70			if (dstOffset[tzKey])
71				return dstOffset[tzKey];
72
73			if (!tzName) {
74				for (var i = 1; i < 12; i++) {
75					dstOffset[tzKey] = Math.abs(jan.getTimezoneOffset() - (new Date(year,i,1)).getTimezoneOffset());
76					if (dstOffset[tzKey] != 0)
77						break;
78				}
79
80				return dstOffset[tzKey];
81			}
82
83			// Same as above but for a defined timezone.
84			var zone = moment.tz.zone(tzName);
85			for (var j = 1; j < 12; j++) {
86				dstOffset[tzKey] = Math.abs(zone.utcOffset(jan.getTime()) - zone.utcOffset((new Date(year, j, 1)).getTime()));
87				if (dstOffset[tzKey] != 0)
88					break;
89			}
90			return dstOffset[tzKey];
91		};
92
93		/**
94		 * Returns the MS difference between the client local time zone offset and the provided time zone offset.
95		 *
96		 * timestamp: UTC timestamp
97		 * tzName: name of the timezone.  Defaults to local offset if not present.
98		 */
99		modelUtil.getTzToLocalMSDiff = function(timestamp, tzName) {
100			if (!tzName)
101				return 0; // No difference if no time zone.
102
103			return (moment.tz.zone(this.checkTzName(tzName)).utcOffset(timestamp) * TIME.MINUTE * -1) - ((new Date(timestamp)).getTimezoneOffset() * TIME.MINUTE * -1);
104		};
105
106		/**
107		 * Patch object with values from record watcher/table API format
108		 * Adds in 'value_ms' UTC millisecond value for recognised dates
109		 */
110		modelUtil.patchObject = function(obj, patch) {
111			for (var attr in patch) {
112				var permission;
113				if (obj[attr])
114					permission = obj[attr]._canWrite;
115				obj[attr] = patch[attr];
116				if (permission)
117					obj[attr]._canWrite = permission;
118				modelUtil.addValueMS(obj[attr]);
119			}
120		};
121
122		/**
123		 * Adds a value_ms to a date time field.
124		 */
125		modelUtil.addValueMS = function(element) {
126			function strToMS(strDate) {
127				var dtComp = strDate.split(" ");
128				var dComp = dtComp[0].split("-"); //y0, m1, d2
129				var tComp = dtComp[1].split(":"); //h0, mi1, s2
130				return Date.UTC(dComp[0], dComp[1]-1, dComp[2], tComp[0], tComp[1], tComp[2]);
131			}
132
133			function strYMDToMS(strYMD) {
134				var dComp = strYMD.split("-");
135				return Date.UTC(dComp[0], dComp[1]-1, dComp[2]);
136			}
137
138			// If the value matches a date stamp, add a conversion to MS.
139			if (typeof element.value === "string") {
140				if (element.value.match(DATE_RX))
141					element.value_ms = strToMS(element.value);
142				else if (element.value.match(YMD_RX))
143					element.value_ms = strYMDToMS(element.value);
144				else
145					return; //If it's not a date
146			} else
147				return; // If it's not a string
148
149			// Create a forced TZ display_value_ms
150			if (element.tz_name && element.value_ms) {
151				element.display_value_ms = element.value_ms + modelUtil.getTzToLocalMSDiff(element.value_ms, element.tz_name);
152
153				// Adjust display value MS for DST if the value and display value span DST changeover
154				var dispInDST = moment(element.display_value_ms).isDST();
155				var valInDST = moment(element.value_ms).isDST();
156				if (dispInDST && !valInDST)
157					element.display_value_ms -= (this.getDSTOffset(element.value_ms) * TIME.MINUTE);
158				else if (!dispInDST && valInDST)
159					element.display_value_ms += (this.getDSTOffset(element.value_ms) * TIME.MINUTE);
160			}
161
162		};
163
164		/**
165		 * Add a value_ms to all date time fields in record
166		 */
167		modelUtil.addValueMSToAll = function(record) {
168			for (var attr in record)
169				modelUtil.addValueMS(record[attr]);
170		};
171
172		/**
173		 * Adds from now/to now display value as display_value_friendly
174		 */
175		modelUtil.addFriendlyDisplayValue = function(element) {
176			if (!element.value_ms)
177				modelUtil.addValueMS(element);
178
179			if (element.value_ms) { // Check if we actually have an ms value
180				if (element.value_ms > Date.now())
181					element.display_value_friendly = moment(element.value_ms).toNow();
182				else
183					element.display_value_friendly = moment(element.value_ms).fromNow();
184			}
185		};
186
187		/**
188		 * Adds a from now/to now display value to all date elements
189		 */
190		modelUtil.addFriendlyDisplayValueToAll = function(record) {
191			for (var attr in record)
192				modelUtil.addFriendlyDisplayValue(record[attr]);
193		};
194
195		/**
196		 * Converts a GlideList representation to JS array.
197		 */
198		modelUtil.glideListToArray = function(element) {
199			if(!angular.isArray(element.display_value)) {
200				if (element.display_value && typeof element.display_value === "string")
201					element.display_value = element.display_value.split(DEFAULT_GLIDE_LIST_SEPARATOR);
202				else
203					element.display_value = [];
204			}
205
206			if(angular.isArray(element.value))
207				return;
208
209			if (element.value && typeof element.value === "string")
210				element.value = element.value.split(",");
211			else
212				element.value = [];
213		};
214
215		/**
216		 * Simple fail function for REST requests
217		 */
218		modelUtil.failNicely = function(response) {
219			$log.info("REST Failure");
220			$log.info(response);
221
222			if (!(response.data && response.data.error))
223				return;
224
225			//If we have any error info try and get any messages
226			$http.get(SNAPI.SERVICE.NOTIFICATION).then(function(response) {
227				if (response.data.result)
228					response.data.result.forEach(function(err){
229						$rootScope.$broadcast("$$uiNotification", {type: err.type, message: err.text});
230					});
231			},
232			function(response) {
233				$log.info("Notification Failure");
234				$log.info(response);
235			});
236		};
237
238		/**
239		 * Simple check if id is 32 bytes of valid hexadecimal
240		 */
241		modelUtil.isValidSysID = function(sysId) {
242			var re = /^[a-f0-9]{32}$/i;
243			return re.test(sysId);
244		};
245	}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.