]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/blob - logs/index.php
Logs: show search pane (on desktop)
[irc/unrealircd/unrealircd-webpanel.git] / logs / index.php
1 <?php
2 require_once "../inc/common.php";
3 require_once "../inc/header.php";
4 ?>
5 <h4>Log viewer</h4>
6
7 <!-- The log table -->
8 <form method="post">
9 <table id="data_list" class="table-striped display nowrap" style="width:100%">
10 <thead class="table-primary">
11 <th scope="col">Time</th>
12 <th scope="col">Level</th>
13 <th scope="col">Subsystem</th>
14 <th scope="col">Event</th>
15 <th scope="col">Message</th>
16 </thead>
17 </table>
18 </form>
19
20 <!-- View log entry -->
21 <div class="modal" id="view_log_entry" tabindex="-1" role="dialog" aria-labelledby="confirmModalCenterTitle" aria-hidden="true">
22 <div class="modal-dialog modal-xl" role="document">
23 <form method="post">
24 <div class="modal-content">
25 <div class="modal-header">
26 <h5 class="modal-title" id="view_log_entry_title">View log entry</h5>
27 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
28 <span aria-hidden="true">&times;</span></button>
29 </div>
30 <div class="modal-body">
31 <ul class="nav nav-tabs" role="tablist">
32 <li class="nav-item" role="presentation"><a class="nav-link active" href="#event_pane" aria-controls="event_pane" role="tab" data-toggle="tab">Log entry</a></li>
33 <li class="nav-item" role="presentation"><a class="nav-link" href="#json_pane" aria-controls="json_pane" role="tab" data-toggle="tab">JSON</a></li>
34 </ul>
35
36 <div class="tab-content">
37 <div class="tab-pane show active" id="event_pane">
38 <table class="table-sm table-responsive caption-top table-hover">
39 <tbody>
40 <tr><td>Time</td><td id="view_log_entry_time"></td></tr>
41 <tr><td>Level</td><td id="view_log_entry_level"></td></tr>
42 <tr><td>Subsystem</td><td id="view_log_entry_subsystem"></td></tr>
43 <tr><td>Event</td><td id="view_log_entry_event"></td></tr>
44 <tr><td>Message</td><td id="view_log_entry_message" class="tdwrap"></td></tr>
45 </tbody>
46 </table>
47 </div>
48 <div class="tab-pane" id="json_pane">
49 <p class="card-text tdwrap" id="view_log_entry_json"></p>
50 </div>
51 </div>
52 </div>
53
54 <div class="modal-footer">
55 <!-- do we want a button at all? -->
56 </div>
57 </div>
58 </form>
59 </div>
60 </div>
61
62
63 <script src="../js/json-formatter.umd.js"></script>
64 <script>
65 let data_list_table = null;
66
67 function level2color(level)
68 {
69 if (level == 'info')
70 return 'green';
71 if (level == 'warn')
72 return 'orange';
73 if ((level == 'error') || (level == 'fatal'))
74 return 'red';
75 }
76
77 function log_colorizer(data, type, row)
78 {
79 if (type == 'display')
80 {
81 var color = level2color(row['Level']);
82 data = '<span style="color: '+color+'">' + data + '</span>';
83 }
84 return data;
85 }
86
87 function log_timestamp(data, type, row)
88 {
89 if (type == 'display')
90 {
91 return moment.utc(data).local().format('HH:mm:ss');
92 }
93 return data;
94 }
95
96 function resize_check()
97 {
98 if (window.innerWidth < 900)
99 {
100 data_list_table.column(1).visible(false); // level
101 data_list_table.column(2).visible(false); // subsystem
102 data_list_table.column(3).visible(false); // event
103 } else
104 if (window.innerWidth < 1250)
105 {
106 data_list_table.column(1).visible(true); // level
107 data_list_table.column(2).visible(false); // subsystem
108 data_list_table.column(3).visible(false); // event
109 } else
110 if (window.innerWidth < 1450)
111 {
112 data_list_table.column(1).visible(true); // level
113 data_list_table.column(2).visible(true); // subsystem
114 data_list_table.column(3).visible(false); // event
115 } else
116 {
117 data_list_table.column(1).visible(true); // level
118 data_list_table.column(2).visible(true); // subsystem
119 data_list_table.column(3).visible(true); // event
120 }
121 data_list_table.rows().invalidate('data').draw(false);
122 }
123
124 function log_text(data, type, row)
125 {
126 var esc = function (t) {
127 return ('' + t)
128 .replace(/&/g, '&amp;')
129 .replace(/</g, '&lt;')
130 .replace(/>/g, '&gt;')
131 .replace(/"/g, '&quot;');
132 };
133
134 if (type != 'display')
135 return data;
136
137 var color = level2color(row['Level']);
138 var cutoff;
139 if (window.innerWidth < 500)
140 cutoff = 35;
141 else if (window.innerWidth < 1000)
142 cutoff = 75;
143 else if (window.innerWidth < 1750)
144 cutoff = 100
145 else
146 cutoff = 125;
147
148 if (data.length > cutoff)
149 {
150 // stolen from ellipsis
151 var shortened = data.substr(0, cutoff - 1);
152 data = '<span class="ellipsis" style="color: '+color+'" title="' +
153 esc(data) +
154 '">' +
155 shortened +
156 '&#8230;</span>';
157 } else {
158 // otherwise just like log_colorizer...
159 data = '<span style="color: '+color+'">' + data + '</span>';
160 }
161 return data;
162 }
163
164 $(document).ready( function () {
165 args = {
166 //'responsive': true,
167 'fixedHeader': {
168 header: true,
169 headerOffset: 53
170 },
171 'columns': [
172 { 'data': 'Time', 'responsivePriority': 1, 'render': log_timestamp, 'className':'virtuallink' },
173 { 'data': 'Level', 'responsivePriority': 3, 'render': log_colorizer },
174 { 'data': 'Subsystem', 'responsivePriority': 4, 'render': log_colorizer },
175 { 'data': 'Event', 'responsivePriority': 5, 'render': log_colorizer },
176 //{ 'data': 'Message', 'responsivePriority': 2, 'render': DataTable.render.ellipsis(100, false) },
177 { 'data': 'Message', 'responsivePriority': 2, 'render': log_text },
178 { 'data': 'Raw', 'visible': false, 'searchable': false },
179 ],
180 'pageLength':100,
181 'order':[[0,'desc']],
182 };
183
184 /* Only show filter pane on desktop */
185 if (window.innerWidth > 800)
186 {
187 args['dom'] = 'Pfrtip';
188 args['searchPanes'] = {
189 'initCollapsed': 'true',
190 'columns': [1,2,3],
191 'dtOpts': {
192 select: { style: 'multi'},
193 order: [[ 1, "desc" ]]
194 },
195 }
196 }
197
198 data_list_table = $('#data_list').DataTable(args);
199
200 resize_check();
201 window.addEventListener('resize', resize_check);
202
203 StartLogStream('<?php echo get_config('base_url'); ?>api/log.php');
204
205 $('#data_list').on( 'click', 'td', function () {
206 view_log_entry(this);
207 } );
208 } );
209
210 function view_log_entry(e)
211 {
212 var data = data_list_table.row(e).data();
213 $('#view_log_entry_time').html('<code>' + data['Time'] + '</code>')
214 $('#view_log_entry_level').html('<code>' + data['Level'] + '</code>')
215 $('#view_log_entry_subsystem').html('<code>' + data['Subsystem'] + '</code>')
216 $('#view_log_entry_event').html('<code>' + data['Event'] + '</code>')
217 $('#view_log_entry_message').html('<pre class="tdwrap">' + data['Message'] + '</pre>')
218 j = new JSONFormatter(data['Raw'], 99);
219 $('#view_log_entry_json').html(j.render());
220 $('#view_log_entry').modal('show');
221 }
222 </script>
223
224 <?php require_once '../inc/footer.php'; ?>