[AngularJs] Une maquette d’application Weathermap, en 3 heures de temps.

Introduction

logo


On m’a demandé de faire l’app suivante :

Using the OpenWeatherMap API (http://www.openweathermap.com/current), build a Weather
Dashboard webApp using AngularJS.
The App should have two pages :
● The “Home” page, displaying the list of the user’s weather widgets.
○ Each widget displays the name of the city, the current temperature in celsius and
an icon of the weather (http://erikflowers.github.io/weather-icons/)
● The “Settings” page, used to edit the content of the “Home” page.
○ The user can Add, Remove weather widgets.
You are free to increase the features and create the design.

Technologies utilisées :


  • AngularJs 1.5.1
  • Bootstrap 3.0
  • AngularUi
  • Openweather Map Api pour AngularJs

Résultat, après 3 heures de temps:

Tester ici : http://nicolash.org/weatherdashboard/#/accueil

Le code

Explication sommaire du code : on « donne à manger  » à l’api WeatherMAP dans la fonction create_city_weather(), qui injecte les nouveaux widgets ainsi créés dans $scope.meteos ! Les widgets sont contenus dans la FACTORY , qui est manipulée par l’utilisateur dans la vue « compte ». Les noms des modèles de données mériteraient une normalisation UML (En fait, je dois changer « villes » par « widgets » dans tout le code !!), néanmoins, cela fonctionne déjà comme cela ! Pas de directive, c’est fait à la bourrin mais ça marche super ! Je me le garde sous la main pour le structurer plus tard …

On a index.html qui charge les librairies, affiche les menus, et affiche les vues dans la balise ng-view:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Neutre</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
		
		<!-- CHARGEMENT DES LIBRAIRIES -->
		
		<!-- JQUERY ET BOOTSRAP -->
        <script src="bower_components/jquery/dist/jquery.min.js"></script>
        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
		<link rel="stylesheet" type="text/css" href="bower_components/bootstrap/dist/css/bootstrap.css">
		<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css" type="text/css">
 
        <!-- ANGULARJS -->
	         <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular-animate.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular-aria.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.5.1/angular-sanitize.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular-messages.min.js"></script>
		<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular-route.min.js'></script>
		
		<!-- ANGULARUI -->
		 <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
		
		<!-- API WEATHERMAP  -->
		<script src="bower_components/angular-openweathermap-api-factory/dist/angular-openweathermap-api-factory.min.js"></script>
		
		<!-- APPLICATION PERSO -->
		<script src="js/app.js"></script>
		<link rel="stylesheet" type="text/css" href="css/style.css">
		<link rel="stylesheet" type="text/css" href="css/simple-sidebar.css">
		
		<!-- FIN DE CHARGEMENT DES LIBRAIRIES -->
  </head>

	<body ng-app="neutre" >

	<div id="throbber" style="display:none; min-height:120px;"></div>
	<div id="noty-holder"></div>

		<!-- Navigation -->
		<nav class="navbar navbar-inverse navbar-fixed-top" >
		
			<ul class="nav  top-nav">
				<li >
					<a href="#" data-placement="bottom" data-toggle="tooltip" id="menu-toggle" data-placement="bottom" data-toggle="tooltip" href="#" data-original-title="MENU"><i class="glyphicon glyphicon-th-list"></i></a>
				</li> 
				<li><a href="#/compte" data-placement="up" data-toggle="tooltip" href="#" data-original-title="Stats"><i class="fa fa-bar-chart-o"></i>
					</a>
				</li>            
				<li class="dropdown pull-right">
					<a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin User <b class="fa fa-angle-down"></b></a>
					<ul class="dropdown-menu">
						<li><a href="#"><i class="fa fa-fw fa-user"></i> Edit Profile</a></li>
						<li><a href="#"><i class="fa fa-fw fa-cog"></i> Change Password</a></li>
						<li class="divider"></li>
						<li><a href="#"><i class="fa fa-fw fa-power-off"></i> Logout</a></li>
					</ul>
				</li>
			</ul>
			
		</nav>

		 <div id="wrapper">
			<!-- Sidebar -->
			<div id="sidebar-wrapper">
				<ul class="sidebar-nav">
					<li class="sidebar-brand">
						WeatherMap
					</li>
					<li class="sidebar-brand">
						<a class="navbar-brand" ><img src="img/logo.jpg"  alt="LOGO"></a>
					</li>
					<li>
						<a href="#/accueil">accueil</a>
					</li>
					<li>
						<a href="#/compte">compte</a>
					</li>
				</ul>
			</div>
			<!-- /#sidebar-wrapper -->
		
		<!-- LES VUES VONT APPARAITRE ICI -->
		<div ng-view></div>
		  
		
	</body>
</html>
    
<!-- Menu Toggle Script obligatoire pour slider la barre des tâches de côté-->
    <script>
    $("#menu-toggle").click(function(e) {
        e.preventDefault();
        $("#wrapper").toggleClass("toggled");
    });
    </script>

Ensuite, on a le fichier app.js, qui contient

    L’appel aux modules,
    Le routing de vues
    Les 2 controleurs
    La factory des villes NOTE : IL FAUDRA LA RENOMMER EN WIDGETFACTORY POUR QUE CE SOIT PLUS LOGIQUE
var monApp = angular.module('neutre',['ngRoute','jtt_openweathermap'])
  
monApp.config(function ($routeProvider, $locationProvider){
	$routeProvider
	.when('/accueil', {
		templateUrl: 'accueil.html',
		controller: 'accueilCtrl'
	})
	.when('/compte', {
		templateUrl: 'compte.html',
		controller: 'compteCtrl'
	})
	.otherwise({redirectTo: '/accueil'}); 
})

monApp.controller('accueilCtrl', function($scope,openweathermapFactory,villesFactory) {
	
	/* INIT DES VARIABLES*/
	$scope.meteos =[]; // VA CONTENIR LES METEOS QUI PROVIENNENT DE WEATHERMAP
	villes  = villesFactory.get_villes();

	/* GENERAL */
	function create_city_weather(city,country){
		var k = city+','+country;
		console.log(k);
		openweathermapFactory.getWeatherFromCitySearchByName({
		q:k, //city name and country code divided by comma, use ISO 3166 country codes eg "London,uk"
		lang:"fr", // (optional) http://openweathermap.org/current#multi
		units:"metric", // (optinal) http://openweathermap.org/current#data
		type:"<TYPE>", // (optional) 'like' = close result, 'accurate' = accurate result
		appid:"fb35d246e1d1bc10296b6dbbff4ff92e"
	}).then(function(_data){
		//on success
		console.log(_data);
		$scope.meteos.push(_data);
	}).catch(function (_data) {
		//on error
	});
		
	}

	var x = 0;
	for(x<0;x<villes.length;x++){
		create_city_weather(villes[x].nom,villes[x].pays);	
	};

	/* POUR BIEN AFFICHER LE FORMAT DE DATE  PROVENANT D UN UNIX TIMESTAMP */
	$scope.timeConverter = function(UNIX_timestamp){
		  var a = new Date(UNIX_timestamp * 1000);
		  var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
		  var year = a.getFullYear();
		  var month = months[a.getMonth()];
		  var date = a.getDate();
		  var hour = a.getHours();
		  var min = a.getMinutes();
		  var sec = a.getSeconds();
		  var time =  hour + ':' + min + ':' + sec ;
		  return time;
	}

/* FIN DU CONTROLEUR */
})


monApp.controller('compteCtrl', function($scope,villesFactory) {
	
	$scope.villes_gestion = villesFactory.get_villes();
 
	$scope.changerPays = function(pays){
		switch (pays) {
			case "fr":
				$scope.villes = [
					{"nom":"Paris"},
					{"nom":"Toulouse"},
					{"nom":"Nantes"},
					{"nom":"Marseille"},
					{"nom":"Cannes"},
					{"nom":"Biarritz"}
				]
				break;
			case "us":
				$scope.villes = [
					{"nom":"detroit"},
					{"nom":"losangeles"},
					{"nom":"sacramento"},
					{"nom":"Denver"},
					{"nom":"Houston"},
					{"nom":"atlanta"},
					{"nom":"Washington"}
				]
				break;
			case "uk":
				$scope.villes = [
					{"nom":"london"},
					{"nom":"glasgow"},
					{"nom":"manchester"},
					{"nom":"cardiff"},
					{"nom":"inverness"},
					
				]
				break;
		}
	}
	
	$scope.ajouter_ville = function(){
		villesFactory.insert_ville({"nom":$scope.ville,"pays":$scope.pays});
	}

	$scope.supprimer_ville = function(ville){
		villesFactory.supprimer_ville(ville);
	}

/* FIN DU CONTROLEUR */
})


/* LA FACTORY QUI CONTIENT LES WIDGETS IL FAUDRA LA RENOMMER WIDGETFACTORY POUR QUE CE SOIT PLUS LOGIQUE, JAVAIS NOMME CA DANS L URGENCE*/
monApp.factory('villesFactory',function($http){
 
   var factory = [
		{"nom":"londres","pays":"uk"},
		{"nom":"paris","pays":"fr"}
		];
 
   factory.get_villes = function(){
        return factory
    }
	
	factory.insert_ville = function(ville){
      factory.push(ville);
    }
	
	factory.supprimer_ville = function(ville){
		var index = factory.indexOf(ville);
		factory.splice(index, 1);     
	}
	return factory
})
  

Voilà, ensuite, on a les 2 vues accueil.html qui présentent la météo des villes, et compte.html, qui permet de gérer les villes à afficher :

accueil.html :

    <!-- Page Content -->
<div id="page-content-wrapper">
	<div class="content">
		<div class="row  " >
			<div class="col-md-3" ng-repeat="x in meteos">
				<div class="panel panel-default "  >

					<div class="panel-heading"><h4>
						<img ng-src="img/nuageux.jpg"  ng-if="x.data.weather[0].description=='partiellement ensoleillé'"/>
						<img ng-src="img/sunny.jpg"  ng-if="x.data.weather[0].description=='ciel dégagé'"/>
						<img ng-src="img/nuageux.jpg"  ng-if="x.data.weather[0].description=='peu nuageux'"/>
						<img ng-src="img/openweathermap.jpg"  ng-if="x.data.weather[0].description!=='peu nuageux' && x.data.weather[0].description!=='partiellement ensoleillé' && x.data.weather[0].description!=='ciel dégagé'"/>
						{{x.data.name}} </h4>
					</div>
					
					
					<div class="panel-body panel-body-overflow">
						<div  > CIEL :  {{x.data.weather[0].description}}</div>
						<div  > TEMPERATURE : {{x.data.main.temp}} °</div>
						<div  > VENT : {{x.data.wind.speed}} noeuds</div>
						<div  > HUMIDITE : {{x.data.main.humidity}} % </div>
						<div  > LEVE DU SOLEIL:  {{timeConverter(x.data.sys.sunrise)}} heures</DIV>
						<div  > COUCHE DU SOLEIL:  {{timeConverter(x.data.sys.sunset)}} heures</DIV>
						<div  > COORDONNEES  {{x.data.coord}} </DIV>
					</div>

					<div class="panel-footer text-right"> </div>
				</div>
			</div>
		</div>

et la vue compte.html :


    <!-- Page Content -->
<div id="page-content-wrapper">
    <div class="content">
    <div class="container-fluid">

			
		<div class="row padded " >
		    
	

			<div class="col-md-6">
				<div class="panel panel-default anchor" id="anchor2" name="anchor2">

					<div class="panel-heading"><h4><i class="fa fa-calendar" aria-hidden="true"></i> Ajouter un  Widget </h4></div>

					<div class="panel-body panel-body-overflow">
						
						<div class="col-md-6">
							<div class="form-group">
							<label >Pays</label>
								<select class="form-control" ng-model="pays" ng-change="changerPays(pays)">
								  <option value="fr">France</option>
								  <option value="uk">Uk</option>
								  <option value="us">Usa</option>
								</select> 
							</div> 
						</div>
						<div class="col-md-6">
							<div class="form-group">
							<label >Villes</label>
								<select class="form-control" ng-model="ville" ng-disabled="!villes" >
								  <option ng-repeat="v in villes" ng-value="v.nom">{{v.nom}}</option>
								</select> 
							</div> 
						</div>
					
					</div>

					<div class="panel-footer text-right"> 
						<button class="btn btn-success " ng-disabled="pays==null||ville==null"  ng-click="ajouter_ville()"> 
						<span class="glyphicon glyphicon-ok"></span> Valider</button> </form>
						</button>
					</div>

				</div>
			</div>
		  
			<div class="col-md-6">
				<div class="panel panel-default anchor" id="anchor2" name="anchor2">

					<div class="panel-heading"><h4><i class="fa fa-calendar" aria-hidden="true"></i> Gérer les widgets </h4></div>

					<div class="panel-body panel-body-overflow">
					 <table style="width:100%">
						  <tr ng-repeat="v in villes_gestion">
							<th>{{v.nom}}</th>
							<th>{{v.pays}}</th>
							<th><button class="btn btn-danger" ng-click="supprimer_ville(v)">Supprimer</button></th>
						  </tr>
						  <tr>

						</table> 
					
					</div>

					

				</div>
			</div>
		  
Publicités