Revision 693e96f1
Ajout du refresh dans la toolbar et correction CSS / W3C
git-svn-id: https://vigilo-dev.si.c-s.fr/svn@538 b22e2e97-25c9-44ff-b637-2e5ceca36478
vigiboard/config/middleware.py | ||
---|---|---|
35 | 35 |
|
36 | 36 |
|
37 | 37 |
""" |
38 |
|
|
38 |
# chargement de la config |
|
39 | 39 |
for i in vigiboard_config: |
40 | 40 |
app_conf[i] = vigiboard_config[i] |
41 | 41 |
|
42 | 42 |
# on cré l'application de base |
43 | 43 |
app = make_base_app(global_conf, full_stack=True, **app_conf) |
44 |
|
|
44 |
|
|
45 | 45 |
# on rajoute le path public de l'application |
46 | 46 |
import vigiboard |
47 | 47 |
app = Cascade([ |
vigiboard/config/vigiboard.py | ||
---|---|---|
33 | 33 |
# - %(host)s |
34 | 34 |
# - %(service)s |
35 | 35 |
# - %(tt)s |
36 |
'vigiboard_links.tt' : 'http://example4.com/%(idevent)d/%(tt)s' |
|
36 |
'vigiboard_links.tt' : 'http://example4.com/%(idevent)d/%(tt)s', |
|
37 |
|
|
38 |
# Taille de police par défaut |
|
39 |
'vigiboard_font.size' : '10' |
|
37 | 40 |
} |
vigiboard/controllers/root.py | ||
---|---|---|
5 | 5 |
import tg |
6 | 6 |
|
7 | 7 |
from tg import config, expose, flash, require, request, redirect, \ |
8 |
validate, tmpl_context |
|
8 |
validate, tmpl_context, session
|
|
9 | 9 |
|
10 | 10 |
from tw.forms import validators |
11 | 11 |
|
... | ... | |
71 | 71 |
@param output: Idem que host mais sur le text explicatif |
72 | 72 |
@param trouble_ticket: Idem que host mais sur les tickets attribués |
73 | 73 |
""" |
74 |
|
|
74 | 75 |
if page < 1 : |
75 | 76 |
page = 1 |
76 | 77 |
|
77 | 78 |
events = VigiboardRequest() |
78 | 79 |
|
79 |
search = 0
|
|
80 |
search = {'host':'', 'service':'', 'output':'', 'tt':''}
|
|
80 | 81 |
# Application des filtres si nécessaire |
81 | 82 |
if host : |
82 |
search = 1
|
|
83 |
search['host'] = host
|
|
83 | 84 |
events.add_filter(Events.hostname.like('%%%s%%' % host)) |
84 | 85 |
if service : |
85 |
search = 1
|
|
86 |
search['service'] = service
|
|
86 | 87 |
events.add_filter(Events.servicename.like('%%%s%%' % service)) |
87 | 88 |
if output : |
88 |
search = 1
|
|
89 |
search['output'] = output
|
|
89 | 90 |
events.add_filter(Events.output.like('%%%s%%' % output)) |
90 | 91 |
if trouble_ticket : |
91 |
search = 1
|
|
92 |
search['tt'] = trouble_ticket
|
|
92 | 93 |
events.add_filter(Events.trouble_ticket.like( |
93 | 94 |
'%%%s%%' % trouble_ticket)) |
94 | 95 |
|
... | ... | |
104 | 105 |
|
105 | 106 |
events.format_events(id_first_row, id_last_row) |
106 | 107 |
events.generate_tmpl_context() |
107 |
|
|
108 | 108 |
return dict( |
109 | 109 |
events = events.events, |
110 | 110 |
id_first_row = id_first_row + 1, |
... | ... | |
117 | 117 |
hist_error = False, |
118 | 118 |
plugin_context = events.context_fct, |
119 | 119 |
search = search |
120 |
|
|
120 | 121 |
) |
121 |
|
|
122 |
|
|
122 | 123 |
@validate(validators={'idevent':validators.Int(not_empty=True)}, |
123 | 124 |
error_handler=process_form_errors) |
124 | 125 |
@expose('json') |
... | ... | |
132 | 133 |
|
133 | 134 |
@param id: identifiant de l'évènement |
134 | 135 |
""" |
135 |
|
|
136 |
|
|
136 | 137 |
# Obtention de données sur l'évènement et sur son historique |
137 | 138 |
events = DBSession.query(Events.severity, Events.idevent, |
138 | 139 |
Events.hostname, Events.servicename |
139 | 140 |
).join(( HostGroups , Events.hostname == HostGroups.hostname ) |
140 | 141 |
).filter(HostGroups.groupname.in_(get_user_groups()) |
141 | 142 |
).filter(Events.idevent == idevent)[0] |
142 |
|
|
143 | 143 |
initial_state = DBSession.query(EventHistory |
144 | 144 |
).filter(EventHistory.idevent == idevent |
145 | 145 |
).order_by(asc(EventHistory.timestamp) |
146 | 146 |
).order_by(asc(EventHistory.type_action)) |
147 |
|
|
148 | 147 |
if initial_state.count() > 0 : |
149 |
initial_state = initial_state[0].value |
|
148 |
for i in initial_state: |
|
149 |
if i.value != '' and i.value is not None: |
|
150 |
initial_state = i.value |
|
151 |
break |
|
150 | 152 |
else : |
151 | 153 |
initial_state = 0 |
152 | 154 |
|
... | ... | |
204 | 206 |
history = events.hist, |
205 | 207 |
hist_error = True, |
206 | 208 |
plugin_context = events.context_fct, |
207 |
search = 0
|
|
209 |
search = {'host':None,'service':None,'output':None,'tt':None}
|
|
208 | 210 |
) |
209 | 211 |
|
210 | 212 |
@validate(validators={'host':validators.NotEmpty(), |
... | ... | |
245 | 247 |
history = events.hist, |
246 | 248 |
hist_error = True, |
247 | 249 |
plugin_context = events.context_fct, |
248 |
search = 0
|
|
250 |
search = {'host':None,'service':None,'output':None,'tt':None}
|
|
249 | 251 |
) |
250 | 252 |
|
251 | 253 |
@validate(validators={ |
... | ... | |
330 | 332 |
return p.controller(*arg,**krgv) |
331 | 333 |
except: |
332 | 334 |
raise |
335 |
|
|
336 |
@validate(validators={"fontsize":validators.Int()}, error_handler=process_form_errors) |
|
337 |
@expose('json') |
|
338 |
def set_fontsize(self,fontsize): |
|
339 |
try: |
|
340 |
session['fontsize'] = fontsize |
|
341 |
session.save() |
|
342 |
return dict(ret='ok') |
|
343 |
except: |
|
344 |
return dict(ret='fail') |
|
345 |
|
|
346 |
@validate(validators={"refresh":validators.Int()}, error_handler=process_form_errors) |
|
347 |
@expose('json') |
|
348 |
def set_refresh(self,refresh): |
|
349 |
try: |
|
350 |
session['refresh'] = refresh |
|
351 |
session.save() |
|
352 |
return dict(ret='ok') |
|
353 |
except: |
|
354 |
return dict(ret='fail') |
|
355 |
|
vigiboard/controllers/vigiboardrequest.py | ||
---|---|---|
274 | 274 |
|
275 | 275 |
# Liste des éléments pour la tête du tableau |
276 | 276 |
|
277 |
lst_title = [['',{}], [_('Date')+ '<span style="font-weight:normal">' + _('<br />[Duration]') + '</span>', {'style':'text-align:left'}], ['#',{'title':_('Occurrence')}], [_('Host'),{'style':'text-align:left'}],
|
|
277 |
lst_title = [['',{}], [_('Date')+ '<span style="font-weight:normal">' + _('<br />[Duration]') + '</span>', {'style':'text-align:left'}], ['#',{'title':_('Nombre d\'occurrences')}], [_('Host'),{'style':'text-align:left'}],
|
|
278 | 278 |
[_('Service Type<br />Service Name'),{'style':'text-align:left'}], [_('Output'),{'style':'text-align:left'}]] |
279 | 279 |
lst_title.extend([[plug.name,plug.style] for plug in self.plugin]) |
280 | 280 |
lst_title.extend([[_('[TT]'),{'title':_('Trouble Ticket')}], ['',{}]]) |
... | ... | |
350 | 350 |
).filter(EventHistory.idevent.in_(self.idevents) |
351 | 351 |
).order_by(desc(EventHistory.timestamp) |
352 | 352 |
).order_by(desc(EventHistory.idhistory)) |
353 |
print history |
|
354 | 353 |
if history.count() == 0: |
355 |
self.hist = [] |
|
354 |
self.hist = {} |
|
355 |
for i in self.idevents: |
|
356 |
self.hist[i] = [] |
|
356 | 357 |
return |
357 | 358 |
hists = {} |
358 | 359 |
i = 0 |
vigiboard/public/css/vigiboard_style.css | ||
---|---|---|
14 | 14 |
border-collapse:collapse; |
15 | 15 |
margin-bottom: 10px; |
16 | 16 |
} |
17 |
.table_top tr td { |
|
18 |
padding: 4px; |
|
19 |
} |
|
20 |
|
|
21 |
.history_table { |
|
22 |
width: 100%; |
|
23 |
margin-bottom: 30px; |
|
24 |
} |
|
25 |
.history_table thead { |
|
26 |
background-color:#F8F8F8; |
|
27 |
font-weight:bold; |
|
28 |
} |
|
29 |
|
|
30 |
|
|
17 | 31 |
.vigitable { |
18 | 32 |
width: 100%; |
19 | 33 |
border-collapse: collapse; |
... | ... | |
25 | 39 |
|
26 | 40 |
.vigitable thead tr td { |
27 | 41 |
padding: 0px; |
28 |
color:white; |
|
29 | 42 |
} |
30 | 43 |
|
31 | 44 |
.vigitable thead tr th { |
32 | 45 |
padding: 4px 10px; |
33 | 46 |
background-color: #EBECF0; |
34 | 47 |
font-weight: bold; |
35 |
border: none;
|
|
48 |
border: solid 1px #EBECF0;
|
|
36 | 49 |
} |
37 | 50 |
|
38 | 51 |
.vigitable tbody tr { |
... | ... | |
139 | 152 |
clear:both; |
140 | 153 |
} |
141 | 154 |
|
155 |
.refresh_select { |
|
156 |
background-color: #DBEAF5; |
|
157 |
border: 1px solid #4682B4; |
|
158 |
} |
|
159 |
|
|
160 |
.refresh_button { |
|
161 |
background-color: red; |
|
162 |
color: white |
|
163 |
} |
|
164 |
|
vigiboard/templates/vigiboard.html | ||
---|---|---|
12 | 12 |
<link rel="stylesheet" type="text/css" href="${tg.url('/css/vigiboard_style.css')}" /> |
13 | 13 |
</head> |
14 | 14 |
|
15 |
<body> |
|
15 |
<body style="font-size:${tg.session.get('fontsize',tg.config['vigiboard_font.size'])}px">
|
|
16 | 16 |
|
17 | 17 |
<table class="table_top" summary="Barre Outils"> |
18 | 18 |
<tr> |
... | ... | |
21 | 21 |
<a py:if="tg.config['vigiboard_links.logo'] == ''" href="${tg.url('/')}"><img alt="logo" title="Logo" src="${tg.url('/images/vigilo.png')}" style="width:58px;"/></a> |
22 | 22 |
v${tg.config['vigiboard_version']}</td> |
23 | 23 |
<td style="text-align: center"> |
24 |
<span py:if="search == 1" style="color:rgb(70, 130, 180)">
|
|
24 |
<span py:if="search['host'] != '' or search['service'] != '' or search['output'] != '' or search['tt'] != ''" style="color:rgb(70, 130, 180)">
|
|
25 | 25 |
Mode recherche, <a href="${tg.url('/')}" style="color:rgb(70, 130, 180); text-decoration: underline;">cliquer ici</a> pour revenir au mode initial. |
26 | 26 |
</span> |
27 | 27 |
</td> |
28 |
<td style="width: 20%;text-align: right;"><a href="${tg.url('/')}"><img alt="accueil" title="Accueil" src="${tg.url('/images/home.gif')}" /></a> |
|
28 |
<td style="width: 200px;text-align: right;"> |
|
29 |
<select id="refresh_time" class="refresh_select"> |
|
30 |
<option value="0">Never</option> |
|
31 |
<option value="30000">30 Secondes</option> |
|
32 |
<option value="60000">1 Minute</option> |
|
33 |
<option value="300000">5 Minutes</option> |
|
34 |
<option value="600000">10 Minutes</option> |
|
35 |
</select> |
|
36 |
<input type="button" id="refresh_button" class="refresh_button" onclick="javascript:change_refresh($('#refresh_time').val())" value="[Start]" /> |
|
37 |
</td> |
|
38 |
<td style="width: 100px;text-align: right;"> |
|
39 |
<a href="javascript:change_fontsize(5)"><img alt="Default font size" title="Default font size" src="${tg.url('/images/icn_text_sm.png')}" /></a> |
|
40 |
<a href="javascript:change_fontsize(10)"><img alt="Medium font size" title="Medium font size" src="${tg.url('/images/icn_text_md.png')}" /></a> |
|
41 |
<a href="javascript:change_fontsize(25)"><img alt="Large font size" title="Large font size" src="${tg.url('/images/icn_text_lg.png')}" /></a> |
|
42 |
</td> |
|
43 |
<td style="width: 100px;text-align: right;"> |
|
44 |
<a href="${tg.url('/')}"> |
|
45 |
<img alt="accueil" title="Accueil" src="${tg.url('/images/home.gif')}" /> |
|
46 |
</a> |
|
29 | 47 |
<a id="SearchLien" href="javascript:vigiboard_searchdialog()"> |
30 | 48 |
<img src="${tg.url('/images/filter.png')}" alt="filtrer" title="Filtrer"/> |
31 |
</a>
|
|
49 |
</a> |
|
32 | 50 |
</td> |
33 | 51 |
</tr> |
34 | 52 |
</table> |
... | ... | |
37 | 55 |
<div py:if="flash" py:content="XML(flash)" /> |
38 | 56 |
</py:with> |
39 | 57 |
<div class="main_content"> |
40 |
${event_table(events,page,pages,id_first_row,id_last_row,total_row,event_edit_status_options,history,hist_error)} |
|
58 |
${event_table(events,page,pages,id_first_row,id_last_row,total_row,event_edit_status_options,history,hist_error,search)}
|
|
41 | 59 |
</div> |
42 | 60 |
<script type="text/javascript"> |
43 | 61 |
$("#flash").show("slow",function(){ |
44 | 62 |
setTimeout('$("#flash").hide("slow")',5000); |
45 | 63 |
}); |
64 |
function change_fontsize(size) { |
|
65 |
document.body.style.fontSize = size + "px"; |
|
66 |
$.getJSON("${tg.url('/set_fontsize')}",{'fontsize':size},function(json){ |
|
67 |
if ( json.ret == 'fail' ) |
|
68 |
alert("Can't save preferences"); |
|
69 |
}) |
|
70 |
} |
|
71 |
var refresh_timeout; |
|
72 |
function change_refresh_rate (timeout) { |
|
73 |
if ( timeout != 0 ) { |
|
74 |
if ( refresh_timeout ) { |
|
75 |
clearTimeout(refresh_timeout); |
|
76 |
refresh_timeout = null; |
|
77 |
$('#refresh_time').removeAttr('disabled'); |
|
78 |
$('#refresh_button').attr('value','[Start]'); |
|
79 |
} else { |
|
80 |
refresh_timeout = setTimeout('window.location.reload(true)',timeout); |
|
81 |
$('#refresh_time').attr("disabled", "disabled"); |
|
82 |
$('#refresh_button').attr('value','[Stop]'); |
|
83 |
} |
|
84 |
} |
|
85 |
} |
|
86 |
function change_refresh(timeout) { |
|
87 |
$.getJSON("${tg.url('/set_refresh')}",{'refresh':timeout},function(json){}); |
|
88 |
change_refresh_rate(timeout); |
|
89 |
} |
|
90 |
<py:if test="tg.session.get('refresh','0') != '0'"> |
|
91 |
change_refresh_rate(${tg.session.get('refresh',0)}); |
|
92 |
</py:if> |
|
46 | 93 |
</script> |
47 | 94 |
</body> |
48 | 95 |
</html> |
vigiboard/templates/vigiboard_event_table.html | ||
---|---|---|
5 | 5 |
|
6 | 6 |
<xi:include href="vigiboard_history_table.html" /> |
7 | 7 |
|
8 |
<py:def function="event_table(events,page,pages,id_first_row,id_last_row,total_row,edit_event_status_options,history,hist_error)"> |
|
8 |
<py:def function="event_table(events,page,pages,id_first_row,id_last_row,total_row,edit_event_status_options,history,hist_error,search)">
|
|
9 | 9 |
<?python from genshi import HTML ?> |
10 | 10 |
|
11 | 11 |
<py:if test="len(events) > 1"> |
... | ... | |
14 | 14 |
<thead> |
15 | 15 |
<tr > |
16 | 16 |
<td style="width:26px;border-right: solid 1px #4682b4"> |
17 |
<a py:if="page > pages[0]" href="${tg.url('/%d' % (page-1))}"><img src="${tg.url('/images/fleche_up.png')}" alt="up" title="Page précédente"/></a>
|
|
18 |
<img py:if="page == pages[0]" src="${tg.url('/images/fleche_up.png')}" alt="up" title="Page précédente" />
|
|
17 |
<a py:if="page > pages[0]" href="${tg.url('/%d' % (page-1))}"><img src="${tg.url('/images/fleche_up.png')}" alt="Précédent" title="Page précédente"/></a>
|
|
18 |
<img py:if="page == pages[0]" src="${tg.url('/images/fleche_up.png')}" alt="Précédent" title="Page précédente" />
|
|
19 | 19 |
</td> |
20 |
<td colspan="${8+len(events[1][6])}" style="background-color: #4682b4" >Showing rows ${id_first_row} to ${id_last_row} of ${total_row}<br /> |
|
20 |
<td colspan="${8+len(events[1][6])}" style="color: white;background-color: #4682b4" >Showing rows ${id_first_row} to ${id_last_row} of ${total_row}<br />
|
|
21 | 21 |
Pages <py:for each="p in pages"> |
22 | 22 |
<a py:if="p != page" href="${tg.url('/%d' % p)}" py:content="p" /> |
23 | 23 |
<span py:if="p == page" py:replace="p" /> |
24 | 24 |
</py:for> |
25 | 25 |
</td> |
26 | 26 |
<td style="width:26px;border-left: solid 1px #4682b4"> |
27 |
<a py:if="pages[-1] > page" href="${tg.url('/%d' % (page+1))}"><img src="${tg.url('/images/fleche_down.png')}" alt="down" title="Page suivante"/></a>
|
|
28 |
<img py:if="page == pages[-1]" src="${tg.url('/images/fleche_down.png')}" alt="down" title="Page suivante" />
|
|
27 |
<a py:if="pages[-1] > page" href="${tg.url('/%d' % (page+1))}"><img src="${tg.url('/images/fleche_down.png')}" alt="Suivante" title="Page suivante"/></a>
|
|
28 |
<img py:if="page == pages[-1]" src="${tg.url('/images/fleche_down.png')}" alt="" title="Page suivante" /> |
|
29 | 29 |
</td> |
30 | 30 |
</tr> |
31 | 31 |
|
... | ... | |
33 | 33 |
<py:for each="(pname,pstyle) in events[0]"> |
34 | 34 |
<th style="padding: 5px;" py:attrs="pstyle">${HTML(pname)}</th> |
35 | 35 |
</py:for> |
36 |
<th style="width:26px;padding: 0px;"><a class="Edit_EventsLien" href="javascript:vigiboard_edit_eventdialog('all')"><img src="${tg.url('/images/icon_page_edit.png')}" alt="edit_all" title="Editer tous les évènements sélectionnés"/></a></th>
|
|
36 |
<th style="width:26px;padding: 0px;"><a class="Edit_EventsLien" href="javascript:vigiboard_edit_eventdialog('all')"><img src="${tg.url('/images/icon_page_edit.png')}" alt="Edit all selected events" title="Edit all selected events"/></a></th>
|
|
37 | 37 |
<th style="padding:0px;"><input title="Sélectioner tout" id="vigiboard_checkall_checkbox" type="checkbox" onclick="javascript:vigiboard_checkall()" /></th> |
38 | 38 |
</tr> |
39 | 39 |
</thead> |
... | ... | |
109 | 109 |
$('#Edit_EventsDialog').dialog('open'); |
110 | 110 |
} |
111 | 111 |
function vigiboard_searchdialog() { |
112 |
$('#search_form_host').attr('value',''); |
|
113 |
$('#search_form_service').attr('value',''); |
|
114 |
$('#search_form_output').attr('value',''); |
|
115 |
$('#search_form_trouble_ticket').attr('value', ''); |
|
112 |
$('#search_form_host').attr('value','${search['host']}');
|
|
113 |
$('#search_form_service').attr('value','${search['service']}');
|
|
114 |
$('#search_form_output').attr('value','${search['output']}');
|
|
115 |
$('#search_form_trouble_ticket').attr('value', '${search['tt']}');
|
|
116 | 116 |
$('#SearchDialog').dialog('open'); |
117 | 117 |
} |
118 | 118 |
function vigiboard_checkall() { |
... | ... | |
134 | 134 |
|
135 | 135 |
</script> |
136 | 136 |
|
137 |
<div id="HistoryDialog"> |
|
137 |
<div style="display:none" id="HistoryDialog">
|
|
138 | 138 |
Initial State: <span id="HistoryDialog_initial_state" /><br /> |
139 | 139 |
Current State: <span id="HistoryDialog_current_state" /><br /> |
140 | 140 |
<ul> |
... | ... | |
146 | 146 |
</ul> |
147 | 147 |
</div> |
148 | 148 |
|
149 |
<div id="Edit_EventsDialog"> |
|
149 |
<div style="display:none" id="Edit_EventsDialog">
|
|
150 | 150 |
${tmpl_context.edit_event_form()} |
151 | 151 |
</div> |
152 |
<div id="SearchDialog"> |
|
152 |
<div style="display:none" id="SearchDialog">
|
|
153 | 153 |
${tmpl_context.search_form()} |
154 | 154 |
</div> |
155 | 155 |
|
... | ... | |
185 | 185 |
</tbody> |
186 | 186 |
</table> |
187 | 187 |
${tmpl_context.searchdialog} |
188 |
<div id="SearchDialog"> |
|
188 |
<div style="display:none" id="SearchDialog">
|
|
189 | 189 |
${tmpl_context.search_form()} |
190 | 190 |
</div> |
191 | 191 |
<script type="text/javascript"> |
vigiboard/templates/vigiboard_history_table.html | ||
---|---|---|
9 | 9 |
</p> |
10 | 10 |
|
11 | 11 |
<py:if test="history and len(history) > 0"> |
12 |
<table style="width: 100%;margin-bottom: 30px;" summary="Historique de l'élément">
|
|
12 |
<table class="history_table" summary="Historique de l'élément">
|
|
13 | 13 |
<thead> |
14 |
<tr style="background-color:#F8F8F8;font-weight:bold">
|
|
14 |
<tr> |
|
15 | 15 |
<td>Time</td> |
16 | 16 |
<td>User</td> |
17 | 17 |
<td>Type</td> |
Also available in: Unified diff