FINALL JAVASCRIPT
unknown
javascript
a year ago
12 kB
8
Indexable
import Alpine from 'alpinejs';
window.Alpine = Alpine;
window.layoutData = ({
apiBaseUrl,
deviceId,
refreshRate,
displayType,
backgroundColor = null,
primaryColor = null,
secondaryColor = null,
lines = null,
displayMessageOnError = null,
departuresInterval = null,
adInterval = null,
adsPath = null,
}) => {
return {
scheduleTickNr: 0,
adsTickNr: 0,
lastSuccessfulAPIFetch: '',
heapSize: '',
loadsInProgress: 0,
hasErrors: false,
firstDataGet: false,
adsLayerVisible: false,
currentAd: -1,
scheduleData: [],
appSettings: {
apiBaseUrl,
deviceId,
refreshRate,
displayType,
backgroundColor,
primaryColor,
secondaryColor,
lines,
displayMessageOnError,
departuresInterval,
adInterval,
adsPath,
},
ads: [
{
"id": 156,
"client_id": 1,
"name": "Testadvert 0",
"media": "adv/2020_YTP_DFI_1920x360.jpg",
"media_type": null,
"media_size": null,
"ad_interval": 3,
"visible_from": null,
"visible_to": null,
"visible_time_from": null,
"visible_time_to": null,
"created_at": "2024-06-12T19:56:51.000000Z",
"updated_at": "2024-06-12T19:56:51.000000Z",
"pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 1}
},
{
"id": 9,
"client_id": 1,
"name": "Testadvert 1",
"media": "adv/SA_DFI_1920x360.jpg",
"media_type": null,
"media_size": null,
"ad_interval": 3,
"visible_from": null,
"visible_to": null,
"visible_time_from": null,
"visible_time_to": null,
"created_at": "2024-06-12T19:56:51.000000Z",
"updated_at": "2024-06-12T19:56:51.000000Z",
"pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 2}
},
{
"id": 1878,
"client_id": 1,
"name": "Testadvert 2",
"media": "adv/TD_Vertrieb_VRR_TFTScreen_1920x1080px.jpg",
"media_type": null,
"media_size": null,
"ad_interval": 6,
"visible_from": null,
"visible_to": null,
"visible_time_from": null,
"visible_time_to": null,
"created_at": "2024-06-12T19:56:51.000000Z",
"updated_at": "2024-06-12T19:56:51.000000Z",
"pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 3}
},
{
"id": 33,
"client_id": 1,
"name": "Testadvert 3",
"media": "adv/YTP_DFI_1920x360.jpg",
"media_type": null,
"media_size": null,
"ad_interval": 7,
"visible_from": null,
"visible_to": null,
"visible_time_from": null,
"visible_time_to": null,
"created_at": "2024-06-12T19:56:51.000000Z",
"updated_at": "2024-06-12T19:56:51.000000Z",
"pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 4}
},
],
newAds: [] || false,
get availableAds() {
return this.ads.filter((ad) => this.isCurrentTimeBetween(ad.visible_time_from, ad.visible_time_to));
},
mounted() {
this.runApp();
},
isCurrentTimeBetween(startTime, endTime) {
if (!startTime || !endTime || startTime === '' || endTime === '') return true;
const currentTime = new Date();
const currentMs = currentTime.getHours() * 60 * 60 * 1000 +
currentTime.getMinutes() * 60 * 1000 +
currentTime.getSeconds() * 1000 +
currentTime.getMilliseconds();
const [startHours, startMinutes] = startTime.split(':').map(Number);
const [endHours, endMinutes] = endTime.split(':').map(Number);
const startMs = startHours * 60 * 60 * 1000 + startMinutes * 60 * 1000;
const endMs = endHours * 60 * 60 * 1000 + endMinutes * 60 * 1000;
if (startMs < endMs) {
return currentMs >= startMs && currentMs <= endMs;
} else {
return currentMs >= startMs || currentMs <= endMs;
}
},
getTranportIcon(transportClass) {
switch (transportClass) {
case 'BUS':
case 'CITY_BUS':
case 'EXPRESS_BUS':
case 'REGIONAL_BUS':
case 'CALL_BUS':
case 'CITIZEN_BUS':
return 'busLogo.svg';
case 'TRAM':
case 'UNDERGROUND':
return 'tramLogo.svg';
case 'REGIONAL_TRAIN':
case 'NATIONAL_TRAIN':
case 'INTERNATIONAL_TRAIN':
return 'trainLogo.svg';
case 'SUBURBAN_TRAIN':
return 'sLogo.svg';
default:
return null;
}
},
getTimeGerman(date) {
return date.toLocaleDateString('de-DE', {hour: 'numeric', minute: 'numeric'}).split(',')[1];
},
parseResponse(response) {
return response.map((entity) => {
const departureTime = new Date(entity.departure_planned);
const estimatedTime = entity.departure_estimated === null ? new Date(0) : new Date(entity.departure_estimated);
return {
platform: entity.platform,
departureTime,
estimatedTime,
departureString: this.getTimeGerman(departureTime),
estimatedString: this.getTimeGerman(estimatedTime),
destination: entity.destination_name,
transportTitle: entity.transport_name ? `${entity.transport_name} ${entity.transport_number}` : (entity.transport_full_name || null),
transportClass: entity.transport_class,
transportIcon: this.getTranportIcon(entity.transport_class),
hint: entity.hints || '',
delay: (estimatedTime > departureTime) ? (estimatedTime.getTime() - departureTime.getTime()) / (60 * 1000) : 0
};
}).sort((a, b) => a.departureTime.getTime() - b.departureTime.getTime());
},
async makeApiCall(api) {
this.loadsInProgress++;
const requestUrl = api === 'ads' ? `${this.appSettings.apiBaseUrl}${this.appSettings.deviceId}/ads` : `${this.appSettings.apiBaseUrl}${this.appSettings.deviceId}/departures?limit=${this.appSettings.lines}`;
return fetch(requestUrl, {
method: 'GET',
}).then((response) => {
if (response.headers.get("X-Force-Refresh") === "1") {
return window.location.reload();
}
return response.json();
}).then((data) => {
this.loadsInProgress--;
return data;
}).catch((error) => {
this.hasErrors = true;
this.loadsInProgress--;
throw new Error('API fetching error' + error);
});
},
async doAppTick() {
this.scheduleTickNr++;
const departuresData = await this.makeApiCall('departures');
if (departuresData !== null) {
try {
this.lastSuccessfulAPIFetch = (new Date()).toLocaleDateString('de-DE', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
this.firstDataGet = true;
this.scheduleData = this.parseResponse(departuresData);
} catch (error) {
this.hasErrors = true;
throw new Error('Error in departures API response: ' + error);
}
}
},
findNextAdIndex(ads) {
const nextAd = ads.findIndex(ad => ad.id === this.currentAd);
if (nextAd === -1) {
return 0;
}
return nextAd === (ads.length - 1) ? 0 : nextAd + 1;
},
async doAdsTick() {
this.adsTickNr++;
const adsData = await this.makeApiCall('ads');
if (adsData !== null) {
try {
this.ads = adsData;
} catch (error) {
this.hasErrors = true;
throw new Error('Error in ads API response: ' + error);
}
let defaultSpaceBetweenAds = this.appSettings.departuresInterval * 1000;
if (this.availableAds.length === 0) {
setTimeout(() => {
this.doAdsTick();
}, defaultSpaceBetweenAds);
return;
}
const nextAdIndex = this.findNextAdIndex(this.availableAds);
const currentAdVisibilityTime = () => {
return this.availableAds[nextAdIndex].ad_interval ? this.availableAds[nextAdIndex].ad_interval * 1000 : this.appSettings.adInterval * 1000;
}
this.currentAd = this.availableAds[nextAdIndex].id;
this.adsLayerVisible = true;
setTimeout(() => {
this.adsLayerVisible = false;
}, currentAdVisibilityTime());
setTimeout(() => {
this.doAdsTick();
}, currentAdVisibilityTime() + defaultSpaceBetweenAds);
}
},
runApp() {
try {
this.doAppTick();
setInterval(() => {
this.doAppTick();
}, this.appSettings.refreshRate * 1000);
setTimeout(() => {
this.doAdsTick();
}, this.appSettings.departuresInterval * 1000);
} catch (error) {
console.error('Error in runApp:', error);
}
},
}
}
Alpine.start();
Editor is loading...
Leave a Comment