atriusmaps-node-sdk 3.3.834 → 3.3.837
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.
- package/dist/cjs/package.json.js +1 -1
- package/dist/cjs/plugins/flightStatus/src/flightDetailsMapper.js +250 -0
- package/dist/cjs/plugins/flightStatus/src/flightStatus.js +209 -0
- package/dist/cjs/plugins/flightStatus/src/utils.js +34 -0
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +11 -0
- package/dist/cjs/src/configs/sdkHeadless.json.js +2 -0
- package/dist/cjs/src/utils/date.js +29 -0
- package/dist/cjs/utils/constants.js +13 -0
- package/dist/package.json.js +1 -1
- package/dist/plugins/flightStatus/src/flightDetailsMapper.js +1 -0
- package/dist/plugins/flightStatus/src/flightStatus.js +1 -0
- package/dist/plugins/flightStatus/src/utils.js +1 -0
- package/dist/plugins/sdkServer/src/sdkHeadless.js +1 -1
- package/dist/src/configs/sdkHeadless.json.js +1 -1
- package/dist/src/utils/date.js +1 -0
- package/dist/utils/constants.js +1 -0
- package/package.json +1 -1
package/dist/cjs/package.json.js
CHANGED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var luxon = require('luxon');
|
|
4
|
+
var R = require('ramda');
|
|
5
|
+
var date = require('../../../src/utils/date.js');
|
|
6
|
+
var constants = require('../../../utils/constants.js');
|
|
7
|
+
|
|
8
|
+
const FlightType = {
|
|
9
|
+
ARRIVAL: 'arr',
|
|
10
|
+
DEPARTURE: 'dep',
|
|
11
|
+
ALL: 'all',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function mapFlightListItem(nowDate, flight, T, tz, locale) {
|
|
15
|
+
const {
|
|
16
|
+
flightId,
|
|
17
|
+
carrierFsCode,
|
|
18
|
+
flightNumber,
|
|
19
|
+
airline,
|
|
20
|
+
flightType,
|
|
21
|
+
departureAirport,
|
|
22
|
+
arrivalAirport,
|
|
23
|
+
airportResources,
|
|
24
|
+
gatePoi,
|
|
25
|
+
status: statusCode,
|
|
26
|
+
} = flight;
|
|
27
|
+
|
|
28
|
+
const rawDateTime = selectRawDateTime(flight);
|
|
29
|
+
const { localTime, localOldTime } = formatToLocalDateTimes(rawDateTime, tz); // local refers to the venue time
|
|
30
|
+
const status = mapFlightStatus(flightType, statusCode, nowDate, localTime, localOldTime);
|
|
31
|
+
const datePlaceholder =
|
|
32
|
+
flightType === FlightType.DEPARTURE ? 'flightDetails:Departs _date_' : 'flightDetails:Arrives _date_';
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
flightId,
|
|
36
|
+
name: `${R.propOr('', 'name', airline)} - ${carrierFsCode} ${flightNumber}`,
|
|
37
|
+
status,
|
|
38
|
+
statusText: T(`flightDetails:${getFlightStatusText(status)}`),
|
|
39
|
+
baggageClaim:
|
|
40
|
+
flightType === FlightType.ARRIVAL ? prepareBaggageClaim(airportResources.arrivalBagClaim, T) : undefined,
|
|
41
|
+
connectionAirport: prepareAirportLabel(flightType, departureAirport, arrivalAirport, T),
|
|
42
|
+
time: getLocalFormattedTime(localTime, tz, locale),
|
|
43
|
+
oldTime: getLocalFormattedTime(localOldTime, tz, locale),
|
|
44
|
+
date: T(datePlaceholder, {
|
|
45
|
+
date: getLocalFormattedDate(localTime, tz, locale),
|
|
46
|
+
}),
|
|
47
|
+
dateStamp: localTime.toMillis(),
|
|
48
|
+
gate: formatGate(gatePoi),
|
|
49
|
+
gateLabel: T('flightDetails:Gate'),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// todo create test when airline is undefined
|
|
54
|
+
function mapFlightDetails(nowDate, flight, T, tz, locale) {
|
|
55
|
+
const {
|
|
56
|
+
flightNumber,
|
|
57
|
+
flightType,
|
|
58
|
+
departureAirport,
|
|
59
|
+
arrivalAirport,
|
|
60
|
+
airportResources,
|
|
61
|
+
flightStatusUpdates,
|
|
62
|
+
carrierFsCode,
|
|
63
|
+
gatePoi,
|
|
64
|
+
airline,
|
|
65
|
+
status: statusCode,
|
|
66
|
+
} = flight;
|
|
67
|
+
|
|
68
|
+
const pickAirportData = R.pick(['city', 'iata']);
|
|
69
|
+
const rawDateTime = selectRawDateTime(flight);
|
|
70
|
+
const { localTime, localOldTime } = formatToLocalDateTimes(rawDateTime, tz); // local refers to the venue time
|
|
71
|
+
const status = mapFlightStatus(flightType, statusCode, nowDate, localTime, localOldTime);
|
|
72
|
+
const flightTypeLabel = flightType === FlightType.DEPARTURE ? 'Departure' : 'Arrival';
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
flightType,
|
|
76
|
+
flightTypeLabel: T(`flightDetails:${flightTypeLabel}`),
|
|
77
|
+
name: `${R.propOr('', 'name', airline)} - ${carrierFsCode} ${flightNumber}`,
|
|
78
|
+
status,
|
|
79
|
+
statusText: T(`flightDetails:${getFlightStatusText(status)}`),
|
|
80
|
+
baggageClaim:
|
|
81
|
+
flightType === FlightType.ARRIVAL ? prepareBaggageClaim(airportResources.arrivalBagClaim, T) : undefined,
|
|
82
|
+
departure: pickAirportData(departureAirport),
|
|
83
|
+
arrival: pickAirportData(arrivalAirport),
|
|
84
|
+
connectionAirport: prepareAirportLabel(flightType, departureAirport, arrivalAirport, T),
|
|
85
|
+
flightIn: prepareFlightIn(status, flightType, nowDate, localTime, T),
|
|
86
|
+
time: getLocalFormattedTime(localTime, tz, locale),
|
|
87
|
+
oldTime: getLocalFormattedTime(localOldTime, tz, locale),
|
|
88
|
+
date: getLocalFormattedDate(localTime, tz, locale),
|
|
89
|
+
lastUpdated: prepareLastUpdated(nowDate, flightStatusUpdates, T),
|
|
90
|
+
flightDuration: '',
|
|
91
|
+
gateLabel: T('flightDetails:Gate'),
|
|
92
|
+
gate: formatGate(gatePoi),
|
|
93
|
+
tags: [],
|
|
94
|
+
flightIconBaseName: flightType === FlightType.ARRIVAL ? 'arrivals' : 'departures',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// used to sort flights in ASCENDING order of flight arrival/departure time
|
|
99
|
+
const flightComparator = (flight1, flight2) => flight1.dateStamp - flight2.dateStamp;
|
|
100
|
+
|
|
101
|
+
const formatGate = gate => {
|
|
102
|
+
if (!gate) {
|
|
103
|
+
return { name: '-' };
|
|
104
|
+
}
|
|
105
|
+
const name = R.last(gate.name.split(' '));
|
|
106
|
+
return { ...gate, name };
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const prepareFlightIn = (status, flightType, nowDate, flightDate, T) => {
|
|
110
|
+
if (status === constants.FlightLabelStatus.DEPARTED) {
|
|
111
|
+
return T('flightDetails:Departed');
|
|
112
|
+
} else if (status === constants.FlightLabelStatus.ARRIVED) {
|
|
113
|
+
return T('flightDetails:Arrived');
|
|
114
|
+
} else if (status === constants.FlightLabelStatus.CANCELLED) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const prefix = flightType === FlightType.DEPARTURE ? 'Departs' : 'Arrives';
|
|
119
|
+
const minutes = minutesBetween(nowDate, flightDate);
|
|
120
|
+
return T(`flightDetails:${prefix} in _minutes_ minute`, { count: minutes });
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const prepareLastUpdated = (nowDate, flightStatusUpdates, T) => {
|
|
124
|
+
const updateDate = R.compose(R.path(['updatedAt', 'dateUtc']), R.last)(flightStatusUpdates);
|
|
125
|
+
const minutes = minutesBetween(nowDate, getLocalGMTDate(updateDate));
|
|
126
|
+
|
|
127
|
+
if (minutes < 10) {
|
|
128
|
+
return T('flightDetails:Last updated a few minutes ago');
|
|
129
|
+
} else if (minutes < 60) {
|
|
130
|
+
return T('flightDetails:Last updated _minutes_ minutes ago', { minutes });
|
|
131
|
+
} else {
|
|
132
|
+
return T('flightDetails:Last updated over an hour ago');
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check minutes difference between two Luxon dates.
|
|
138
|
+
* @param {DateTime} firstDate
|
|
139
|
+
* @param {DateTime} secondDate
|
|
140
|
+
*/
|
|
141
|
+
const minutesBetween = (firstDate, secondDate) => {
|
|
142
|
+
const ms = Math.abs(firstDate - secondDate);
|
|
143
|
+
return date.msToMin(ms);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const selectRawDateTime = ({ flightType, operationalTimes, departureDate, arrivalDate }) =>
|
|
147
|
+
flightType === FlightType.DEPARTURE
|
|
148
|
+
? prepareRawDateTime(departureDate, operationalTimes.estimatedGateDeparture)
|
|
149
|
+
: prepareRawDateTime(arrivalDate, operationalTimes.estimatedGateArrival);
|
|
150
|
+
|
|
151
|
+
const prepareRawDateTime = (dateTime, estimatedTime) => {
|
|
152
|
+
const localDate = dateTime.dateLocal || dateTime.dateUtc;
|
|
153
|
+
const estimatedDate = estimatedTime.dateLocal || estimatedTime.dateUtc;
|
|
154
|
+
const isTimeChanged = estimatedDate && localDate !== estimatedDate;
|
|
155
|
+
return isTimeChanged ? { time: estimatedDate, oldTime: localDate } : { time: localDate };
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Parse flight dates strings to Luxon dates relative to the venue timezone.
|
|
160
|
+
* @param {{ time: string, oldTime: string }} - times
|
|
161
|
+
* @param {string} tz - venue timezone
|
|
162
|
+
*/
|
|
163
|
+
const formatToLocalDateTimes = ({ time, oldTime }, tz) => ({
|
|
164
|
+
localTime: getLocalGMTDate(time, tz),
|
|
165
|
+
localOldTime: getLocalGMTDate(oldTime, tz),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
function mapFlightStatus(flightType, status, nowDate, localTime, localOldTime) {
|
|
169
|
+
if (!localTime) {
|
|
170
|
+
return constants.FlightLabelStatus.UNKNOWN;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (nowDate > localTime) {
|
|
174
|
+
return lateFlightStatus(flightType);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
status = status.toUpperCase();
|
|
178
|
+
if (status === 'C') {
|
|
179
|
+
return constants.FlightLabelStatus.CANCELLED;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!localOldTime) {
|
|
183
|
+
return constants.FlightLabelStatus.ON_TIME;
|
|
184
|
+
} else if (localTime > localOldTime) {
|
|
185
|
+
return constants.FlightLabelStatus.DELAYED;
|
|
186
|
+
} else {
|
|
187
|
+
return constants.FlightLabelStatus.EARLY;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const getFlightStatusText = status => {
|
|
192
|
+
switch (status) {
|
|
193
|
+
case constants.FlightLabelStatus.ON_TIME:
|
|
194
|
+
return 'on-time';
|
|
195
|
+
case constants.FlightLabelStatus.EARLY:
|
|
196
|
+
return 'early';
|
|
197
|
+
case constants.FlightLabelStatus.DELAYED:
|
|
198
|
+
return 'delayed';
|
|
199
|
+
case constants.FlightLabelStatus.CANCELLED:
|
|
200
|
+
return 'cancelled';
|
|
201
|
+
case constants.FlightLabelStatus.DEPARTED:
|
|
202
|
+
return 'departed';
|
|
203
|
+
case constants.FlightLabelStatus.ARRIVED:
|
|
204
|
+
return 'arrived';
|
|
205
|
+
default:
|
|
206
|
+
return 'unknown';
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const lateFlightStatus = flightType =>
|
|
211
|
+
flightType === FlightType.DEPARTURE ? constants.FlightLabelStatus.DEPARTED : constants.FlightLabelStatus.ARRIVED;
|
|
212
|
+
|
|
213
|
+
const prepareAirportLabel = (flightType, departureAirport, arrivalAirport, T) =>
|
|
214
|
+
flightType === FlightType.DEPARTURE
|
|
215
|
+
? T(formatAirportLabel('To'), arrivalAirport)
|
|
216
|
+
: T(formatAirportLabel('From'), departureAirport);
|
|
217
|
+
|
|
218
|
+
const formatAirportLabel = prefix => `flightDetails:${prefix} _city_ (_iata_)`;
|
|
219
|
+
|
|
220
|
+
const prepareBaggageClaim = (claimNum, T) =>
|
|
221
|
+
claimNum &&
|
|
222
|
+
T('flightDetails:Collect luggage from Baggage Claim _claimNum_', {
|
|
223
|
+
claimNum,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Parse date string to Luxon date relative to the venue timezone.
|
|
228
|
+
* @param {string} date string (can be UTC)
|
|
229
|
+
* @param {string} tz - venue timezone
|
|
230
|
+
*/
|
|
231
|
+
const getLocalGMTDate = (date, tz) => date && luxon.DateTime.fromISO(date, { zone: tz });
|
|
232
|
+
|
|
233
|
+
const getLocalFormattedDate = (dateStr, tz, locale = 'en-US') =>
|
|
234
|
+
dateStr && luxon.DateTime.fromISO(dateStr, { zone: tz }).setLocale(locale).toFormat('EEE, d MMMM');
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Parse date string to Luxon date in venue timezone and return short time.
|
|
238
|
+
* Set locale, so the returned time can match the format used in particular locale.
|
|
239
|
+
* E.g. for 'en-US' it will return "6:00 AM". For 'fr' it will return "6:00".
|
|
240
|
+
* @param {string} dateStr - date string (can be UTC)
|
|
241
|
+
* @param {string} tz - timezone string
|
|
242
|
+
* @param {string} [locale='en-US'] locale string
|
|
243
|
+
*/
|
|
244
|
+
const getLocalFormattedTime = (dateStr, tz, locale = 'en-US') =>
|
|
245
|
+
dateStr && date.formatTime(luxon.DateTime.fromISO(dateStr, { zone: tz }), locale);
|
|
246
|
+
|
|
247
|
+
exports.FlightType = FlightType;
|
|
248
|
+
exports.flightComparator = flightComparator;
|
|
249
|
+
exports.mapFlightDetails = mapFlightDetails;
|
|
250
|
+
exports.mapFlightListItem = mapFlightListItem;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var FlexSearch = require('flexsearch');
|
|
4
|
+
var luxon = require('luxon');
|
|
5
|
+
var R = require('ramda');
|
|
6
|
+
var flightDetailsMapper = require('./flightDetailsMapper.js');
|
|
7
|
+
var utils = require('./utils.js');
|
|
8
|
+
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var R__namespace = /*#__PURE__*/_interopNamespaceDefault(R);
|
|
27
|
+
|
|
28
|
+
function create(app, config) {
|
|
29
|
+
const createIndex = () =>
|
|
30
|
+
new FlexSearch.Index({
|
|
31
|
+
tokenize: 'forward',
|
|
32
|
+
});
|
|
33
|
+
const init = async () => {
|
|
34
|
+
state.tz = await app.bus.get('venueData/getVenueTimezone');
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const state = {
|
|
38
|
+
lastUpdated: 0,
|
|
39
|
+
flights: { dep: null, arr: null },
|
|
40
|
+
index: { dep: createIndex(), arr: createIndex() },
|
|
41
|
+
gates: null,
|
|
42
|
+
apiError: false,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const enrichData = (flights, airportsArg, airlinesArg, flightType) => {
|
|
46
|
+
const airports = airportsArg.reduce((acc, obj) => {
|
|
47
|
+
return { ...acc, [obj.iata]: obj };
|
|
48
|
+
}, {});
|
|
49
|
+
const airlines = airlinesArg
|
|
50
|
+
.flatMap(airline => [
|
|
51
|
+
{ code: airline.iata, airline },
|
|
52
|
+
{ code: airline.icao, airline },
|
|
53
|
+
])
|
|
54
|
+
.filter(({ code }) => code)
|
|
55
|
+
.reduce((acc, { code, airline }) => {
|
|
56
|
+
return { ...acc, [code]: airline };
|
|
57
|
+
}, {});
|
|
58
|
+
return flights.map(flight => {
|
|
59
|
+
const gateId =
|
|
60
|
+
flightType === flightDetailsMapper.FlightType.DEPARTURE
|
|
61
|
+
? R__namespace.pathOr('', ['airportResources', 'departureGate'], flight)
|
|
62
|
+
: R__namespace.pathOr('', ['airportResources', 'arrivalGate'], flight);
|
|
63
|
+
const gatePoi = state.gates[gateId];
|
|
64
|
+
return {
|
|
65
|
+
...flight,
|
|
66
|
+
flightType,
|
|
67
|
+
gatePoi,
|
|
68
|
+
airline: airlines[flight.carrierFsCode],
|
|
69
|
+
departureAirport: airports[flight.departureAirportFsCode],
|
|
70
|
+
arrivalAirport: airports[flight.arrivalAirportFsCode],
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const updateIndexes = (type, flightStatuses) => {
|
|
76
|
+
state.index[type] = createIndex();
|
|
77
|
+
state.flights[type] = {};
|
|
78
|
+
flightStatuses.forEach(status => {
|
|
79
|
+
state.index[type].add(status.flightId, createFlightSearchEntry(status));
|
|
80
|
+
state.flights[type][status.flightId] = status;
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const searchPropertiesPaths = [
|
|
85
|
+
['flightNumber'],
|
|
86
|
+
['airline', 'iata'],
|
|
87
|
+
['airline', 'name'],
|
|
88
|
+
['arrivalAirport', 'iata'],
|
|
89
|
+
['arrivalAirport', 'city'],
|
|
90
|
+
['departureAirport', 'iata'],
|
|
91
|
+
['departureAirport', 'city'],
|
|
92
|
+
];
|
|
93
|
+
const createFlightSearchEntry = R__namespace.pipe(
|
|
94
|
+
// apply each function one after another to passed object
|
|
95
|
+
R__namespace.juxt(R__namespace.map(R__namespace.path, searchPropertiesPaths)), // safe collect of nested properties into list
|
|
96
|
+
R__namespace.filter(R__namespace.identity), // filter 'falsy' values
|
|
97
|
+
R__namespace.join(' '),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const indexGatePois = async () => {
|
|
101
|
+
if (state.gates === null) {
|
|
102
|
+
const gatePois = await app.bus.get('poi/getByCategoryId', {
|
|
103
|
+
categoryId: 'gate',
|
|
104
|
+
});
|
|
105
|
+
const parseGate = ({ name }) => R__namespace.tail(name.replace(',', '').split(' '));
|
|
106
|
+
const pairs = R__namespace.reduce(
|
|
107
|
+
(acc, poi) => {
|
|
108
|
+
const gateIds = parseGate(poi);
|
|
109
|
+
const gateAndPoiPairs = R__namespace.map(gateId => [gateId, poi], gateIds);
|
|
110
|
+
return [...acc, ...gateAndPoiPairs];
|
|
111
|
+
},
|
|
112
|
+
[],
|
|
113
|
+
Object.values(gatePois),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
state.gates = R__namespace.fromPairs(pairs);
|
|
117
|
+
}
|
|
118
|
+
return state;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const updateFlights = async () => {
|
|
122
|
+
await indexGatePois();
|
|
123
|
+
const venueData = await app.bus.get('venueData/getVenueData');
|
|
124
|
+
const params = new URLSearchParams();
|
|
125
|
+
const locale = app.i18n?.().language;
|
|
126
|
+
if (locale) {
|
|
127
|
+
params.append('locale', locale);
|
|
128
|
+
}
|
|
129
|
+
if (config?.timeRange) {
|
|
130
|
+
const now = Date.now();
|
|
131
|
+
const startDate = new Date(now - config.timeRange.beforeNowMs).toISOString();
|
|
132
|
+
const endDate = new Date(now + config.timeRange.afterNowMs).toISOString();
|
|
133
|
+
params.append('startDate', startDate);
|
|
134
|
+
params.append('endDate', endDate);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const baseURL = `https://marketplace.locuslabs.com/venueId/${venueData.baseVenueId}/flight-status`;
|
|
138
|
+
const apiURL = params.toString() ? `${baseURL}?${params.toString()}` : baseURL;
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const response = await fetch(apiURL);
|
|
142
|
+
const data = await response.json();
|
|
143
|
+
[flightDetailsMapper.FlightType.ARRIVAL, flightDetailsMapper.FlightType.DEPARTURE].forEach(type => {
|
|
144
|
+
const key = type === flightDetailsMapper.FlightType.DEPARTURE ? 'departures' : 'arrivals';
|
|
145
|
+
const { airports, airlines } = data.data[key].appendix;
|
|
146
|
+
updateIndexes(type, enrichData(data.data[key].flightStatuses, airports, airlines, type));
|
|
147
|
+
});
|
|
148
|
+
state.apiError = false;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
state.apiError = true;
|
|
151
|
+
console.error('Error from flight status api call', error);
|
|
152
|
+
[flightDetailsMapper.FlightType.ARRIVAL, flightDetailsMapper.FlightType.DEPARTURE].forEach(type => {
|
|
153
|
+
// In the case of an api error we still need to update current flights to an empty array, otherwise we get an object undefined error
|
|
154
|
+
updateIndexes(type, []);
|
|
155
|
+
});
|
|
156
|
+
} finally {
|
|
157
|
+
state.lastUpdated = Date.now();
|
|
158
|
+
}
|
|
159
|
+
return state;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const checkFlights = async () => {
|
|
163
|
+
// if the data was not update in the last minute, update it
|
|
164
|
+
if (Date.now() - state.lastUpdated > 60 * 1000) {
|
|
165
|
+
await updateFlights();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Does query for flight status info. Before doing anything requests verification
|
|
171
|
+
* if the date is up-to-date
|
|
172
|
+
* @param {String} term - term to query the search index, default null, if null returns all flights of provided type
|
|
173
|
+
* @param {String} type - type of flights to query for, default 'dep' (departures)
|
|
174
|
+
*/
|
|
175
|
+
app.bus.on('flightStatus/query', async ({ term = null, type = flightDetailsMapper.FlightType.DEPARTURE } = {}) => {
|
|
176
|
+
await checkFlights();
|
|
177
|
+
return utils.searchFlights(term, type, state);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Fetches flight info based on flight ID, make sure the data is up-tp-date first
|
|
182
|
+
* @param {String} flightId - id of the flight we want to get
|
|
183
|
+
*/
|
|
184
|
+
app.bus.on('flightStatus/getFlight', async ({ flightId }) => {
|
|
185
|
+
await checkFlights();
|
|
186
|
+
const flight = state.flights.dep[flightId] || state.flights.arr[flightId];
|
|
187
|
+
return flight;
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
app.bus.on('flightStatus/mapFlightDetails', async ({ flight }) => {
|
|
191
|
+
return flightDetailsMapper.mapFlightDetails(luxon.DateTime.local(), flight, app.gt(), state.tz, app.i18n().language);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
app.bus.on('flightStatus/mapFlightListItems', async ({ flights }) => {
|
|
195
|
+
return flights
|
|
196
|
+
.map(flight => flightDetailsMapper.mapFlightListItem(luxon.DateTime.local(), flight, app.gt(), state.tz, app.i18n().language))
|
|
197
|
+
.sort(flightDetailsMapper.flightComparator);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
init,
|
|
202
|
+
internal: {
|
|
203
|
+
updateFlights,
|
|
204
|
+
indexGatePois,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
exports.create = create;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var flightDetailsMapper = require('./flightDetailsMapper.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Searches flights by term or returns all flights of specified type(s)
|
|
7
|
+
* @param {String} term - Search term, or null to return all flights
|
|
8
|
+
* @param {String} type - Flight type: 'dep', 'arr', or 'all'
|
|
9
|
+
* @param {Object} state - Flight state object { index, flights, apiError }
|
|
10
|
+
* @returns {Object} { flights: Array, apiError: Boolean }
|
|
11
|
+
*/
|
|
12
|
+
const searchFlights = (term, type, state) => {
|
|
13
|
+
const { index, flights, apiError } = state;
|
|
14
|
+
const types = type === flightDetailsMapper.FlightType.ALL ? [flightDetailsMapper.FlightType.DEPARTURE, flightDetailsMapper.FlightType.ARRIVAL] : [type];
|
|
15
|
+
|
|
16
|
+
let flightResults;
|
|
17
|
+
if (term) {
|
|
18
|
+
flightResults = types.flatMap(t => {
|
|
19
|
+
const ids = index[t].search({ query: term });
|
|
20
|
+
return ids.map(id => flights[t][id]);
|
|
21
|
+
});
|
|
22
|
+
} else {
|
|
23
|
+
flightResults = types.flatMap(t => Object.values(flights[t]));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (flightResults.length === 0 && /^\w\w\d{2,4}$/.test(term)) {
|
|
27
|
+
// When user seach for flight UA4567, we will need to convert it to UA_4567 for a valid search result.
|
|
28
|
+
const modifiedTerm = term.replace(/(\w\w)(\d{2,4})/, '$1_$2');
|
|
29
|
+
return searchFlights(modifiedTerm, type, state);
|
|
30
|
+
}
|
|
31
|
+
return { flights: flightResults, apiError };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
exports.searchFlights = searchFlights;
|
|
@@ -69,6 +69,13 @@ const headlessCommands = [
|
|
|
69
69
|
{ name: 'details', type: 'boolean', optional: true },
|
|
70
70
|
],
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
command: 'getFlightStatus',
|
|
74
|
+
args: [
|
|
75
|
+
{ name: 'term', type: 'string', optional: true },
|
|
76
|
+
{ name: 'type', type: 'string', optional: true },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
72
79
|
];
|
|
73
80
|
|
|
74
81
|
function handleHeadless(app) {
|
|
@@ -139,6 +146,10 @@ function handleHeadless(app) {
|
|
|
139
146
|
return details ? poiList : poiIdList;
|
|
140
147
|
}),
|
|
141
148
|
);
|
|
149
|
+
|
|
150
|
+
app.bus.on('clientAPI/getFlightStatus', async ({ term, type = 'all' }) =>
|
|
151
|
+
app.bus.get('flightStatus/query', { term, type }),
|
|
152
|
+
);
|
|
142
153
|
}
|
|
143
154
|
|
|
144
155
|
exports.handleHeadless = handleHeadless;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var luxon = require('luxon');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Pass in a luxon DateTime object and receive a simple formatted time string
|
|
7
|
+
* This adjusts for odd handling of Icelandic times by Chromium/Blink browser engines.
|
|
8
|
+
* @param {DateTime|Date} datetime A JS Date or a luxon DateTime holding the time you wish to display
|
|
9
|
+
* @param {string} locale The locale (2 character country code - plus optional variant)
|
|
10
|
+
* @returns {string} A time formatted for display
|
|
11
|
+
*/
|
|
12
|
+
const formatTime = (datetime, locale = 'en') => {
|
|
13
|
+
if (datetime instanceof Date) {
|
|
14
|
+
datetime = luxon.DateTime(datetime);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// The following is to force Icelandic (is) locale to display in 24 hour format (the "ca" locale
|
|
18
|
+
// is an arbitrarily selected locale that uses 24 hour format)
|
|
19
|
+
// This is due to Chrome/Chromium/Blink not supporting Icelandic well. See https://issues.chromium.org/issues/40624456
|
|
20
|
+
if (locale === 'is') {
|
|
21
|
+
locale = 'ca';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return datetime.setLocale(locale).toLocaleString(luxon.DateTime.TIME_SIMPLE);
|
|
25
|
+
};
|
|
26
|
+
const msToMin = ms => Math.ceil(ms / 60 / 1000);
|
|
27
|
+
|
|
28
|
+
exports.formatTime = formatTime;
|
|
29
|
+
exports.msToMin = msToMin;
|
package/dist/package.json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e="web-engine",t="3.3.
|
|
1
|
+
var e="web-engine",t="3.3.837",s="UNLICENSED",r="module",o="src/main.js",i=["demo","deploy","nodesdk","src/extModules/flexapi","services/*","libraries/*"],a={"build-storybook":"storybook build",colors:"cat utils/colors1.txt && node utils/processColors.js | pbcopy && cat utils/colors2.txt","cypress:comp":"cypress open --component --browser chrome","cypress:comp:ci":"cypress run --component",demo:"cd demo/ && yarn start",dev:"yarn mol e2e","format:check":"yarn prettier . --check","format:fix":"yarn prettier . --write",goProd:"cd deploy && scripts/goProd.sh",goStaging:"deploy/scripts/goStaging.sh","icons:convert":"node scripts/convertSvgToJsx.mjs",lint:"eslint . --ext .js,.jsx,.ts,.tsx",mod:"demo/startMod.sh",mol:"demo/startMol.sh","mol:build":"demo/startMolBuild.sh",molProd:"cd deploy && yarn buildAndRunMol","playwright:ci":"yarn playwright test --grep-invert sdk","playwright:ci:failed":"yarn playwright test --last-failed --grep-invert sdk","playwright:sdk":"yarn start-server-and-test 'cd ./deploy && yarn buildDev && yarn serveLocal' 8085 'cd ./test/sdk && npx http-server' 8080 'yarn playwright test sdk --ui'","playwright:ui":"yarn playwright test --ui --grep-invert sdk",prepare:"husky",storybook:"storybook dev -p 6006",test:"vitest run","test-watch":"vitest --watch","test:all":"yarn lint && yarn format:check && yarn test && yarn cypress:comp:ci && yarn playwright:ci","test:mod":"playwright test --config=playwright.mod.config.ts",typecheck:"tsc -p tsconfig.checkjs.json"},l=["defaults"],n={"@azure/event-hubs":"^5.12.2","@csstools/normalize.css":"^11.0.1","@dnd-kit/core":"^6.3.1","@dnd-kit/modifiers":"^9.0.0","@dnd-kit/sortable":"^10.0.0","@dnd-kit/utilities":"^3.2.2","@locus-labs/mod-badge":"^0.1.102","@locus-labs/mod-footer":"^0.0.111","@locus-labs/mod-header":"^0.0.105","@locus-labs/mod-location-marker":"^0.0.104","@locus-labs/mod-map-legend":"^0.0.104","@locus-labs/mod-offscreen-indicator":"^0.0.104","@locus-labs/mod-pin":"^0.0.104","@locus-labs/mod-qr-code-card":"^0.0.104","@locus-labs/mod-qr-code-window":"^0.0.105","@locus-labs/mod-walk-time-matrix":"^0.0.103","@mapbox/mapbox-gl-draw":"^1.5.0","@mapbox/mapbox-gl-draw-static-mode":"^1.0.1","@microsoft/applicationinsights-web":"^3.3.6","@turf/area":"^7.2.0","@turf/bbox-clip":"^7.2.0","@turf/bbox-polygon":"^7.2.0","@turf/bearing":"^7.2.0","@turf/circle":"^7.2.0","@turf/helpers":"^7.2.0","@turf/point-to-line-distance":"^7.2.0","@vitejs/plugin-react":"^5.2.0","@zumer/snapdom":"^2.9.0","axe-core":"^4.10.3",browserslist:"^4.27.0","crypto-browserify":"^3.12.1","cypress-multi-reporters":"^2.0.5","cypress-real-events":"^1.14.0",dompurify:"^3.3.3","file-loader":"^6.2.0",flexsearch:"^0.7.43","h3-js":"^4.1.0",i18next:"^26.0.0","i18next-browser-languagedetector":"^6.1.1",jsdom:"^25.0.1",jsonschema:"^1.5.0",luxon:"^3.5.0","maplibre-gl":"^4.7.1","mini-css-extract-plugin":"^2.9.2","mocha-junit-reporter":"^2.2.1",mochawesome:"^7.1.3","node-polyfill-webpack-plugin":"^4.1.0","path-browserify":"^1.0.1",pmtiles:"^4.4.0","prop-types":"^15.8.1","qrcode.react":"^4.2.0",ramda:"^0.30.1",react:"^19.2.4","react-compound-slider":"^3.4.0","react-dom":"^19.2.4","react-json-editor-ajrm":"^2.5.14","react-svg":"^16.3.0","react-virtualized-auto-sizer":"^1.0.25","react-window":"^1.8.11","smoothscroll-polyfill":"^0.4.4","styled-components":"^6.1.15","styled-normalize":"^8.1.1","throttle-debounce":"^5.0.2",trackjs:"^3.10.4","ua-parser-js":"^0.7.40",uuid:"11.1.0",zousan:"^3.0.1","zousan-plus":"^4.0.1"},c={"@applitools/eyes-playwright":"^1.46.8","@axe-core/playwright":"^4.10.2","@azure/identity":"^4.13.0","@azure/playwright":"^1.0.0","@playwright/test":"^1.59.1","@storybook/addon-essentials":"^8.6.15","@storybook/blocks":"^8.6.15","@storybook/react":"^8.6.15","@storybook/react-vite":"^8.6.15","@testing-library/jest-dom":"^6.6.3","@types/react":"^19.0.10","@types/react-dom":"^19.0.4","@typescript-eslint/eslint-plugin":"^8.26.1","@typescript-eslint/parser":"^8.26.1","chai-colors":"^1.0.1","css-loader":"^7.1.2",cypress:"^15.0.0","cypress-wait-until":"^3.0.2",eslint:"^8.57.1","eslint-config-prettier":"^10.1.8","eslint-config-standard":"^17.1.0","eslint-import-resolver-alias":"^1.1.2","eslint-import-resolver-typescript":"^3.9.1","eslint-plugin-cypress":"^2.15.2","eslint-plugin-import":"^2.31.0","eslint-plugin-n":"^17.16.2","eslint-plugin-node":"^11.1.0","eslint-plugin-playwright":"^2.2.2","eslint-plugin-promise":"^5.2.0","eslint-plugin-react":"^7.37.4","eslint-plugin-standard":"^5.0.0","eslint-plugin-vitest":"^0.5.4","fetch-mock":"^12.6.0",glob:"^11.0.1",husky:"^9.1.7","lint-staged":"^16.4.0","node-fetch":"^2.7.0","null-loader":"^4.0.1",nx:"19.8.14","nx-remotecache-azure":"^19.0.0","os-browserify":"^0.3.0",prettier:"^3.8.3","start-server-and-test":"^2.0.11",storybook:"^8.6.15",typescript:"^5.8.2",vite:"^7.3.2",vitest:"^4.1.2","webpack-merge":"^6.0.1"},p="yarn@4.13.0",d={node:"24.x"},y={},m={name:e,version:t,private:!0,license:s,type:r,main:o,workspaces:i,scripts:a,"lint-staged":{"*.js":["eslint --fix","prettier --check"],"*.{json,md,css,ts,tsx,jsx}":["prettier --check"],"src/i18n/**/*.json":["node utils/sort-json.js","prettier --write"]},browserslist:l,dependencies:n,devDependencies:c,packageManager:p,engines:d,nx:y};export{l as browserslist,m as default,n as dependencies,c as devDependencies,d as engines,s as license,o as main,e as name,y as nx,p as packageManager,a as scripts,r as type,t as version,i as workspaces};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DateTime as t}from"luxon";import{pick as e,propOr as a,last as r,compose as i,path as l}from"ramda";import{formatTime as s,msToMin as o}from"../../../src/utils/date.js";import{FlightLabelStatus as n}from"../../../utils/constants.js";const m={ARRIVAL:"arr",DEPARTURE:"dep",ALL:"all"};function u(t,e,r,i,l){const{flightId:s,carrierFsCode:o,flightNumber:n,airline:u,flightType:d,departureAirport:g,arrivalAirport:D,airportResources:f,gatePoi:p,status:E}=e,L=A(e),{localTime:C,localOldTime:U}=R(L,i),P=h(d,E,t,C,U),$=d===m.DEPARTURE?"flightDetails:Departs _date_":"flightDetails:Arrives _date_";return{flightId:s,name:`${a("","name",u)} - ${o} ${n}`,status:P,statusText:r(`flightDetails:${T(P)}`),baggageClaim:d===m.ARRIVAL?I(f.arrivalBagClaim,r):void 0,connectionAirport:v(d,g,D,r),time:N(C,i,l),oldTime:N(U,i,l),date:r($,{date:_(C,i,l)}),dateStamp:C.toMillis(),gate:c(p),gateLabel:r("flightDetails:Gate")}}function d(t,r,i,l,s){const{flightNumber:o,flightType:n,departureAirport:u,arrivalAirport:d,airportResources:g,flightStatusUpdates:p,carrierFsCode:E,gatePoi:L,airline:C,status:U}=r,P=e(["city","iata"]),$=A(r),{localTime:y,localOldTime:O}=R($,l),S=h(n,U,t,y,O);return{flightType:n,flightTypeLabel:i(`flightDetails:${n===m.DEPARTURE?"Departure":"Arrival"}`),name:`${a("","name",C)} - ${E} ${o}`,status:S,statusText:i(`flightDetails:${T(S)}`),baggageClaim:n===m.ARRIVAL?I(g.arrivalBagClaim,i):void 0,departure:P(u),arrival:P(d),connectionAirport:v(n,u,d,i),flightIn:D(S,n,t,y,i),time:N(y,l,s),oldTime:N(O,l,s),date:_(y,l,s),lastUpdated:f(t,p,i),flightDuration:"",gateLabel:i("flightDetails:Gate"),gate:c(L),tags:[],flightIconBaseName:n===m.ARRIVAL?"arrivals":"departures"}}const g=(t,e)=>t.dateStamp-e.dateStamp,c=t=>{if(!t)return{name:"-"};const e=r(t.name.split(" "));return{...t,name:e}},D=(t,e,a,r,i)=>{if(t===n.DEPARTED)return i("flightDetails:Departed");if(t===n.ARRIVED)return i("flightDetails:Arrived");if(t===n.CANCELLED)return null;return i(`flightDetails:${e===m.DEPARTURE?"Departs":"Arrives"} in _minutes_ minute`,{count:p(a,r)})},f=(t,e,a)=>{const s=i(l(["updatedAt","dateUtc"]),r)(e),o=p(t,U(s));return o<10?a("flightDetails:Last updated a few minutes ago"):o<60?a("flightDetails:Last updated _minutes_ minutes ago",{minutes:o}):a("flightDetails:Last updated over an hour ago")},p=(t,e)=>{const a=Math.abs(t-e);return o(a)},A=({flightType:t,operationalTimes:e,departureDate:a,arrivalDate:r})=>t===m.DEPARTURE?E(a,e.estimatedGateDeparture):E(r,e.estimatedGateArrival),E=(t,e)=>{const a=t.dateLocal||t.dateUtc,r=e.dateLocal||e.dateUtc;return r&&a!==r?{time:r,oldTime:a}:{time:a}},R=({time:t,oldTime:e},a)=>({localTime:U(t,a),localOldTime:U(e,a)});function h(t,e,a,r,i){return r?a>r?L(t):"C"===(e=e.toUpperCase())?n.CANCELLED:i?r>i?n.DELAYED:n.EARLY:n.ON_TIME:n.UNKNOWN}const T=t=>{switch(t){case n.ON_TIME:return"on-time";case n.EARLY:return"early";case n.DELAYED:return"delayed";case n.CANCELLED:return"cancelled";case n.DEPARTED:return"departed";case n.ARRIVED:return"arrived";default:return"unknown"}},L=t=>t===m.DEPARTURE?n.DEPARTED:n.ARRIVED,v=(t,e,a,r)=>t===m.DEPARTURE?r(C("To"),a):r(C("From"),e),C=t=>`flightDetails:${t} _city_ (_iata_)`,I=(t,e)=>t&&e("flightDetails:Collect luggage from Baggage Claim _claimNum_",{claimNum:t}),U=(e,a)=>e&&t.fromISO(e,{zone:a}),_=(e,a,r="en-US")=>e&&t.fromISO(e,{zone:a}).setLocale(r).toFormat("EEE, d MMMM"),N=(e,a,r="en-US")=>e&&s(t.fromISO(e,{zone:a}),r);export{m as FlightType,g as flightComparator,d as mapFlightDetails,u as mapFlightListItem};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"flexsearch";import{DateTime as a}from"luxon";import*as e from"ramda";import{FlightType as r,mapFlightDetails as i,mapFlightListItem as n,flightComparator as o}from"./flightDetailsMapper.js";import{searchFlights as s}from"./utils.js";function l(l,p){const u=()=>new t.Index({tokenize:"forward"}),g={lastUpdated:0,flights:{dep:null,arr:null},index:{dep:u(),arr:u()},gates:null,apiError:!1},c=(t,a)=>{g.index[t]=u(),g.flights[t]={},a.forEach(a=>{g.index[t].add(a.flightId,d(a)),g.flights[t][a.flightId]=a})},d=e.pipe(e.juxt(e.map(e.path,[["flightNumber"],["airline","iata"],["airline","name"],["arrivalAirport","iata"],["arrivalAirport","city"],["departureAirport","iata"],["departureAirport","city"]])),e.filter(e.identity),e.join(" ")),f=async()=>{if(null===g.gates){const t=await l.bus.get("poi/getByCategoryId",{categoryId:"gate"}),a=({name:t})=>e.tail(t.replace(",","").split(" ")),r=e.reduce((t,r)=>{const i=a(r);return[...t,...e.map(t=>[t,r],i)]},[],Object.values(t));g.gates=e.fromPairs(r)}return g},h=async()=>{await f();const t=await l.bus.get("venueData/getVenueData"),a=new URLSearchParams,i=l.i18n?.().language;if(i&&a.append("locale",i),p?.timeRange){const t=Date.now(),e=new Date(t-p.timeRange.beforeNowMs).toISOString(),r=new Date(t+p.timeRange.afterNowMs).toISOString();a.append("startDate",e),a.append("endDate",r)}const n=`https://marketplace.locuslabs.com/venueId/${t.baseVenueId}/flight-status`,o=a.toString()?`${n}?${a.toString()}`:n;try{const t=await fetch(o),a=await t.json();[r.ARRIVAL,r.DEPARTURE].forEach(t=>{const i=t===r.DEPARTURE?"departures":"arrivals",{airports:n,airlines:o}=a.data[i].appendix;c(t,((t,a,i,n)=>{const o=a.reduce((t,a)=>({...t,[a.iata]:a}),{}),s=i.flatMap(t=>[{code:t.iata,airline:t},{code:t.icao,airline:t}]).filter(({code:t})=>t).reduce((t,{code:a,airline:e})=>({...t,[a]:e}),{});return t.map(t=>{const a=n===r.DEPARTURE?e.pathOr("",["airportResources","departureGate"],t):e.pathOr("",["airportResources","arrivalGate"],t),i=g.gates[a];return{...t,flightType:n,gatePoi:i,airline:s[t.carrierFsCode],departureAirport:o[t.departureAirportFsCode],arrivalAirport:o[t.arrivalAirportFsCode]}})})(a.data[i].flightStatuses,n,o,t))}),g.apiError=!1}catch(t){g.apiError=!0,console.error("Error from flight status api call",t),[r.ARRIVAL,r.DEPARTURE].forEach(t=>{c(t,[])})}finally{g.lastUpdated=Date.now()}return g},m=async()=>{Date.now()-g.lastUpdated>6e4&&await h()};return l.bus.on("flightStatus/query",async({term:t=null,type:a=r.DEPARTURE}={})=>(await m(),s(t,a,g))),l.bus.on("flightStatus/getFlight",async({flightId:t})=>{await m();return g.flights.dep[t]||g.flights.arr[t]}),l.bus.on("flightStatus/mapFlightDetails",async({flight:t})=>i(a.local(),t,l.gt(),g.tz,l.i18n().language)),l.bus.on("flightStatus/mapFlightListItems",async({flights:t})=>t.map(t=>n(a.local(),t,l.gt(),g.tz,l.i18n().language)).sort(o)),{init:async()=>{g.tz=await l.bus.get("venueData/getVenueTimezone")},internal:{updateFlights:h,indexGatePois:f}}}export{l as create};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{FlightType as t}from"./flightDetailsMapper.js";const r=(e,a,l)=>{const{index:p,flights:s,apiError:i}=l,o=a===t.ALL?[t.DEPARTURE,t.ARRIVAL]:[a];let f;if(f=e?o.flatMap(t=>p[t].search({query:e}).map(r=>s[t][r])):o.flatMap(t=>Object.values(s[t])),0===f.length&&/^\w\w\d{2,4}$/.test(e)){const t=e.replace(/(\w\w)(\d{2,4})/,"$1_$2");return r(t,a,l)}return{flights:f,apiError:i}};export{r as searchFlights};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"ramda";import{locationToEndpoint as t,getStructures as n}from"../../../src/utils/location.js";const i=[{command:"destroy"},{command:"getDirections",args:[{name:"from",type:"location"},{name:"to",type:"location"},{name:"accessible",type:"boolean",optional:!0},{name:"queueTypes",type:"list",itemType:{type:"string"},optional:!0}]},{command:"getDirectionsMultiple",args:[{name:"locations",type:"list",itemType:{type:"location"}},{name:"accessible",type:"boolean",optional:!0},{name:"queueTypes",type:"list",itemType:{type:"string"},optional:!0}]},{command:"getPOIDetails",args:[{name:"poiId",type:"integer",min:0}]},{command:"getAllPOIs"},{command:"getStructures"},{command:"getVenueData"},{command:"getSecurityWaitTimes",args:[{name:"isOpen",type:"boolean",optional:!0}]},{command:"search",args:[{name:"term",type:"string",minLength:2},{name:"details",type:"boolean",optional:!0}]}];function s(i){i.bus.on("clientAPI/destroy",async()=>i.destroy()),i.bus.on("clientAPI/getDirections",async({from:n,to:s,accessible:a,queueTypes:o})=>{const c=await t(i,n),r=await t(i,s),m={requiresAccessibility:!!a};return o&&(m.selectedSecurityLanes={SecurityLane:o}),i.bus.get("wayfinder/getRoute",{fromEndpoint:c,toEndpoint:r,options:m}).then(e.pick(["distance","time","steps","navline","waypoints"]))}),i.bus.on("clientAPI/getDirectionsMultiple",async({locations:n,accessible:s,queueTypes:a})=>{const o=await Promise.all(n.map(async e=>t(i,e))),c={requiresAccessibility:!!s};a&&(c.selectedSecurityLanes={SecurityLane:a});const r=await Promise.all(e.aperture(2,o).map(async e=>i.bus.get("wayfinder/getRoute",{fromEndpoint:e[0],toEndpoint:e[1],options:c}))),m=e.map(e.pick(["distance","time","steps","navline","waypoints"]),r);return{total:{distance:e.sum(e.map(e=>e.distance,m)),time:e.sum(e.map(e=>e.time,m))},directions:m}}),i.bus.on("clientAPI/getPOIDetails",async({poiId:e})=>i.bus.get("poi/getById",{id:e})),i.bus.on("clientAPI/getAllPOIs",async()=>i.bus.get("poi/getAll")),i.bus.on("clientAPI/getStructures",()=>n(i)),i.bus.on("clientAPI/getSecurityWaitTimes",async({isOpen:e})=>i.bus.get("dynamicPois/getSecurityWaitTimes",{isOpen:e}));const s=e=>"function"!=typeof e;i.bus.on("clientAPI/getVenueData",async()=>{const t=await i.bus.get("venueData/getVenueData");return e.filter(s,t)}),i.bus.on("clientAPI/search",async({term:e,details:t})=>i.bus.get("search/queryAsync",{term:e}).then(n=>{const s=n.map(e=>e.poiId);return i.bus.send("event/search",{referrer:"prog",searchMethod:null,query:e,entities:s}),t?n:s}))}export{s as handleHeadless,i as headlessCommands};
|
|
1
|
+
import*as e from"ramda";import{locationToEndpoint as t,getStructures as n}from"../../../src/utils/location.js";const i=[{command:"destroy"},{command:"getDirections",args:[{name:"from",type:"location"},{name:"to",type:"location"},{name:"accessible",type:"boolean",optional:!0},{name:"queueTypes",type:"list",itemType:{type:"string"},optional:!0}]},{command:"getDirectionsMultiple",args:[{name:"locations",type:"list",itemType:{type:"location"}},{name:"accessible",type:"boolean",optional:!0},{name:"queueTypes",type:"list",itemType:{type:"string"},optional:!0}]},{command:"getPOIDetails",args:[{name:"poiId",type:"integer",min:0}]},{command:"getAllPOIs"},{command:"getStructures"},{command:"getVenueData"},{command:"getSecurityWaitTimes",args:[{name:"isOpen",type:"boolean",optional:!0}]},{command:"search",args:[{name:"term",type:"string",minLength:2},{name:"details",type:"boolean",optional:!0}]},{command:"getFlightStatus",args:[{name:"term",type:"string",optional:!0},{name:"type",type:"string",optional:!0}]}];function s(i){i.bus.on("clientAPI/destroy",async()=>i.destroy()),i.bus.on("clientAPI/getDirections",async({from:n,to:s,accessible:a,queueTypes:o})=>{const c=await t(i,n),r=await t(i,s),m={requiresAccessibility:!!a};return o&&(m.selectedSecurityLanes={SecurityLane:o}),i.bus.get("wayfinder/getRoute",{fromEndpoint:c,toEndpoint:r,options:m}).then(e.pick(["distance","time","steps","navline","waypoints"]))}),i.bus.on("clientAPI/getDirectionsMultiple",async({locations:n,accessible:s,queueTypes:a})=>{const o=await Promise.all(n.map(async e=>t(i,e))),c={requiresAccessibility:!!s};a&&(c.selectedSecurityLanes={SecurityLane:a});const r=await Promise.all(e.aperture(2,o).map(async e=>i.bus.get("wayfinder/getRoute",{fromEndpoint:e[0],toEndpoint:e[1],options:c}))),m=e.map(e.pick(["distance","time","steps","navline","waypoints"]),r);return{total:{distance:e.sum(e.map(e=>e.distance,m)),time:e.sum(e.map(e=>e.time,m))},directions:m}}),i.bus.on("clientAPI/getPOIDetails",async({poiId:e})=>i.bus.get("poi/getById",{id:e})),i.bus.on("clientAPI/getAllPOIs",async()=>i.bus.get("poi/getAll")),i.bus.on("clientAPI/getStructures",()=>n(i)),i.bus.on("clientAPI/getSecurityWaitTimes",async({isOpen:e})=>i.bus.get("dynamicPois/getSecurityWaitTimes",{isOpen:e}));const s=e=>"function"!=typeof e;i.bus.on("clientAPI/getVenueData",async()=>{const t=await i.bus.get("venueData/getVenueData");return e.filter(s,t)}),i.bus.on("clientAPI/search",async({term:e,details:t})=>i.bus.get("search/queryAsync",{term:e}).then(n=>{const s=n.map(e=>e.poiId);return i.bus.send("event/search",{referrer:"prog",searchMethod:null,query:e,entities:s}),t?n:s})),i.bus.on("clientAPI/getFlightStatus",async({term:e,type:t="all"})=>i.bus.get("flightStatus/query",{term:e,type:t}))}export{s as handleHeadless,i as headlessCommands};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var a="SDK headless",e={monitoring:{applicationInsights:{}},analytics2:{productName:"LocusMaps JS SDK",active:!1,disableSending:!1},clientAPI:{},dynamicPois:{},poiDataManager:{},sdkServer:{},searchService:{},venueDataLoader:{assetStage:"prod",formatVersion:"v5",availableLanguages:[{langCode:"en",assetSuffix:""}]},wayfinder:{compareFindPaths:!1}},i={name:a,plugins:e};export{i as default,a as name,e as plugins};
|
|
1
|
+
var a="SDK headless",e={monitoring:{applicationInsights:{}},analytics2:{productName:"LocusMaps JS SDK",active:!1,disableSending:!1},clientAPI:{},dynamicPois:{},flightStatus:{},poiDataManager:{},sdkServer:{},searchService:{},venueDataLoader:{assetStage:"prod",formatVersion:"v5",availableLanguages:[{langCode:"en",assetSuffix:""}]},wayfinder:{compareFindPaths:!1}},i={name:a,plugins:e};export{i as default,a as name,e as plugins};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DateTime as e}from"luxon";const o=(o,t="en")=>(o instanceof Date&&(o=e(o)),"is"===t&&(t="ca"),o.setLocale(t).toLocaleString(e.TIME_SIMPLE)),t=e=>Math.ceil(e/60/1e3);export{o as formatTime,t as msToMin};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E={ON_TIME:1,EARLY:2,DELAYED:3,CANCELLED:4,ARRIVED:5,DEPARTED:6,UNKNOWN:7};export{E as FlightLabelStatus};
|
package/package.json
CHANGED