Commit 3dbda6a041c1d5f50b76c384f0d97452b7079431
1 parent
eea995c9
Exists in
master
and in
1 other branch
Date: 17/06/2016
By: Paul Carensac Version: 0.7.4 Import XML + Changed deprecated reverse by dotting path in templates (links) Warning : DB updated Issues (closed): https://projects.irap.omp.eu/issues/3811 Major current version (0.7): https://projects.irap.omp.eu/versions/117
Showing
22 changed files
with
318 additions
and
95 deletions
Show diff stats
README.md
... | ... | @@ -60,11 +60,12 @@ PROJECT STRUCTURE: |
60 | 60 | -------------------------------------------------------------------------------------------- |
61 | 61 | CURRENT VERSION |
62 | 62 | |
63 | -Date: 16/06/2016 | |
63 | +Date: 17/06/2016 | |
64 | 64 | By: Paul Carensac |
65 | -Version: 0.7.3 | |
66 | -Export XML + download | |
67 | -Issues (closed): https://projects.irap.omp.eu/issues/3827 | |
65 | +Version: 0.7.4 | |
66 | +Import XML + Changed deprecated reverse by dotting path in templates (links) | |
67 | +Warning : DB updated | |
68 | +Issues (closed): https://projects.irap.omp.eu/issues/3811 | |
68 | 69 | Major current version (0.7): https://projects.irap.omp.eu/versions/117 |
69 | 70 | |
70 | 71 | ROADMAP: https://projects.irap.omp.eu/projects/pyros/roadmap | ... | ... |
src/alert_manager/templates/alert_manager/alert_simulation.html
... | ... | @@ -15,7 +15,7 @@ |
15 | 15 | <br> |
16 | 16 | <center> |
17 | 17 | <div class="row"> |
18 | - <a href="{% url "alert_manager.views.alert_simulation_start" %}" class="btn btn-lg btn-info"> | |
18 | + <a href="{% url "alert_simulation_start" %}" class="btn btn-lg btn-info"> | |
19 | 19 | Simulate an alert ! |
20 | 20 | </a> |
21 | 21 | </div> | ... | ... |
src/alert_manager/templates/alert_manager/alerts.html
... | ... | @@ -29,7 +29,7 @@ |
29 | 29 | <td align="center"> |
30 | 30 | {{ alert.strategyobs.name }} |
31 | 31 |     |
32 | - <a href="{% url "alert_manager.views.change_obs_strategy" alert.id %}" | |
32 | + <a href="{% url "change_obs_strategy" alert.id %}" | |
33 | 33 | class="btn btn-primary" type="a"> |
34 | 34 | Change |
35 | 35 | </a> | ... | ... |
src/alert_manager/templates/alert_manager/strategy_change.html
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | |
12 | 12 | <div class="row"> |
13 | 13 | <h3>Select a new observation strategy for alert {{ alert.request.name }}:</h3> |
14 | - <form action="{% url 'alert_manager.views.change_obs_strategy_validate' alert.id %}" method="post"> | |
14 | + <form action="{% url 'change_obs_strategy_validate' alert.id %}" method="post"> | |
15 | 15 | {% csrf_token %} |
16 | 16 | {% for strategy in strategies %} |
17 | 17 | <div class="row"> |
... | ... | @@ -33,7 +33,7 @@ |
33 | 33 | </div> |
34 | 34 | |
35 | 35 | <div class="row"> |
36 | - <a href="{% url "alert_manager.views.alerts_list" %}" class="btn btn-sm btn-primary" type="a">Back to alerts list</a> | |
36 | + <a href="{% url "alerts_list" %}" class="btn btn-sm btn-primary" type="a">Back to alerts list</a> | |
37 | 37 | </div> |
38 | 38 | </div><!-- /#page-wrapper --> |
39 | 39 | {% endblock %} | ... | ... |
src/alert_manager/urls.py
... | ... | @@ -2,9 +2,9 @@ from django.conf.urls import url |
2 | 2 | from . import views |
3 | 3 | |
4 | 4 | urlpatterns = [ |
5 | - url(r'^simulation$', views.alert_simulation), | |
6 | - url(r'^simulation/start$', views.alert_simulation_start), | |
7 | - url(r'^change_obs_strategy/(?P<alert_id>\d+)$', views.change_obs_strategy), | |
8 | - url(r'^change_obs_strategy_validate/(?P<alert_id>\d+)$', views.change_obs_strategy_validate), | |
9 | - url(r'^alerts$', views.alerts_list), | |
5 | + url(r'^simulation$', views.alert_simulation, name="alert_simulation"), | |
6 | + url(r'^simulation/start$', views.alert_simulation_start, name="alert_simulation_start"), | |
7 | + url(r'^change_obs_strategy/(?P<alert_id>\d+)$', views.change_obs_strategy, name="change_obs_strategy"), | |
8 | + url(r'^change_obs_strategy_validate/(?P<alert_id>\d+)$', views.change_obs_strategy_validate, name="change_obs_strategy_validate"), | |
9 | + url(r'^alerts$', views.alerts_list, name='alerts_list'), | |
10 | 10 | ] | ... | ... |
src/routine_manager/RequestSerializer.py
1 | 1 | from pyrosapp.models import * |
2 | +import pyrosapp | |
2 | 3 | import xml.etree.ElementTree as ET |
3 | 4 | import sys |
4 | 5 | from xml.dom import minidom |
6 | +from .validators import check_plan_validity | |
7 | +import re | |
8 | +from decimal import Decimal | |
5 | 9 | |
6 | 10 | def prettify(elem): |
7 | 11 | """ |
... | ... | @@ -38,12 +42,156 @@ class RequestSerializer(): |
38 | 42 | with open(file_name, "w") as file: |
39 | 43 | file.write(prettify(request)) |
40 | 44 | |
41 | - def unserialize(self, file_name): | |
45 | + def unserialize(self, xml_data, pyros_user): | |
42 | 46 | """ |
43 | 47 | Unserializes the request read into file_name |
44 | 48 | Throws exceptions in case of invalid file or values |
45 | 49 | |
46 | 50 | Directly saves the objects in DB |
47 | 51 | The request still need to be submitted afterward ! |
52 | + | |
53 | + :returns : "" (empty string) in case of success, error message (string) instead | |
48 | 54 | """ |
49 | - pass | |
55 | + | |
56 | + try: | |
57 | + root = ET.fromstring(xml_data) | |
58 | + except ET.ParseError as E: | |
59 | + return "Invalid file : " + str(E) | |
60 | + | |
61 | + self.pyros_user = pyros_user | |
62 | + self.request = None | |
63 | + | |
64 | + """ self.sequences will be a [(seq, album_list), ...], and same thing for album """ | |
65 | + self.sequences = [] | |
66 | + ret = self.unserialize_request(root) | |
67 | + if ret != "": | |
68 | + return ret | |
69 | + | |
70 | + self.request.save() | |
71 | + for sequence, albums in self.sequences: | |
72 | + sequence.request = self.request | |
73 | + sequence.save() | |
74 | + for album, plans in albums: | |
75 | + album.sequence = sequence | |
76 | + album.save() | |
77 | + for plan in plans: | |
78 | + plan.album = album | |
79 | + plan.save() | |
80 | + check_plan_validity(plan) | |
81 | + | |
82 | + return "" | |
83 | + | |
84 | + def unserialize_request(self, request): | |
85 | + if request.tag != "request": | |
86 | + return "Main object should be a request (found %s instead)" % (request.tag,) | |
87 | + possible_attribs = ["name", "scientific_program", "target_type"] | |
88 | + | |
89 | + self.request = Request(pyros_user=self.pyros_user, is_alert=False, complete=False, submitted=False) | |
90 | + | |
91 | + for name, value in request.attrib.items(): | |
92 | + if name not in possible_attribs: | |
93 | + return "Unknown attribute %s in request" % (name,) | |
94 | + if name == "scientific_program": | |
95 | + try: | |
96 | + sp = ScientificProgram.objects.get(name=value) | |
97 | + self.request.scientific_program = sp | |
98 | + except Exception as E: | |
99 | + print(str(E)) | |
100 | + return "Invalid scientific program %s" % (value,) | |
101 | + else: | |
102 | + self.request.__dict__[name] = value | |
103 | + | |
104 | + for sequence in request: | |
105 | + ret = self.unserialize_sequence(sequence) | |
106 | + if ret != "": | |
107 | + return ret | |
108 | + return "" | |
109 | + | |
110 | + def unserialize_sequence(self, sequence): | |
111 | + if sequence.tag != "sequence": | |
112 | + return "A request can only have 'sequence' children (found %s instead)" % (sequence.tag,) | |
113 | + possible_attribs = ["name", "target_coords", "jd1", "jd2", "duration"] | |
114 | + | |
115 | + seq = Sequence(request=self.request, status=Sequence.INCOMPLETE) | |
116 | + | |
117 | + for name, value in sequence.attrib.items(): | |
118 | + if name not in possible_attribs: | |
119 | + return "Unknown attribute %s in sequence" % (name,) | |
120 | + if name == "name": | |
121 | + seq.name = value | |
122 | + elif name == "target_coords": | |
123 | + seq.target_coords = value | |
124 | + elif name == "jd1": | |
125 | + seq.jd1 = Decimal(value) | |
126 | + elif name == "jd2": | |
127 | + seq.jd2 = Decimal(value) | |
128 | + elif name == "duration": | |
129 | + seq.duration = Decimal(value) | |
130 | + | |
131 | + # faire des checks ?? j'imagine | |
132 | + album_list = [] | |
133 | + self.sequences.append((seq, album_list)) | |
134 | + | |
135 | + for album in sequence: | |
136 | + ret = self.unserialize_album(album, seq, album_list) | |
137 | + if ret != "": | |
138 | + return ret | |
139 | + return "" | |
140 | + | |
141 | + def unserialize_album(self, album, sequence, album_list): | |
142 | + if album.tag != "album": | |
143 | + return "A sequence can only have 'album' children (found %s instead)" % (album.tag,) | |
144 | + possible_attribs = ["name", "detector"] | |
145 | + | |
146 | + alb = Album(sequence=sequence) | |
147 | + | |
148 | + for name, value in album.attrib.items(): | |
149 | + if name not in possible_attribs: | |
150 | + return "Unknown attribute %s in album" % (name,) | |
151 | + if name == "detector": | |
152 | + try: | |
153 | + detector = Detector.objects.get(device__name=value) | |
154 | + alb.detector = detector | |
155 | + except Exception as E: | |
156 | + print(str(E)) | |
157 | + return "Invalid detector %s" % (value,) | |
158 | + elif name == "name": | |
159 | + alb.name = value | |
160 | + plan_list = [] | |
161 | + album_list.append((alb, plan_list)) | |
162 | + | |
163 | + for plan in album: | |
164 | + ret = self.unserialize_plan(plan, alb, plan_list) | |
165 | + if ret != "": | |
166 | + return ret | |
167 | + return "" | |
168 | + | |
169 | + | |
170 | + def unserialize_plan(self, plan, album, plan_list): | |
171 | + if plan.tag != "plan": | |
172 | + return "An album can only have 'plan' children (found %s instead)" % (plan.tag,) | |
173 | + possible_attribs = ["name", "filter", "duration", "nb_images"] | |
174 | + | |
175 | + pl = Plan(album=album) | |
176 | + | |
177 | + for name, value in plan.attrib.items(): | |
178 | + if name not in possible_attribs: | |
179 | + return "Unknown attribute %s in plan" % (name,) | |
180 | + if name == "filter": | |
181 | + try: | |
182 | + filter = Filter.objects.get(device__name=value) | |
183 | + pl.filter = filter | |
184 | + except Exception as E: | |
185 | + return "Invalid filter %s" % (value,) | |
186 | + elif name == "name": | |
187 | + pl.name = value | |
188 | + elif name == "duration": | |
189 | + pl.duration = Decimal(value) | |
190 | + elif name == "nb_images": | |
191 | + pl.nb_images = int(value) | |
192 | + | |
193 | + # quelques checks ... | |
194 | + | |
195 | + plan_list.append(pl) | |
196 | + return "" | |
197 | + | ... | ... |
src/routine_manager/templates/routine_manager/edit_base.html
... | ... | @@ -13,19 +13,19 @@ |
13 | 13 | <ul class="nav nav-tabs col-lg-4" style="margin-bottom: 15px;"> |
14 | 14 | |
15 | 15 | {% if depth_level > 0 %} |
16 | - <li {% if depth_level == 1 %}class="active"{% endif %}><a href="{% url "routine_manager.views.action_request" req_id action%}" >Request Info</a></li> | |
16 | + <li {% if depth_level == 1 %}class="active"{% endif %}><a href="{% url "action_request" req_id action%}" >Request Info</a></li> | |
17 | 17 | {% endif %} |
18 | 18 | |
19 | 19 | {% if depth_level > 1 %} |
20 | - <li {% if depth_level == 2 %}class="active"{% endif %}><a href="{% url "routine_manager.views.action_sequence" seq_id action%}" >Sequence Info</a></li> | |
20 | + <li {% if depth_level == 2 %}class="active"{% endif %}><a href="{% url "action_sequence" seq_id action%}" >Sequence Info</a></li> | |
21 | 21 | {% endif %} |
22 | 22 | |
23 | 23 | {% if depth_level > 2 %} |
24 | - <li {% if depth_level == 3 %}class="active"{% endif %}><a href="{% url "routine_manager.views.action_album" alb_id action%}" >Album Info</a></li> | |
24 | + <li {% if depth_level == 3 %}class="active"{% endif %}><a href="{% url "action_album" alb_id action%}" >Album Info</a></li> | |
25 | 25 | {% endif %} |
26 | 26 | |
27 | 27 | {% if depth_level > 3 %} |
28 | - <li {% if depth_level == 4 %}class="active"{% endif %}><a href="{% url "routine_manager.views.action_plan" plan_id action%}" >Plan Info</a></li> | |
28 | + <li {% if depth_level == 4 %}class="active"{% endif %}><a href="{% url "action_plan" plan_id action%}" >Plan Info</a></li> | |
29 | 29 | {% endif %} |
30 | 30 | </ul> |
31 | 31 | |
... | ... | @@ -34,20 +34,20 @@ |
34 | 34 | <div class="row col-lg-4"> |
35 | 35 | {% if req.submitted == False %} |
36 | 36 | {% if req.complete == True %} |
37 | - <a href="{% url "routine_manager.views.submit_request" req.id %}" class="btn btn-info" onclick="return confirm('The request will be validated, and the sequences scheduled')" | |
37 | + <a href="{% url "submit_request" req.id %}" class="btn btn-info" onclick="return confirm('The request will be validated, and the sequences scheduled')" | |
38 | 38 | title="The request will be validated, and the sequences scheduled">Submit request for scheduling</a> |
39 | 39 | {% else %} |
40 | 40 | <a class="btn btn-info" onclick="return confirm('The request must be complete to be submitted')" |
41 | 41 | title="The request must be complete to be submitted">Submit request for scheduling</a> |
42 | 42 | {% endif %} |
43 | 43 | {% else %} |
44 | - <a href="{% url "routine_manager.views.unsubmit_request" req.id %}" class="btn btn-warning" onclick="return confirm('The request will be unvalidated, and the unexecuted sequences, unscheduled')" | |
44 | + <a href="{% url "unsubmit_request" req.id %}" class="btn btn-warning" onclick="return confirm('The request will be unvalidated, and the unexecuted sequences, unscheduled')" | |
45 | 45 | title="The request will be unvalidated, and the unexecuted sequences, unscheduled">Unsubmit request</a> |
46 | 46 | {% endif %} |
47 | 47 | </div> |
48 | 48 | |
49 | 49 | <div class="row col-lg-4"> |
50 | - <a href="{% url "routine_manager.views.export_request" req.id %}" class="btn btn-info">Export request as XML file</a> | |
50 | + <a href="{% url "export_request" req.id %}" class="btn btn-info">Export request as XML file</a> | |
51 | 51 | </div> |
52 | 52 | |
53 | 53 | <div class="row col-lg-4"> |
... | ... | @@ -80,25 +80,25 @@ |
80 | 80 | <div class="panel-heading"><h3>Summary</h3></div> |
81 | 81 | <div class="well" style="overflow:hidden; height:350px;"> |
82 | 82 | <div> |
83 | - <a class="btn btn-sm {% if req.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "routine_manager.views.action_request" req_id action%}" >Request: {{ req.name }}</a> | |
83 | + <a class="btn btn-sm {% if req.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "action_request" req_id action%}" >Request: {{ req.name }}</a> | |
84 | 84 | {% if depth_level == 1 %}<span class="label label-info">{{action}}ing ...</span>{% endif %} |
85 | 85 | </div> |
86 | 86 | {% for seq in req.sequences.all %} |
87 | 87 | |
88 | 88 | <div> |
89 | - <a class="btn btn-sm {% if seq.status != "INCPL" %}btn-success{% else %}btn-danger{% endif %}" href="{% url "routine_manager.views.action_sequence" seq.id action%}" style="margin-left: 60px" >Sequence: {{ seq.name }}</a> | |
89 | + <a class="btn btn-sm {% if seq.status != "INCPL" %}btn-success{% else %}btn-danger{% endif %}" href="{% url "action_sequence" seq.id action%}" style="margin-left: 60px" >Sequence: {{ seq.name }}</a> | |
90 | 90 | {% if depth_level == 2 and seq_id == seq.id %}<span class="label label-info">{{action}}ing ...</span>{% endif %} |
91 | 91 | </div> |
92 | 92 | {% for album in seq.albums.all %} |
93 | 93 | |
94 | 94 | <div> |
95 | - <a class="btn btn-sm {% if album.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "routine_manager.views.action_album" album.id action%}" style="margin-left: 120px" >Album: {{ album.name }}</a> | |
95 | + <a class="btn btn-sm {% if album.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "action_album" album.id action%}" style="margin-left: 120px" >Album: {{ album.name }}</a> | |
96 | 96 | {% if depth_level == 3 and alb_id == album.id %}<span class="label label-info">{{action}}ing ...</span>{% endif %} |
97 | 97 | </div> |
98 | 98 | {% for plan in album.plans.all %} |
99 | 99 | |
100 | 100 | <div> |
101 | - <a class="btn btn-sm {% if plan.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "routine_manager.views.action_plan" plan.id action%}" style="margin-left: 180px" >Plan: {{ plan.name }}</a> | |
101 | + <a class="btn btn-sm {% if plan.complete %}btn-success{% else %}btn-danger{% endif %}" href="{% url "action_plan" plan.id action%}" style="margin-left: 180px" >Plan: {{ plan.name }}</a> | |
102 | 102 | {% if depth_level == 4 and plan_id == plan.id %}<span class="label label-info">{{action}}ing ...</span>{% endif %} |
103 | 103 | </div> |
104 | 104 | ... | ... |
src/routine_manager/templates/routine_manager/requests_list.html
... | ... | @@ -10,10 +10,32 @@ |
10 | 10 | |
11 | 11 | <div class="row"> |
12 | 12 | <div class="col-lg-5"> |
13 | - <h3>List of Routine Requests in the database</h3> | |
13 | + <h3>Actions</h3> | |
14 | 14 | </div> |
15 | +</div> | |
15 | 16 | |
17 | +<div class="row"> | |
18 | + <div class="col-lg-5"> | |
19 | + <form action="{% url "import_request" %}" method="post" enctype="multipart/form-data"> | |
20 | + {% csrf_token %} | |
21 | + <label class="btn btn-primary btn-file"> | |
22 | + Import an XML file as a request <input type="file" onchange="this.form.submit()" name="request_file" style="display:none;"/> | |
23 | + </label> | |
24 | + </form> | |
25 | + </div> | |
26 | +</div> | |
16 | 27 | |
28 | +<div class="row" style="margin-top:10px;"> | |
29 | + <div class="col-lg-12 text-left"> | |
30 | + <a href="{% url "create_request" %}"><button class="btn btn-primary">Create manually a new | |
31 | + observation request</button></a> | |
32 | + </div> | |
33 | +</div> | |
34 | + | |
35 | +<div class="row"> | |
36 | + <div class="col-lg-5"> | |
37 | + <h3>List of Routine Requests in the database</h3> | |
38 | + </div> | |
17 | 39 | </div> |
18 | 40 | |
19 | 41 | <div class="row"> |
... | ... | @@ -40,7 +62,7 @@ |
40 | 62 | <tbody> |
41 | 63 | {% for row in requests %} |
42 | 64 | <tr> |
43 | - <td><a href="{% url "routine_manager.views.action_request" row.req.id 'view' %}">{{ row.req.name }}</a></td> | |
65 | + <td><a href="{% url "action_request" row.req.id 'view' %}">{{ row.req.name }}</a></td> | |
44 | 66 | <td>{{ row.req.created }}</td> |
45 | 67 | <td>{{ row.req.updated }}</td> |
46 | 68 | <td>{{ row.req.type }}</td> |
... | ... | @@ -50,10 +72,10 @@ |
50 | 72 | <td> |
51 | 73 | <center> |
52 | 74 | {% if row.req.submitted == False %} |
53 | - <a href="{% url "routine_manager.views.action_request" row.req.id 'edit' %}" class="btn btn-primary">Edit</a> | |
75 | + <a href="{% url "action_request" row.req.id 'edit' %}" class="btn btn-primary">Edit</a> | |
54 | 76 | {% endif %} |
55 | - <a href="{% url "routine_manager.views.action_request" row.req.id 'view' %}" class="btn btn-primary">View</a> | |
56 | - <a href="{% url "routine_manager.views.action_request" row.req.id 'delete' %}" class="btn btn-danger" | |
77 | + <a href="{% url "action_request" row.req.id 'view' %}" class="btn btn-primary">View</a> | |
78 | + <a href="{% url "action_request" row.req.id 'delete' %}" class="btn btn-danger" | |
57 | 79 | onclick="return confirm('Are you sure you want to delete this request ?')">Delete</a> |
58 | 80 | </center> |
59 | 81 | </td> |
... | ... | @@ -71,13 +93,6 @@ |
71 | 93 | |
72 | 94 | </div> |
73 | 95 | |
74 | -<div class="row"> | |
75 | - <div class="col-lg-12 text-left"> | |
76 | - <a href="{% url "routine_manager.views.create_request" %}"><button class="btn btn-primary">Create a new | |
77 | - observation request</button></a> | |
78 | - </div> | |
79 | -</div> | |
80 | - | |
81 | 96 | |
82 | 97 | |
83 | 98 | ... | ... |
src/routine_manager/templates/routine_manager/view_album.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | {% endblock %} |
6 | 6 | |
7 | 7 | {% block fields %} |
8 | - <form action="{% url "routine_manager.views.album_validate" alb.id %}" method="post" enctype="multipart/form-data"> | |
8 | + <form action="{% url "album_validate" alb.id %}" method="post" enctype="multipart/form-data"> | |
9 | 9 | {% csrf_token %} |
10 | 10 | <br> |
11 | 11 | |
... | ... | @@ -69,11 +69,11 @@ |
69 | 69 | <td> |
70 | 70 | <center> |
71 | 71 | {% if action == 'edit' %} |
72 | - <a href="{% url "routine_manager.views.action_plan" plan.id 'edit' %}" class="btn btn-primary">Edit</a> | |
73 | - <a href="{% url "routine_manager.views.action_plan" plan.id 'delete' %}" class="btn btn-danger" | |
72 | + <a href="{% url "action_plan" plan.id 'edit' %}" class="btn btn-primary">Edit</a> | |
73 | + <a href="{% url "action_plan" plan.id 'delete' %}" class="btn btn-danger" | |
74 | 74 | onclick="return confirm('Are you sure you want to delete this plan ?')">Delete</a> |
75 | 75 | {% else %} |
76 | - <a href="{% url "routine_manager.views.action_plan" plan.id 'view' %}" class="btn btn-primary"><span class="glyphicon glyphicon-e"></span></a> | |
76 | + <a href="{% url "action_plan" plan.id 'view' %}" class="btn btn-primary"><span class="glyphicon glyphicon-e"></span></a> | |
77 | 77 | {% endif %} |
78 | 78 | </center> |
79 | 79 | </td> | ... | ... |
src/routine_manager/templates/routine_manager/view_plan.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | {% endblock %} |
6 | 6 | |
7 | 7 | {% block fields %} |
8 | - <form action="{% url "routine_manager.views.plan_validate" plan.id %}" method="post" enctype="multipart/form-data"> | |
8 | + <form action="{% url "plan_validate" plan.id %}" method="post" enctype="multipart/form-data"> | |
9 | 9 | {% csrf_token %} |
10 | 10 | <br> |
11 | 11 | ... | ... |
src/routine_manager/templates/routine_manager/view_request.html
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | |
7 | 7 | |
8 | 8 | {% block fields %} |
9 | - <form action="{% url "routine_manager.views.request_validate" req.id %}" method="post" enctype="multipart/form-data"> | |
9 | + <form action="{% url "request_validate" req.id %}" method="post" enctype="multipart/form-data"> | |
10 | 10 | {% csrf_token %} |
11 | 11 | <br> |
12 | 12 | |
... | ... | @@ -67,11 +67,11 @@ |
67 | 67 | <td> |
68 | 68 | <center> |
69 | 69 | {% if action == 'edit' %} |
70 | - <a href="{% url "routine_manager.views.action_sequence" seq.id 'edit' %}" class="btn btn-primary">Edit</a> | |
71 | - <a href="{% url "routine_manager.views.action_sequence" seq.id 'delete' %}" class="btn btn-danger" | |
70 | + <a href="{% url "action_sequence" seq.id 'edit' %}" class="btn btn-primary">Edit</a> | |
71 | + <a href="{% url "action_sequence" seq.id 'delete' %}" class="btn btn-danger" | |
72 | 72 | onclick="return confirm('Are you sure you want to delete this sequence ?')">Delete</a> |
73 | 73 | {% else %} |
74 | - <a href="{% url "routine_manager.views.action_sequence" seq.id 'view' %}" class="btn btn-primary">View</a> | |
74 | + <a href="{% url "action_sequence" seq.id 'view' %}" class="btn btn-primary">View</a> | |
75 | 75 | {% endif %} |
76 | 76 | </center> |
77 | 77 | </td> | ... | ... |
src/routine_manager/templates/routine_manager/view_sequence.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | {% endblock %} |
6 | 6 | |
7 | 7 | {% block fields %} |
8 | - <form action="{% url "routine_manager.views.sequence_validate" seq.id %}" method="post" enctype="multipart/form-data"> | |
8 | + <form action="{% url "sequence_validate" seq.id %}" method="post" enctype="multipart/form-data"> | |
9 | 9 | {% csrf_token %} |
10 | 10 | <br> |
11 | 11 | |
... | ... | @@ -65,11 +65,11 @@ |
65 | 65 | <td> |
66 | 66 | <center> |
67 | 67 | {% if action == 'edit' %} |
68 | - <a href="{% url "routine_manager.views.action_album" alb.id 'edit' %}" class="btn btn-primary">Edit</a> | |
69 | - <a href="{% url "routine_manager.views.action_album" alb.id 'delete' %}" class="btn btn-danger" | |
68 | + <a href="{% url "action_album" alb.id 'edit' %}" class="btn btn-primary">Edit</a> | |
69 | + <a href="{% url "action_album" alb.id 'delete' %}" class="btn btn-danger" | |
70 | 70 | onclick="return confirm('Are you sure you want to delete this album ?')">Delete</a> |
71 | 71 | {% else %} |
72 | - <a href="{% url "routine_manager.views.action_album" alb.id 'view' %}" class="btn btn-primary">View</a> | |
72 | + <a href="{% url "action_album" alb.id 'view' %}" class="btn btn-primary">View</a> | |
73 | 73 | {% endif %} |
74 | 74 | </center> |
75 | 75 | </td> | ... | ... |
src/routine_manager/urls.py
... | ... | @@ -2,35 +2,36 @@ from django.conf.urls import url |
2 | 2 | from . import views |
3 | 3 | |
4 | 4 | urlpatterns = [ |
5 | - url(r'^$', views.requests_list), | |
6 | - url(r'^(?P<status>[-1,0,1])/(?P<message>[a-zA-Z0-9_ ]{1,100})$', views.requests_list), | |
5 | + url(r'^$', views.requests_list, name="requests_list"), | |
6 | + url(r'^(?P<status>-?\d)/(?P<message>.+)$', views.requests_list, name="requests_list"), | |
7 | 7 | |
8 | - url(r'^action_request/(?P<req_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_request), | |
9 | - url(r'^action_request/(?P<req_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>[-1,0,1])/(?P<message>[a-zA-Z0-9_ ]{1,100})$', views.action_request), | |
8 | + url(r'^action_request/(?P<req_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_request, name="action_request"), | |
9 | + url(r'^action_request/(?P<req_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>-?\d)/(?P<message>.+)$', views.action_request, name="action_request_message"), | |
10 | 10 | |
11 | - url(r'^action_sequence/(?P<seq_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_sequence), | |
12 | - url(r'^action_sequence/(?P<seq_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>[-1,0,1])/(?P<message>[a-zA-Z0-9_ ]{1,100})$', views.action_sequence), | |
11 | + url(r'^action_sequence/(?P<seq_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_sequence, name="action_sequence"), | |
12 | + url(r'^action_sequence/(?P<seq_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>-?\d)/(?P<message>.+)$', views.action_sequence, name="action_sequence_message"), | |
13 | 13 | |
14 | - url(r'^action_album/(?P<alb_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_album), | |
15 | - url(r'^action_album/(?P<alb_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>[-1,0,1])/(?P<message>[a-zA-Z0-9_ ]{1,100})$', views.action_album), | |
14 | + url(r'^action_album/(?P<alb_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_album, name="action_album"), | |
15 | + url(r'^action_album/(?P<alb_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>-?\d)/(?P<message>.+)$', views.action_album, name="action_album_message"), | |
16 | 16 | |
17 | - url(r'^action_plan/(?P<plan_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_plan), | |
18 | - url(r'^action_plan/(?P<plan_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>[-1,0,1])/(?P<message>[a-zA-Z0-9_ ]{1,100})$', views.action_plan), | |
17 | + url(r'^action_plan/(?P<plan_id>\d+)/(?P<action>[a-z_]{1,20})$', views.action_plan, name="action_plan"), | |
18 | + url(r'^action_plan/(?P<plan_id>\d+)/(?P<action>[a-z_]{1,20})/(?P<status>-?\d)/(?P<message>.+)$', views.action_plan, name="action_plan_message"), | |
19 | 19 | |
20 | - url(r'^request_validate/(?P<req_id>\d+)$', views.request_validate), | |
21 | - url(r'^sequence_validate/(?P<seq_id>\d+)$', views.sequence_validate), | |
22 | - url(r'^album_validate/(?P<alb_id>\d+)$', views.album_validate), | |
23 | - url(r'^plan_validate/(?P<plan_id>\d+)$', views.plan_validate), | |
20 | + url(r'^request_validate/(?P<req_id>\d+)$', views.request_validate, name="request_validate"), | |
21 | + url(r'^sequence_validate/(?P<seq_id>\d+)$', views.sequence_validate, name="sequence_validate"), | |
22 | + url(r'^album_validate/(?P<alb_id>\d+)$', views.album_validate, name="album_validate"), | |
23 | + url(r'^plan_validate/(?P<plan_id>\d+)$', views.plan_validate, name="plan_validate"), | |
24 | 24 | |
25 | - url(r'^create_request$', views.create_request), | |
26 | - url(r'^create_sequence/(?P<req_id>\d+)$', views.create_sequence), | |
27 | - url(r'^create_album/(?P<seq_id>\d+)$', views.create_album), | |
28 | - url(r'^create_plan/(?P<alb_id>\d+)$', views.create_plan), | |
25 | + url(r'^create_request$', views.create_request, name="create_request"), | |
26 | + url(r'^create_sequence/(?P<req_id>\d+)$', views.create_sequence, name="create_sequence"), | |
27 | + url(r'^create_album/(?P<seq_id>\d+)$', views.create_album, name="create_album"), | |
28 | + url(r'^create_plan/(?P<alb_id>\d+)$', views.create_plan, name="create_plan"), | |
29 | 29 | |
30 | - url(r'^submit_request/(?P<req_id>\d+)$', views.submit_request), | |
31 | - url(r'^unsubmit_request/(?P<req_id>\d+)$', views.unsubmit_request), | |
30 | + url(r'^submit_request/(?P<req_id>\d+)$', views.submit_request, name="submit_request"), | |
31 | + url(r'^unsubmit_request/(?P<req_id>\d+)$', views.unsubmit_request, name="unsubmit_request"), | |
32 | 32 | |
33 | - url(r'^export_request/(?P<req_id>\d+)$', views.export_request), | |
33 | + url(r'^export_request/(?P<req_id>\d+)$', views.export_request, name="export_request"), | |
34 | + url(r'^import_request$', views.import_request, name="import_request"), | |
34 | 35 | |
35 | 36 | ] |
36 | 37 | ... | ... |
src/routine_manager/validators.py
1 | 1 | from pyrosapp.models import Sequence |
2 | 2 | |
3 | +def check_plan_validity(plan): | |
4 | + """ | |
5 | + Checks if a plan is complete, and save its status in DB | |
6 | + | |
7 | + A plan is complete if His name, Filter, Duration and Nb_images are set | |
8 | + :returns : a bool equal to True if the request was submitted but incomplete | |
9 | + """ | |
10 | + | |
11 | + if plan.name == None or plan.filter == None or plan.duration <= 0 or plan.nb_images <= 0: | |
12 | + plan.complete = False | |
13 | + else: | |
14 | + plan.complete = True | |
15 | + plan.save() | |
16 | + return check_album_validity(plan.album) | |
3 | 17 | |
4 | 18 | def check_album_validity(alb): |
5 | 19 | """ |
... | ... | @@ -16,6 +30,7 @@ def check_album_validity(alb): |
16 | 30 | alb.save() |
17 | 31 | return check_sequence_validity(alb.sequence) |
18 | 32 | |
33 | + | |
19 | 34 | def check_sequence_validity(seq): |
20 | 35 | """ |
21 | 36 | Computes the sequence duration | ... | ... |
src/routine_manager/views.py
... | ... | @@ -3,10 +3,11 @@ from pyrosapp.models import * |
3 | 3 | from django.db.models import Q |
4 | 4 | from django.contrib.auth.decorators import login_required |
5 | 5 | from .forms import RequestForm, SequenceForm, AlbumForm, PlanForm |
6 | -from .validators import check_album_validity, check_sequence_validity, check_request_validity | |
6 | +from .validators import check_plan_validity, check_album_validity, check_sequence_validity, check_request_validity | |
7 | 7 | from .RequestSerializer import RequestSerializer |
8 | 8 | import scheduler |
9 | 9 | |
10 | +""" XML Export / Import utils """ | |
10 | 11 | from wsgiref.util import FileWrapper |
11 | 12 | from django.utils.encoding import smart_str |
12 | 13 | from django.http import HttpResponse |
... | ... | @@ -275,7 +276,7 @@ def action_plan(request, plan_id, action, status=0, message=""): |
275 | 276 | message = "You can't edit a submitted request" |
276 | 277 | action = "view" |
277 | 278 | |
278 | - if check_album_validity(plan.album) == True: | |
279 | + if check_plan_validity(plan) == True: | |
279 | 280 | return redirect(unsubmit_request, req_id) |
280 | 281 | if action == "edit": |
281 | 282 | form = PlanForm(instance=plan) |
... | ... | @@ -422,7 +423,7 @@ def export_request(request, req_id): |
422 | 423 | req = Request.objects.get(id=req_id) |
423 | 424 | if req.complete == False: |
424 | 425 | message = "Request must be completely valid to be serialized" |
425 | - return redirect(action_request, req_id=req_id, action="view", status=1, message=message) | |
426 | + return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) | |
426 | 427 | |
427 | 428 | file_name = "saved_requests/request" + str(req.id) + ".xml" |
428 | 429 | rs = RequestSerializer() |
... | ... | @@ -436,3 +437,29 @@ def export_request(request, req_id): |
436 | 437 | response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(os.path.basename(file_name)) # same here |
437 | 438 | |
438 | 439 | return response |
440 | + | |
441 | +@login_required | |
442 | +def import_request(request): | |
443 | + """ | |
444 | + Ask for a XML file, parse it and create a request in DB | |
445 | + Don't do anything if there is a single error into the file | |
446 | + """ | |
447 | + | |
448 | + if request.method == "POST": | |
449 | + file = request.FILES.get("request_file") | |
450 | + if file.size > 1000000: | |
451 | + status = -1 | |
452 | + message = "File is too big (more than 1 000 000 bytes)" | |
453 | + else: | |
454 | + rs = RequestSerializer() | |
455 | + message = rs.unserialize(file.read(), request.user.pyros_user) | |
456 | + if message != "": | |
457 | + status = -1 | |
458 | + else: | |
459 | + status = 1 | |
460 | + message = "Request imported successfully. Please check it before submitting for scheduling." | |
461 | + else: | |
462 | + status = -1 | |
463 | + message = "Internal error" | |
464 | + | |
465 | + return redirect(requests_list, status=status, message=message) | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +<?xml version="1.0" ?> | |
2 | +<request name="532871" scientific_program="GRB" target_type="aze"> | |
3 | + <sequence duration="1.00000000" jd1="0E-8" jd2="10.00000000" name="532871_1" target_coords="azer"> | |
4 | + <album detector="Cagire" name="532871_11"> | |
5 | + <plan duration="1.0" filter="First infrared filter" name="532871_111" nb_images="5"/> | |
6 | + </album> | |
7 | + <album detector="Visible camera" name="532871_12"> | |
8 | + <plan duration="1.0" filter="First visible filter" name="532871_121" nb_images="1"/> | |
9 | + </album> | |
10 | + </sequence> | |
11 | + <sequence duration="1.00000000" jd1="0E-8" jd2="10.00000000" name="532871_2" target_coords="azerty"> | |
12 | + <album detector="Cagire" name="532871_21"> | |
13 | + <plan duration="1.0" filter="Second infrared filter" name="532871_211" nb_images="3"/> | |
14 | + </album> | |
15 | + </sequence> | |
16 | +</request> | ... | ... |
src/scheduler/urls.py
... | ... | @@ -5,6 +5,6 @@ from django.conf import settings |
5 | 5 | from django.conf.urls.static import static |
6 | 6 | |
7 | 7 | urlpatterns = [ |
8 | - url(r'^$', views.current_schedule), | |
9 | - url(r'^simulation$', views.schedule_simulation), | |
8 | + url(r'^$', views.current_schedule, name="current_schedule"), | |
9 | + url(r'^simulation$', views.schedule_simulation, name="schedule_simulation"), | |
10 | 10 | ] |
11 | 11 | \ No newline at end of file | ... | ... |
src/templates/base.html
... | ... | @@ -47,23 +47,23 @@ |
47 | 47 | <div class="collapse navbar-collapse navbar-ex1-collapse"> |
48 | 48 | |
49 | 49 | <ul class="nav navbar-nav side-nav"> |
50 | - <li><a href="{% url "scheduler.views.schedule_simulation" %}">Schedule</a></li> | |
51 | - <li><a href="{% url "dashboard.views.system" %}">System</a></li> | |
52 | - <li><a href="{% url "alert_manager.views.alerts_list" %}">Alerts</a></li> | |
53 | - <li><a href="{% url "routine_manager.views.requests_list" %}">Routines</a></li> | |
54 | - <li><a href="{% url "dashboard.views.weather" %}">Weather</a></li> | |
55 | - <li><a href="{% url "dashboard.views.site" %}">Site</a></li> | |
56 | - <li><a href="{% url "dashboard.views.devices" %}">Devices</a></li> | |
57 | - <li><a href="{% url "dashboard.views.users" %}">Users</a></li> | |
50 | + <li><a href="{% url "schedule_simulation" %}">Schedule</a></li> | |
51 | + <li><a href="{% url "system" %}">System</a></li> | |
52 | + <li><a href="{% url "alerts_list" %}">Alerts</a></li> | |
53 | + <li><a href="{% url "requests_list" %}">Routines</a></li> | |
54 | + <li><a href="{% url "weather" %}">Weather</a></li> | |
55 | + <li><a href="{% url "site" %}">Site</a></li> | |
56 | + <li><a href="{% url "devices" %}">Devices</a></li> | |
57 | + <li><a href="{% url "users" %}">Users</a></li> | |
58 | 58 | </ul> |
59 | 59 | |
60 | 60 | <ul class="nav navbar-nav navbar-right navbar-user"> |
61 | 61 | |
62 | 62 | <li class="dropdown alerts-dropdown"> |
63 | - <a href="{% url "user_manager.views.profile" %}"><i class="fa fa-user"></i> {{ user.first_name }} <b class="caret"></b></a> | |
63 | + <a href="{% url "profile" %}"><i class="fa fa-user"></i> {{ user.first_name }} <b class="caret"></b></a> | |
64 | 64 | </li> |
65 | 65 | <li class="dropdown user-dropdown"> |
66 | - <a href="{% url "user_manager.views.user_logout" %}"><i class="fa fa-power-off"></i> Log Out</a> | |
66 | + <a href="{% url "user_logout" %}"><i class="fa fa-power-off"></i> Log Out</a> | |
67 | 67 | </li> |
68 | 68 | </ul> |
69 | 69 | ... | ... |
src/user_manager/templates/user_manager/home_login.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | |
6 | 6 | |
7 | 7 | <div class="form-group"> |
8 | - <form action=" {% url "user_manager.views.login_validation" %}" method="post" enctype="multipart/form-data"> | |
8 | + <form action=" {% url "login_validation" %}" method="post" enctype="multipart/form-data"> | |
9 | 9 | {% csrf_token %} |
10 | 10 | {% if next %} |
11 | 11 | <input class="form-control" type="hidden" name="next" value="{{ next }}" /> |
... | ... | @@ -29,7 +29,7 @@ |
29 | 29 | </div> |
30 | 30 | <div class="row"> |
31 | 31 | <input class="btn btn-primary" type="submit" value="Log In" /> |
32 | - <a href="{% url "user_manager.views.create_user" %}" class="btn btn-primary">Subscription form</a> | |
32 | + <a href="{% url "create_user" %}" class="btn btn-primary">Subscription form</a> | |
33 | 33 | </div> |
34 | 34 | </div> |
35 | 35 | <div class="row"> | ... | ... |
src/user_manager/templates/user_manager/home_user_creation.html
... | ... | @@ -7,7 +7,7 @@ |
7 | 7 | <div class="form-group"> |
8 | 8 | |
9 | 9 | |
10 | - <form action="{% url "user_manager.views.user_signup_validation" %}" method="post" enctype="multipart/form-data"> | |
10 | + <form action="{% url "user_signup_validation" %}" method="post" enctype="multipart/form-data"> | |
11 | 11 | {% csrf_token %} |
12 | 12 | <div class="col-lg-3 text-left" > |
13 | 13 | <p></p> | ... | ... |
src/user_manager/urls.py
... | ... | @@ -2,9 +2,9 @@ from django.conf.urls import url |
2 | 2 | from . import views |
3 | 3 | |
4 | 4 | urlpatterns = [ |
5 | - url(r'^create$', views.create_user), | |
6 | - url(r'^creation_validate$', views.user_signup_validation), | |
7 | - url(r'^login$', views.login_validation), | |
8 | - url(r'^profile$', views.profile), | |
9 | - url(r'^logout$', views.user_logout), | |
5 | + url(r'^create$', views.create_user, name="create_user"), | |
6 | + url(r'^creation_validate$', views.user_signup_validation, name="user_signup_validation"), | |
7 | + url(r'^login$', views.login_validation, name="login_validation"), | |
8 | + url(r'^profile$', views.profile, name="profile"), | |
9 | + url(r'^logout$', views.user_logout, name="user_logout"), | |
10 | 10 | ] | ... | ... |