Convert DateTimeType to a more user-friendly string

Hello @Olymp
I’ll do my best to extrapolate the modal code as you asked, but keep in mind there are several files involved and it is difficult to extrapolate all the code and css rules needed. Let me explain a bit how it is all set up, this may help you understand the code/find the right snippets. I’m not a programmer, I know html & css and a bit of js, but am a UI Designer myself, so I had to find a way to implement my design at my best, using and modifying pieces of code I found around here, with a lot of trial and error - the code is pretty messy. My design started with the intention to slightly modify the fantastic Matrix Theme for HABPanel - but I ended up basically rewriting everything from scratch, it was easier than modifying something that was more complicated than what I needed.
In HABPanel I customized pretty heavily the additional css. The sizes of many elements are given in px, my main focus was to make it look nice on a specific tablet, not to go with a full responsive approach. I had started using SVGs but endend up converting everything to minified PNGs because my tablet was suffering and lagging with all those SVGs.

My HABPanel theme is managed with a single big widget, the “tabs” (lights, rollershutters, temperatures management, power management, and system) are all inside a slider so you can tap the single icons on the top right of the interface or just swype left/right over the house map to cycle between the tabs. This is done with an Angular carousel. When you click one of the red circles inside the temperatures tab, they open a modal.

This is the code:

<div class="bolloTemperatura TempSala" ng-click="openModal('modalSala.html', true, 'lg')">
...
</div>

then you have the code for the modal itself:

 <style> 
 	.modal .modal-dialog.modal-lg {
 		width: 800px;
 		height: 555px;
 		padding: 0;
 	}
 	.modal .modal-content {
 		width: 800px;
 		height: 555px;
 		padding: 0;
 		background-color: #161719;
 		color: #FFF;
 	}
 	.modal .modal-dialog {
 		margin-bottom: 0px !important;
 	}
 	.modal h3 {
 		font-size: 37px;
 		line-height: 37px;
 		text-transform: uppercase;
 		margin: 16px 0 0 25px;
 		font-family: 'Montserrat_T';
 	}
 	.modal .updated {
 		font-size: 12px;
 		line-height: 12px;
 		color: #777777;
 		text-transform: uppercase;
 		margin: 38px 0 0 15px;
 		font-family: 'Montserrat_M';
 	}
 	.modal a.modalCloseBtn {
 		display:block;
 		position: relative;
 		width: 19px;
 		height: 19px;
 		float: right;
 		background-image: url(/static/ALB-matrix-reloaded-theme/png/icons/close_19x19@2x-min.png);
 		background-size: contain;
 		background-color: transparent;
 		background-repeat: no-repeat;
 		border: 0;
 		padding: 0;
 		margin: 25px 25px 0 0;
 	}
 	.modal .modalDetails {
 		padding: 15px 0 0 25px;
 		overflow: hidden;
 		position: absolute;
 		top: 55px;
 	}
 	.modal .modalDetails .modalDetailsIcon {
 		width: 24px;
 		height: 50px;
 		clear: both;
 		display: block;
 	}
 	.modal .modalDetails .temp{
 		font-size: 40px;
 		line-height: 40px;
 		margin: 5px 0 0 11px;
 		color: #FFF;
 		min-width: 120px;
 	}
 	.modal .modalDetails .temp sup.deg {
 		top: -17px;
 		font-size: 16px;
 		line-height: 16px;
 		color: #999;
 	}
 	.modal .humLevel .hum {
 		margin-bottom: 9px;
 	}
 	.modal .humLevel img {
 		display: block;
 		float: left;
 	}
 	.modal .humLevel span {
 		display: block;
 		float: left;
 		margin: 2px 0 0 5px;
 	}
 	.modal .periodi{
 		overflow: hidden;
 		margin: 4px 25px 0 0;
 		/* clear: right; */
 		float: right;
 		padding: 0;
 	}
 	.modal a.periodo {
 		display: block;
 		float: left;
 		margin: 10px 0 0 -1px;
 		border: 1px solid #FFF;
 		color: #FFF;
 		padding: 5px 7px;
 	}
 	.modal a.periodo:first-child {
 		margin-left: 0;
 	}
 	.modal a.periodo.active {
 		background-color: #FF6363;
 		color: #FFF;
 				border: 1px solid #FF6363;
 	}
 	.patchTitoloGrafico {
 		position: absolute;
 		width: 100%;
 		height: 30px;
 		margin-top: 75px;
 		z-index: 99;
 		background-color: #161719;
 	} 
 	.modalGraphContainer{
 		min-width: 116px;
 		min-height: 116px;
 		background-image: url(/static/ALB-matrix-reloaded-theme/gif/loader.gif);
 		background-color: transparent;
 		background-repeat: no-repeat;
 		background-position: 360px 210px;
 		background-size: 10%;
 	}
 </style>

