Commit e31b22083f88e0386151e15de6e64f9d33fb3d51
1 parent
94ac51a7
Exists in
dev
Severals Changes on web and Config addition
Showing
18 changed files
with
495 additions
and
57 deletions
Show diff stats
src/common/admin.py
src/common/models.py
1 | -# This is an auto-generated Django model module. | |
2 | -# You'll have to do the following manually to clean this up: | |
3 | -# * Rearrange models' order | |
4 | -# * Make sure each model has one field with primary_key=True | |
5 | -# * Make sure each ForeignKey has `on_delete` set to the desired behavior. | |
6 | -# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table | |
7 | -# Feel free to rename the models, but don't rename db_table values or | |
8 | -# field names. | |
9 | 1 | from __future__ import unicode_literals |
10 | 2 | |
11 | 3 | from django.contrib.auth.models import AbstractUser |
... | ... | @@ -798,7 +790,7 @@ class WeatherWatch(models.Model): |
798 | 790 | |
799 | 791 | class WeatherWatchHistory(models.Model): |
800 | 792 | datetime = models.DateTimeField(blank=True, null=True, auto_now_add=True) |
801 | - humid_int = models.CharField(max_length=45, blank=True, null=True) | |
793 | + humid_int = models.FloatField(blank=True, null=True) | |
802 | 794 | humid_ext = models.CharField(max_length=45, blank=True, null=True) |
803 | 795 | wind = models.CharField(max_length=45, blank=True, null=True) |
804 | 796 | wind_dir = models.CharField(max_length=45, blank=True, null=True) |
... | ... | @@ -815,3 +807,27 @@ class WeatherWatchHistory(models.Model): |
815 | 807 | |
816 | 808 | def __str__(self): |
817 | 809 | return (str(self.datetime)) |
810 | + | |
811 | + | |
812 | +class Config(models.Model): | |
813 | + id = models.IntegerField(default='1', primary_key=True) | |
814 | + latitude = models.FloatField(default=1) | |
815 | + local_time_zone = models.FloatField(default=1) | |
816 | + longitude = models.FloatField(default=1) | |
817 | + altitude = models.FloatField(default=1) | |
818 | + horizon_line = models.FloatField(default=1) | |
819 | + row_data_save_frequency = models.IntegerField(default='300') | |
820 | + request_frequency = models.IntegerField(default='300') | |
821 | + analysed_data_save = models.IntegerField(default='300') | |
822 | + telescope_ip_address = models.CharField(max_length=45, default="127.0.0.1") | |
823 | + camera_ip_address = models.CharField(max_length=45, default="127.0.0.1") | |
824 | + plc_ip_address = models.CharField(max_length=45, default="127.0.0.1") | |
825 | + global_mode = models.BooleanField(default='True') | |
826 | + | |
827 | + class Meta: | |
828 | + managed = True | |
829 | + db_table = 'config' | |
830 | + verbose_name_plural = "Config" | |
831 | + | |
832 | + def __str__(self): | |
833 | + return (str(self.__dict__)) | |
818 | 834 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +from django import forms | |
2 | +from common.models import Config | |
3 | + | |
4 | +class ConfigForm(forms.ModelForm): | |
5 | + class Meta: | |
6 | + model = Config | |
7 | + fields = ('latitude', | |
8 | + 'local_time_zone', | |
9 | + 'longitude', | |
10 | + 'altitude', | |
11 | + 'horizon_line', | |
12 | + 'row_data_save_frequency', | |
13 | + 'request_frequency', | |
14 | + 'analysed_data_save', | |
15 | + 'telescope_ip_address', | |
16 | + 'camera_ip_address', | |
17 | + 'plc_ip_address',) | |
18 | + labels = { | |
19 | + 'latitude': ('Latitude :'), | |
20 | + 'local_time_zone': ('Local Time Zone :'), | |
21 | + 'longitude': ('Longitude :'), | |
22 | + 'altitude': ('Altitude :'), | |
23 | + 'horizon_line': ('Horizon Line :'), | |
24 | + 'row_data_save_frequency': ('Row Data Save Frequency :'), | |
25 | + 'request_frequency': ('Request Frequency :'), | |
26 | + 'analysed_data_save': ('Analysed Data Save :'), | |
27 | + 'telescope_ip_address': ('Ip Address :'), | |
28 | + 'camera_ip_address': ('Ip Address :'), | |
29 | + 'plc_ip_address': ('Ip Address :'), | |
30 | + } | |
0 | 31 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,63 @@ |
1 | +{% extends "base.html" %} | |
2 | + | |
3 | +{% block title %} | |
4 | + PYROS CONFIGURATION | |
5 | +{% endblock %} | |
6 | + | |
7 | +{% block content %} | |
8 | +<style> | |
9 | + #siteForm { | |
10 | + padding-top: 2%; | |
11 | + padding-left: 2%; | |
12 | + | |
13 | + } | |
14 | + | |
15 | + input[type] { | |
16 | + width: 5%; | |
17 | + padding: 3px; | |
18 | + box-sizing: border-box; | |
19 | + border: 3px solid #ccc; | |
20 | + -webkit-transition: 0.5s; | |
21 | + transition: 0.5s; | |
22 | + outline: none; | |
23 | + margin-right: 2%; | |
24 | + } | |
25 | + | |
26 | + input[type]:focus { | |
27 | + border: 3px solid #555; | |
28 | + } | |
29 | + | |
30 | + #Update { | |
31 | + font-family: 'Montserra', sans-serif; | |
32 | + margin-left: 5%; | |
33 | + margin-top: 2%; | |
34 | + } | |
35 | + fieldset { | |
36 | + margin-top: 2%; | |
37 | + } | |
38 | + | |
39 | + label{ | |
40 | + font-family: 'Montserra', sans-serif; | |
41 | + } | |
42 | +</style> | |
43 | +<form id="siteForm" action="" method="post">{% csrf_token %} | |
44 | + {% for field in form %} | |
45 | + {% if field.name == 'latitude' %} | |
46 | + <fieldset id="site" > <legend>Site :</legend> {{field.label}} {{field}} | |
47 | + {% elif field.name == 'row_data_save_frequency' %} | |
48 | + </fieldset><fieldset id="environment_monitoring" > <legend>Environment Monitoring :</legend> {{field.label}} {{field}} | |
49 | + {% elif field.name == 'telescope_ip_address' %} | |
50 | + </fieldset><fieldset id="telescope" > <legend>Telescope :</legend> {{field.label}} {{field}}</fieldset> | |
51 | + {% elif field.name == 'camera_ip_address' %} | |
52 | + <fieldset > <legend id="camera" >Camera :</legend> {{field.label}} {{field}}</fieldset> | |
53 | + {% elif field.name == 'plc_ip_address' %} | |
54 | + <fieldset > <legend id="plc" >PLC :</legend> {{field.label}} {{field}}</fieldset> | |
55 | + {% else %} | |
56 | + {{field.label}} {{field}} | |
57 | + {% endif %} | |
58 | + | |
59 | + {% endfor %} | |
60 | + <br> <input id="Update" type="submit" value="Update" /> | |
61 | +</form> | |
62 | + | |
63 | +{% endblock %} | |
0 | 64 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,56 @@ |
1 | +<style> | |
2 | + | |
3 | +#none { | |
4 | + font-family: 'Montserra', sans-serif; | |
5 | +} | |
6 | + | |
7 | +</style> | |
8 | + <div class="row"> | |
9 | + | |
10 | + <h1 id="none">Site info</h1> | |
11 | + | |
12 | + {% if site_info == None %} | |
13 | + | |
14 | + <h3 id="none" >There is no site info in the database</h3> | |
15 | + | |
16 | + {% else %} | |
17 | + <div class="well"> | |
18 | + Maximum of internal site info iteration set: {{iteration}} | |
19 | + </div> | |
20 | + <div class="row"> | |
21 | + <h3>List of Internal Site Info </h3> | |
22 | + <div class="table-responsive"> | |
23 | + <table | |
24 | + class="table table-bordered table-hover table-striped tablesorter" style="font-family: 'Montserra', sans-serif;"> | |
25 | + <thead> | |
26 | + <tr> | |
27 | + <th>Global Status <i class="fa fa-sort"></i></th> | |
28 | + <th>Updated <i class="fa fa-sort"></i></th> | |
29 | + <th>Lights <i class="fa fa-sort"></i></th> | |
30 | + <th>Dome <i class="fa fa-sort"></i></th> | |
31 | + <th>Doors <i class="fa fa-sort"></i></th> | |
32 | + <th>Temperature <i class="fa fa-sort"></i></th> | |
33 | + <th>Pressure <i class="fa fa-sort"></i></th> | |
34 | + <th>Shutter <i class="fa fa-sort"></i></th> | |
35 | + <th>Humidity <i class="fa fa-sort"></i></th> | |
36 | + </tr> | |
37 | + </thead> | |
38 | + <tbody> | |
39 | + {% for site_inf in site_info %} | |
40 | + <tr> | |
41 | + <td>{{ site_inf.global_status }}</td> | |
42 | + <td>{{ site_inf.updated }}</td> | |
43 | + <td>{{ site_inf.lights }}</td> | |
44 | + <td>{{ site_inf.dome }}</td> | |
45 | + <td>{{ site_inf.doors }}</td> | |
46 | + <td>{{ site_inf.temperature }}</td> | |
47 | + <td>{{ site_inf.pressure }}</td> | |
48 | + <td>{{ site_inf.shutter }}</td> | |
49 | + <td>{{ site_inf.humidity }}</td> | |
50 | + </tr> | |
51 | + {% endfor %} | |
52 | + </tbody> | |
53 | + </table> | |
54 | + </div> | |
55 | + </div> | |
56 | + {% endif %} | |
0 | 57 | \ No newline at end of file | ... | ... |
src/dashboard/templates/dashboard/current_weather.html
0 โ 100644
... | ... | @@ -0,0 +1,56 @@ |
1 | +<style> | |
2 | + | |
3 | +#none { | |
4 | + font-family: 'Montserra', sans-serif; | |
5 | +} | |
6 | + | |
7 | +</style> | |
8 | + <div class="row"> | |
9 | + | |
10 | + <h1 id="none">Weather info</h1> | |
11 | + | |
12 | + {% if weather_info == None %} | |
13 | + | |
14 | + <h3 id="none" >There is no weather info in the database</h3> | |
15 | + | |
16 | + {% else %} | |
17 | + <div class="well"> | |
18 | + Maximum of weather info iteration set: {{iteration}} | |
19 | + </div> | |
20 | + <div class="row"> | |
21 | + <h3>List of Weather Info </h3> | |
22 | + <div class="table-responsive"> | |
23 | + <table | |
24 | + class="table table-bordered table-hover table-striped tablesorter" style="font-family: 'Montserra', sans-serif;"> | |
25 | + <thead> | |
26 | + <tr> | |
27 | + <th>Global Status <i class="fa fa-sort"></i></th> | |
28 | + <th>Updated <i class="fa fa-sort"></i></th> | |
29 | + <th>Humidity <i class="fa fa-sort"></i></th> | |
30 | + <th>Wind <i class="fa fa-sort"></i></th> | |
31 | + <th>Wind Direction <i class="fa fa-sort"></i></th> | |
32 | + <th>Temperature <i class="fa fa-sort"></i></th> | |
33 | + <th>Pressure <i class="fa fa-sort"></i></th> | |
34 | + <th>Rain <i class="fa fa-sort"></i></th> | |
35 | + <th>Cloud <i class="fa fa-sort"></i></th> | |
36 | + </tr> | |
37 | + </thead> | |
38 | + <tbody> | |
39 | + {% for weather_inf in weather_info %} | |
40 | + <tr> | |
41 | + <td>{{ weather_inf.global_status }}</td> | |
42 | + <td>{{ weather_inf.updated }}</td> | |
43 | + <td>{{ weather_inf.humidity }}</td> | |
44 | + <td>{{ weather_inf.wind }}</td> | |
45 | + <td>{{ weather_inf.wind_dir }}</td> | |
46 | + <td>{{ weather_inf.temperature }}</td> | |
47 | + <td>{{ weather_inf.pressure }}</td> | |
48 | + <td>{{ weather_inf.rain }}</td> | |
49 | + <td>{{ weather_inf.cloud }}</td> | |
50 | + </tr> | |
51 | + {% endfor %} | |
52 | + </tbody> | |
53 | + </table> | |
54 | + </div> | |
55 | + </div> | |
56 | + {% endif %} | |
0 | 57 | \ No newline at end of file | ... | ... |
src/dashboard/templates/dashboard/index.html
1 | 1 | {% extends "base.html" %} |
2 | 2 | |
3 | +{%block topbar} | |
3 | 4 | {% block title %} |
4 | 5 | PYROS DASHBOARD |
5 | 6 | {% endblock %} |
... | ... | @@ -11,24 +12,25 @@ |
11 | 12 | max-height: 300px; |
12 | 13 | margin: 0 auto; |
13 | 14 | padding: 0% 2%; |
15 | + margin-top: 2%; | |
14 | 16 | } |
15 | 17 | |
16 | 18 | .science-section { |
17 | 19 | max-width: 1900px; |
18 | 20 | max-height: 300px; |
19 | - padding: 7% 2%; | |
21 | + padding: 5% 2%; | |
20 | 22 | } |
21 | 23 | |
22 | 24 | .monitoring-section h1 { |
23 | 25 | text-align: center; |
24 | 26 | font-family: 'Montserra', sans-serif; |
25 | - font-size: 50px; | |
27 | + font-size: 40px; | |
26 | 28 | } |
27 | 29 | |
28 | 30 | .science-section h1 { |
29 | 31 | text-align: center; |
30 | 32 | font-family: 'Montserra', sans-serif; |
31 | - font-size: 50px; | |
33 | + font-size: 40px; | |
32 | 34 | } |
33 | 35 | |
34 | 36 | .all-grid { |
... | ... | @@ -49,7 +51,7 @@ |
49 | 51 | |
50 | 52 | .all-grid li { |
51 | 53 | width: 220px; |
52 | - height: 200px; | |
54 | + height: 180px; | |
53 | 55 | display: inline-block; |
54 | 56 | margin: 40px; |
55 | 57 | } |
... | ... | @@ -99,16 +101,16 @@ |
99 | 101 | <a href="{% url "weather" %}"> |
100 | 102 | <div class="all-info"> |
101 | 103 | <h3>Weather</h3> |
102 | - <img src="{% static "media/weather.png" %}" alt="html5" height="200" width="200" /> | |
104 | + <img src="{% static "media/weather.png" %}" alt="html5" height="200" width="200"/> | |
103 | 105 | </div></a> |
104 | 106 | </div> |
105 | 107 | </li> |
106 | 108 | <li> |
107 | 109 | <div class="all-box all-img-observatory"> |
108 | - <a href="#"> | |
110 | + <a href="{% url "site" %}"> | |
109 | 111 | <div class="all-info"> |
110 | 112 | <h3>Observatory</h3> |
111 | - <img src="{% static "media/observatory.png" %}" alt="html5" height="200" width="200" /> | |
113 | + <img src="{% static "media/observatory.png" %}" alt="html5" height="200" width="200"/> | |
112 | 114 | </div></a> |
113 | 115 | </div> |
114 | 116 | </li> |
... | ... | @@ -117,7 +119,16 @@ |
117 | 119 | <a href="#"> |
118 | 120 | <div class="all-info"> |
119 | 121 | <h3>Tele & Inst</h3> |
120 | - <img src="{% static "media/telescope.png" %}" alt="html5" height="200" width="200" /> | |
122 | + <img src="{% static "media/telescope.png" %}" alt="html5" height="200" width="200"/> | |
123 | + </div></a> | |
124 | + </div> | |
125 | + </li> | |
126 | + <li> | |
127 | + <div class="all-box all-img-camera"> | |
128 | + <a href="#"> | |
129 | + <div class="all-info"> | |
130 | + <h3>Cameras</h3> | |
131 | + <img src="{% static "media/camera.png" %}" alt="html5" height="200" width="200"/> | |
121 | 132 | </div></a> |
122 | 133 | </div> |
123 | 134 | </li> |
... | ... | @@ -129,10 +140,10 @@ |
129 | 140 | <ul class="all-grid"> |
130 | 141 | <li> |
131 | 142 | <div class="all-box all-img-proposal"> |
132 | - <a href="#"> | |
143 | + <a href="{% url "proposal" %}"> | |
133 | 144 | <div class="all-info"> |
134 | 145 | <h3>Proposal</h3> |
135 | - {% load static %} <img src="{% static "media/proposal.png" %}" alt="html5" height="200" width="200" /> | |
146 | + {% load static %} <img src="{% static "media/proposal.png" %}" alt="html5" height="180" width="180" /> | |
136 | 147 | </div></a> |
137 | 148 | </div> |
138 | 149 | </li> |
... | ... | @@ -141,34 +152,35 @@ |
141 | 152 | <a href="{% url "requests_list" %}"> |
142 | 153 | <div class="all-info"> |
143 | 154 | <h3>Request</h3> |
144 | - {% load static %} <img src="{% static "media/request.png" %}" alt="html5" height="200" width="200" /> | |
155 | + {% load static %} <img src="{% static "media/request.png" %}" alt="html5" height="180" width="180" /> | |
145 | 156 | </div></a> |
146 | 157 | </div> |
147 | 158 | </li> |
148 | 159 | <li> |
149 | - <div class="all-box all-img-schedule"> | |
150 | - <a href="{% url "current_schedule" %}"> | |
160 | + <div class="all-box all-img-alert"> | |
161 | + <a href="{% url "alerts_list" %}"> | |
151 | 162 | <div class="all-info"> |
152 | - <h3>Schedule</h3> | |
153 | - <img src="{% static "media/schedule.png" %}" alt="html5" height="200" width="200" /> | |
163 | + <h3>Alerts</h3> | |
164 | + <img src="{% static "media/alert.png" %}" alt="html5" height="180" width="180" /> | |
154 | 165 | </div></a> |
155 | 166 | </div> |
156 | 167 | </li> |
157 | 168 | <li> |
158 | - <div class="all-box all-img-alert"> | |
159 | - <a href="{% url "alerts_list" %}"> | |
169 | + <div class="all-box all-img-schedule"> | |
170 | + <a href="{% url "current_schedule" %}"> | |
160 | 171 | <div class="all-info"> |
161 | - <h3>Alert</h3> | |
162 | - <img src="{% static "media/alert.png" %}" alt="html5" height="200" width="200" /> | |
172 | + <h3>Schedule</h3> | |
173 | + <img src="{% static "media/schedule.png" %}" alt="html5" height="180" width="180" /> | |
163 | 174 | </div></a> |
164 | 175 | </div> |
165 | 176 | </li> |
177 | + | |
166 | 178 | <li> |
167 | 179 | <div class="all-box all-img-image"> |
168 | 180 | <a href="#"> |
169 | 181 | <div class="all-info"> |
170 | - <h3>Image</h3> | |
171 | - <img src="{% static "media/image.png" %}" alt="html5" height="200" width="200" /> | |
182 | + <h3>Images</h3> | |
183 | + <img src="{% static "media/image.png" %}" alt="html5" height="180" width="180" /> | |
172 | 184 | </div></a> |
173 | 185 | </div> |
174 | 186 | </li> | ... | ... |
... | ... | @@ -0,0 +1,59 @@ |
1 | +{% extends "base.html" %} | |
2 | + | |
3 | +{% block content %} | |
4 | + | |
5 | +<style> | |
6 | + | |
7 | +#none { | |
8 | + font-family: 'Montserra', sans-serif; | |
9 | +} | |
10 | + | |
11 | +#page-wrapper { | |
12 | + padding: 1% 3%; | |
13 | +} | |
14 | +</style> | |
15 | + <div id="refresh" class="container-fluid"> | |
16 | + </div> | |
17 | + <div class="row"> | |
18 | + | |
19 | + <h1 id="none">Proposal info</h1> | |
20 | + | |
21 | + {% if proposal_info == None %} | |
22 | + | |
23 | + <h3 id="none" >There is no proposal info in the database</h3> | |
24 | + | |
25 | + {% else %} | |
26 | + <div class="well"> | |
27 | + Number of proposal : {{nb_info_proposal}} | |
28 | + </div> | |
29 | + <div class="row"> | |
30 | + <h3>List of proposal Info - <span class="label label-primary">{{proposal_info|length}}</span></h3> | |
31 | + <div class="table-responsive"> | |
32 | + <table | |
33 | + class="table table-bordered table-hover table-striped tablesorter" style="font-family: 'Montserra', sans-serif;"> | |
34 | + <thead> | |
35 | + <tr> | |
36 | + <th>Users <i class="fa fa-sort"></i></th> | |
37 | + <th>Name <i class="fa fa-sort"></i></th> | |
38 | + <th>Desc <i class="fa fa-sort"></i></th> | |
39 | + <th>Quota <i class="fa fa-sort"></i></th> | |
40 | + <th>Priority <i class="fa fa-sort"></i></th> | |
41 | + </tr> | |
42 | + </thead> | |
43 | + <tbody> | |
44 | + {% for proposal_inf in proposal_info %} | |
45 | + <tr> | |
46 | + <td>{{ proposal_inf.pyros_users }}</td> | |
47 | + <td>{{ proposal_inf.name }}</td> | |
48 | + <td>{{ proposal_inf.desc }}</td> | |
49 | + <td>{{ proposal_inf.quota }}</td> | |
50 | + <td>{{ proposal_inf.priority }}</td> | |
51 | + </tr> | |
52 | + {% endfor %} | |
53 | + </tbody> | |
54 | + </table> | |
55 | + </div> | |
56 | + </div> | |
57 | + {% endif %} | |
58 | + | |
59 | +{% endblock %} | |
0 | 60 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | + | |
2 | +{% extends "base.html" %} | |
3 | + | |
4 | +{% block head %} | |
5 | +<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> | |
6 | +<script> | |
7 | + function current_site() { | |
8 | + $('#refresh').load("{% url 'site_current' %}"); | |
9 | + } | |
10 | + | |
11 | + $(document).ready(function() { | |
12 | + current_site(); | |
13 | + setInterval(current_site, 1000); | |
14 | + }); | |
15 | + | |
16 | +</script> | |
17 | + | |
18 | +{% endblock %} | |
19 | + | |
20 | +{% block content %} | |
21 | +<div id="refresh" class="container-fluid"> | |
22 | + </div> | |
23 | + | |
24 | +{% endblock %} | |
0 | 25 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | + | |
2 | +{% extends "base.html" %} | |
3 | + | |
4 | +{% block head %} | |
5 | +<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> | |
6 | +<script> | |
7 | + function current_weather() { | |
8 | + $('#refresh').load("{% url 'weather_current' %}"); | |
9 | + } | |
10 | + | |
11 | + $(document).ready(function() { | |
12 | + current_weather(); | |
13 | + setInterval(current_weather, 1000); | |
14 | + }); | |
15 | + | |
16 | +</script> | |
17 | + | |
18 | +{% endblock %} | |
19 | + | |
20 | +{% block content %} | |
21 | +<div id="refresh" class="container-fluid"> | |
22 | + </div> | |
23 | + | |
24 | +{% endblock %} | |
0 | 25 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +from django import template | |
2 | +from common.models import Config | |
3 | + | |
4 | +register = template.Library() | |
5 | + | |
6 | +@register.simple_tag | |
7 | +def global_mode(request): | |
8 | + if (Config.objects.get(id=1).global_mode == True): | |
9 | + return("AUTOMATIC MODE") | |
10 | + else: | |
11 | + return("MANUAL MODE") | |
0 | 12 | \ No newline at end of file | ... | ... |
src/dashboard/urls.py
... | ... | @@ -4,9 +4,14 @@ from . import views |
4 | 4 | urlpatterns = [ |
5 | 5 | url(r'^index$', views.index, name='index'), |
6 | 6 | url(r'^users$', views.users, name="users"), |
7 | + url(r'^configuration$', views.configUpdate, name='configuration'), | |
8 | + url(r'^status$', views.change_globalMode, name='change_globalMode'), | |
7 | 9 | url(r'^routines$', views.routines, name="routines"), |
8 | 10 | url(r'^weather$', views.weather, name="weather"), |
11 | + url(r'^weather/current$', views.weather_current, name="weather_current"), | |
9 | 12 | url(r'^site$', views.site, name="site"), |
13 | + url(r'^site/current$', views.site_current, name="site_current"), | |
14 | + url(r'^proposal$', views.proposal, name='proposal'), | |
10 | 15 | url(r'^devices$', views.devices, name="devices"), |
11 | 16 | url(r'^system$', views.system, name="system"), |
12 | 17 | url(r'^system/logs$', views.system_retrieve_logs, | ... | ... |
src/dashboard/views.py
1 | 1 | from django.shortcuts import render, redirect |
2 | 2 | from django.core import urlresolvers |
3 | 3 | from django.contrib.auth.decorators import login_required |
4 | -from common.models import Log | |
5 | - | |
4 | +from common.models import Log, WeatherWatch, SiteWatch, ScientificProgram, Config | |
6 | 5 | import utils.Logger as l |
6 | +from dashboard.forms import ConfigForm | |
7 | +from django.views.generic.edit import UpdateView | |
8 | +from django.shortcuts import get_object_or_404 | |
9 | +from django.utils.decorators import method_decorator | |
10 | +from django.urls import reverse_lazy | |
11 | + | |
7 | 12 | log = l.setupLogger("dashboard", "dashboard") |
8 | 13 | |
9 | 14 | @login_required |
10 | 15 | def index(request): |
11 | - return render(request, 'dashboard/index.html') | |
16 | + return render(request, 'dashboard/index.html') # return the initial view (the dashboard's one) | |
12 | 17 | |
13 | 18 | @login_required |
14 | 19 | def users(request): |
15 | 20 | url_ = urlresolvers.reverse('admin:auth_user_changelist') |
16 | - return redirect(url_) | |
21 | + return redirect(url_) | |
17 | 22 | |
18 | 23 | @login_required |
19 | 24 | def routines(request): |
... | ... | @@ -23,15 +28,58 @@ def routines(request): |
23 | 28 | |
24 | 29 | @login_required |
25 | 30 | def weather(request): |
26 | - url_ = urlresolvers.reverse('admin:common_weatherwatch_changelist') | |
27 | - return redirect(url_) | |
31 | + return render(request, 'dashboard/reload_weather.html') # return the needed html file | |
32 | + | |
33 | +@login_required | |
34 | +def weather_current(request): | |
35 | + if (len(Config.objects.all()) == 1): | |
36 | + monitoring = int(int(Config.objects.get(id=1).row_data_save_frequency) / 5) | |
37 | + else: | |
38 | + monitoring = 60 | |
39 | + if (len(WeatherWatch.objects.all()) > 0): | |
40 | + weather_info = WeatherWatch.objects.order_by("-id")[:monitoring] # Use 300 seconds by default with an iteration every 5 seconds # Get the number of data available | |
41 | + else: | |
42 | + weather_info = None | |
43 | + return render(request, 'dashboard/current_weather.html', {'weather_info' : weather_info, 'iteration' : monitoring}) | |
28 | 44 | |
29 | 45 | |
30 | 46 | @login_required |
31 | 47 | def site(request): |
32 | - url_ = urlresolvers.reverse('admin:common_sitewatch_changelist') | |
33 | - return redirect(url_) | |
48 | + return render(request, 'dashboard/reload_site.html') # return the needed html file | |
49 | + | |
50 | +@login_required | |
51 | +def site_current(request): | |
52 | + if (len(Config.objects.all()) == 1): | |
53 | + monitoring = int(int(Config.objects.get(id=1).row_data_save_frequency) / 5) | |
54 | + else: | |
55 | + monitoring = 60 | |
56 | + if (len(SiteWatch.objects.all()) > 0): | |
57 | + site_info = SiteWatch.objects.order_by("-id")[:monitoring] | |
58 | + else: | |
59 | + site_info = None | |
60 | + return render(request, 'dashboard/current_site.html', {'site_info' : site_info, 'iteration' : monitoring}) | |
61 | + | |
62 | +@login_required | |
63 | +def proposal(request): | |
64 | + if (len(ScientificProgram.objects.all()) > 0): # checking if the observatory table is empty | |
65 | + proposal_info = ScientificProgram.objects.order_by("-id")[:100] # Sorting Weather table | |
66 | + nb_info_proposal = len(proposal_info) # Get the number of data available | |
67 | + | |
68 | + else: # if empty set everything to 0 / None (variables are checked in src/templates/scheduler/current_weather.html) | |
69 | + proposal_info = None | |
70 | + nb_info_proposal = 0 | |
34 | 71 | |
72 | + return render(request, 'dashboard/proposal.html', {'proposal_info' : proposal_info, 'nb_info_proposal' : nb_info_proposal}) | |
73 | + | |
74 | +@login_required | |
75 | +def configUpdate(request): | |
76 | + instance = get_object_or_404(Config, id=1) | |
77 | + form = ConfigForm(request.POST or None, instance=instance) | |
78 | + if form.is_valid(): | |
79 | + form.save() | |
80 | + return redirect('../user_manager/profile') | |
81 | + return render(request, 'dashboard/configuration.html', {'form': form}) | |
82 | + | |
35 | 83 | |
36 | 84 | @login_required |
37 | 85 | def devices(request): |
... | ... | @@ -67,3 +115,10 @@ def schedule(request): |
67 | 115 | def quotas(request): |
68 | 116 | url_ = urlresolvers.reverse('admin:common_pyrosuser_changelist') |
69 | 117 | return redirect(url_) |
118 | + | |
119 | + | |
120 | +def change_globalMode(request): | |
121 | + config = get_object_or_404(Config, id=1) | |
122 | + config.global_mode = not config.global_mode | |
123 | + config.save() | |
124 | + return redirect('index') | |
70 | 125 | \ No newline at end of file | ... | ... |
55.5 KB
src/misc/static/media/proposal.png
src/misc/templates/base.html
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | <meta name="author" content="CNRS-IRAP"> |
12 | 12 | |
13 | 13 | |
14 | - <title>SVOM French GFT Control Center</title> | |
14 | + <title >Colibri Control Center</title> | |
15 | 15 | |
16 | 16 | <!-- Bootstrap core CSS --> |
17 | 17 | <link href={% static "bootstrap/css/bootstrap.css" %} rel="stylesheet"> |
... | ... | @@ -28,27 +28,54 @@ |
28 | 28 | <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" crossorigin="anonymous"> |
29 | 29 | |
30 | 30 | {% block head %} |
31 | - | |
31 | + <style> | |
32 | + #title { | |
33 | + font-family: 'Montserra', sans-serif; | |
34 | + font-size: 50px; | |
35 | + } | |
36 | + </style> | |
32 | 37 | {% endblock %} |
33 | 38 | |
34 | 39 | </head> |
35 | 40 | |
36 | 41 | <body> |
37 | - | |
42 | +<style> | |
43 | +#page-wrapper { | |
44 | + padding: 15px 60px; | |
45 | +} | |
46 | +#wrapper { | |
47 | + padding-left: 10%; | |
48 | +} | |
49 | + | |
50 | +.side-nav { | |
51 | + margin-left: -200px; | |
52 | + left: 200px; | |
53 | + width: 200px; | |
54 | +} | |
55 | + | |
56 | +a { | |
57 | + font-family: 'Montserra', sans-serif; | |
58 | + | |
59 | +} | |
60 | + | |
61 | +#fas { | |
62 | + size: 20px; | |
63 | +} | |
64 | +</style> | |
65 | +{% load tags %} | |
38 | 66 | <div id="wrapper"> |
39 | 67 | |
40 | 68 | <!-- Sidebar --> |
41 | 69 | <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> |
42 | 70 | <!-- Brand and toggle get grouped for better mobile display --> |
43 | 71 | <div class="navbar-header"> |
44 | - <a class="navbar-brand" href={% url "index" %}>SVOM French GFT Control Center</a> | |
72 | + <a class="navbar-brand" href={% url "index" %}>Colibri Control Center</a> | |
45 | 73 | </div> |
46 | 74 | |
47 | 75 | |
48 | 76 | <!-- Collect the nav links, forms, and other content for toggling --> |
49 | 77 | <div class="collapse navbar-collapse navbar-ex1-collapse"> |
50 | - | |
51 | - <ul class="nav navbar-nav side-nav"> | |
78 | + <ul class="nav navbar-nav side-nav"> | |
52 | 79 | <li><a href="{% url "current_schedule" %}">Schedule</a></li> |
53 | 80 | <li><a href="{% url "system" %}">System</a></li> |
54 | 81 | <li><a href="{% url "alerts_list" %}">Alerts</a></li> |
... | ... | @@ -58,20 +85,19 @@ |
58 | 85 | <li><a href="{% url "devices" %}">Devices</a></li> |
59 | 86 | <li><a href="{% url "users" %}">Users</a></li> |
60 | 87 | </ul> |
61 | - | |
62 | 88 | <ul class="nav navbar-nav navbar-right navbar-user"> |
63 | - | |
64 | - <li class="dropdown alerts-dropdown"> | |
89 | + <li> | |
90 | + <a id="globalmode" href="{% url "change_globalMode" %}" onclick="return confirm('Are you sure you want to switch the controller mode ?')"> {% global_mode request %} </a> | |
91 | + </li> | |
92 | + <li> | |
65 | 93 | <a href="{% url "profile" %}"><i class="fas fa-cog"></i></a> |
66 | 94 | </li> |
67 | - <li class="dropdown user-dropdown"> | |
95 | + <li> | |
68 | 96 | <a href="{% url "user_logout" %}" ><i class="fa fa-power-off"></i> Log Out</a> |
69 | 97 | </li> |
70 | 98 | </ul> |
71 | - | |
72 | 99 | </div><!-- /.navbar-collapse --> |
73 | - | |
74 | - | |
100 | + | |
75 | 101 | </nav> |
76 | 102 | |
77 | 103 | <div id="page-wrapper"> | ... | ... |
src/pyros/settings.py
... | ... | @@ -126,11 +126,11 @@ LOGIN_URL = "/" |
126 | 126 | "$ pyros.py simulator_development" will automatically set them to "True" |
127 | 127 | ''' |
128 | 128 | # FOR SIMULATOR (TODO: remove because not used) |
129 | -SIMULATOR = False | |
129 | +SIMULATOR = True | |
130 | 130 | # FOR SIMULATOR (and TESTS) |
131 | -CELERY_TEST = False | |
131 | +CELERY_TEST = True | |
132 | 132 | |
133 | -# CELERY_TEST = False ==> DEFAULT (NORMAL) RUN MODE, use pyros (normal) database | |
133 | +# CELERY_TEST = True ==> DEFAULT (NORMAL) RUN MODE, use pyros (normal) database | |
134 | 134 | if not CELERY_TEST: |
135 | 135 | if not MYSQL: |
136 | 136 | DATABASES = { |
... | ... | @@ -149,7 +149,7 @@ if not CELERY_TEST: |
149 | 149 | } |
150 | 150 | } |
151 | 151 | |
152 | -# CELERY_TEST = False ==> 'TEST' RUN MODE, use pyros_test database | |
152 | +# CELERY_TEST = True ==> 'TEST' RUN MODE, use pyros_test database | |
153 | 153 | else: |
154 | 154 | DATABASES = { |
155 | 155 | 'default': { | ... | ... |
src/user_manager/templates/user_manager/profile.html
... | ... | @@ -89,7 +89,7 @@ |
89 | 89 | </li> |
90 | 90 | <li> |
91 | 91 | <div class="setting-box setting-img-users"> |
92 | - <a href="url "users" %}"> | |
92 | + <a href="{% url "users" %}"> | |
93 | 93 | <div class="setting-info"> |
94 | 94 | <h3>Users</h3> |
95 | 95 | <img src="{% static "media/users.png" %}" alt="html5" height="250" width="250" /> |
... | ... | @@ -98,7 +98,7 @@ |
98 | 98 | </li> |
99 | 99 | <li> |
100 | 100 | <div class="setting-box setting-img-configuration"> |
101 | - <a href="#"> | |
101 | + <a href="{% url "configuration" %}"> | |
102 | 102 | <div class="setting-info"> |
103 | 103 | <h3>Configuration</h3> |
104 | 104 | <img src="{% static "media/configuration.png" %}" alt="html5" height="250" width="250" /> | ... | ... |