<!-- ---------- iFrame SALA ---------- -->
<script type="text/ng-template" id="modalSala.html">
	<div class="modalContainer">
		<div class="modalHeader overflowHidden">
			<h3 class="red floatLeft">Sala</h3>
			<div class="updated floatLeft">Ultimo aggiornamento: {{getItem('HTP_Sala_LastUpdate').transformedState}}</div>
			<a ng-click="$close()" class="modalCloseBtn floatRight"></a>
		</div>
		
		<div class="patchTitoloGrafico"></div>
		<div class="modalGraphContainer">
			<iframe id="iframeSala" class="grafanaIframe" src="/static/ALB-matrix-reloaded-theme/iframeSala.html" width="798px" height="490px" frameborder="0" style="margin-top: 10px;"></iframe>
		</div>
	</div>

	<div class="modalDetails">
		<img class="modalDetailsIcon floatLeft" src="/static/ALB-matrix-reloaded-theme/png/controls/termometro@2x-min.png" />
		<div class="temp floatLeft">{{(getItem('HTP_Sala_Temperature').state.replace(" °C", "") | number : 1).replace(",", ".")}}<sup class="deg">&deg;C</sup></div>
		<div class="humLevel floatLeft">	
			<div class="hum overflowHidden"><img class="icon_20x20" src="/static/ALB-matrix-reloaded-theme/png/icons/humidity_20x20@2x-min.png" /><span>    UMIDIT&Agrave;&nbsp;{{getItem('HTP_Sala_Humidity').state.replace(" %", "") | number : 0}}%</span></div>
			<!-- 0-30=DRY // 30-50=COMFORT // 50-100=WET -->
			<div class="level overflowHidden" ng-if="getItem('HTP_Sala_Humidity').state.replace(' %', '') <= 30"><img class="icon_20x20" src="/static/ALB-matrix-reloaded-theme/png/icons/    dry_20x20@2x-min.png" /><span>DRY</span></div>
			<div class="level overflowHidden" ng-if="getItem('HTP_Sala_Humidity').state.replace(' %', '') > 30 && getItem('HTP_Sala_Humidity').state.replace(' %', '') < 55"><img class="icon_20x20"     src="/static/ALB-matrix-reloaded-theme/png/icons/comfort_20x20@2x-min.png" /><span>COMFORT</span></div>
			<div class="level overflowHidden" ng-if="getItem('HTP_Sala_Humidity').state.replace(' %', '') >= 55"><img class="icon_20x20" src="/static/ALB-matrix-reloaded-theme/png/icons/    wet_20x20@2x-min.png" /><span>WET</span></div>
		</div>
	</div>
</script>

Inside the modal, there is an iFrame (iframeSala.html) which is a simple html page:

<!-- UPDATED: 2020-05-19 -->

<!DOCTYPE html>
<html>
<head>
	<script src="http://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
	<meta http-equiv="Content-type" CONTENT="text/html; charset=utf-8">
	<style>
		html, body {
			background-color: #161719;
		}
		.container iframe {
			width: 100%;
			height: 400px;
		}
		.container {
			width: 98%;
			margin: 0 auto;
			border: 0;
		}
		
		div.periodi{
			overflow: hidden;
			margin: 4px 25px 0 0;
			/* clear: right; */
			float: right;
			padding: 0;
		}
		a.periodo {
			float: left;
			margin: 10px 0 0 -1px;
			border: 1px solid #555;
			color: #FFF;
			padding: 10px 9px;
			text-decoration: none;
			font-family: arial;
			font-size: 13px;
			line-height: 13px;
		}
		a.periodo:first-child {
			margin-left: 0;
		}
		a.periodo.active {
			background-color: #FF6363;
			color: #FFF;
			border: 1px solid #FF6363;
			position: relative;
			z-index: 999;
		}
	</style>

</head>

<body>
	<div class="periodi">
		<a class="periodo periodo1"        href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-3h&to=now"  target="iframeSala">3 ORE</a>
		<a class="periodo periodo2"        href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-6h&to=now"  target="iframeSala">6 ORE</a>
		<a class="periodo periodo3 active" href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-12h&to=now" target="iframeSala">12 ORE</a>
		<a class="periodo periodo4"        href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-24h&to=now" target="iframeSala">24 ORE</a>
		<a class="periodo periodo5"        href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-2d&to=now"  target="iframeSala">2 GIORNI</a>
		<a class="periodo periodo6"        href="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-7d&to=now"  target="iframeSala">1 SETTIMANA</a>
	</div>
	<div class="modalGraphContainer">
		<iframe id="iframeSala" name="iframeSala" class="grafanaIframe" src="http://192.168.2.150:3000/d-solo/mROk6Xigz/temperature?panelId=2&orgId=1&from=now-12h&to=now" width="790px" height="    410px" frameborder="0" style="margin-top: 10px;"></iframe>
	</div>

</body>


<script type="text/javascript"> 
	$(document).ready(function(){
		$("a.periodo").click(function(){
			$(this).parent().children().removeClass("active");
			$(this).addClass("active");
		});
	});
</script>

</html>

As you can see some css rules right now are next to the code. Not the best solution, I know, but easier to test quickly (all this temperatures tab is still WIP) before moving them to the main css file.
On the main css file there are other rules impacting the final layout, and it’s quite complicated to extrapolate each single rule that may be needed in your environment. It would also probably break your layout. So be aware that these code snippets won’t work out of the box, you will have to tweak heavily the code, or I suggest you take them just as a track to point you in the right direction to write your own widget, probably with a much cleaner code! :grin:

I hope it can help you somehow. Pardon the messy code, as I said I did my best. For sure everything could be done in a much cleaner, easier way. In my case I chose to go for a ugly code that works, instead of scratching my head on sophisticated code that I am not able to manage.

1 Like