4
4
class =" log-card"
5
5
:collapsible =" true"
6
6
:collapsed =" true"
7
+ @expanded =" onCardExpand"
7
8
>
8
- <template #actions >
9
+ <template #actions = " { collapsed } " >
9
10
<openwb-base-avatar
10
- class =" bg-success clickable"
11
- @click.stop =" loadLog(logFile)"
11
+ v-if =" !collapsed"
12
+ class =" clickable mr-1"
13
+ :class =" pastebinLink ? 'bg-success' : 'bg-info'"
14
+ @click.stop =" postToPastebin"
15
+ >
16
+ <font-awesome-icon
17
+ fixed-width
18
+ :icon =" pastebinLink ? ['fas', 'check'] : ['fas', 'share-nodes']"
19
+ :title =" pastebinLink ? 'Link in die Zwischenablage kopiert' : 'Log auf paste.openwb.de teilen'"
20
+ />
21
+ </openwb-base-avatar >
22
+ <openwb-base-avatar
23
+ v-if =" !collapsed"
24
+ class =" clickable mr-1"
25
+ :class =" copyMessage ? 'bg-success' : 'bg-info'"
26
+ @click.stop =" copyToClipboard(logData)"
27
+ >
28
+ <font-awesome-icon
29
+ fixed-width
30
+ :icon =" copyMessage ? ['fas', 'check'] : ['fas', 'clipboard']"
31
+ :title =" copyMessage ? 'Log in die Zwischenablage kopiert' : 'Log kopieren'"
32
+ />
33
+ </openwb-base-avatar >
34
+ <openwb-base-avatar
35
+ v-if =" !collapsed"
36
+ class =" clickable"
37
+ :class =" loading ? 'bg-success' : 'bg-info'"
38
+ @click.stop =" loadLog(logFile, selectedVariant)"
12
39
>
13
40
<font-awesome-icon
14
41
fixed-width
15
42
:class =" loading ? 'fa-spin-pulse' : ''"
16
43
:icon =" loading ? ['fas', 'spinner'] : ['fas', 'file-download']"
44
+ title =" Log laden/aktualisieren"
17
45
/>
18
46
</openwb-base-avatar >
19
47
</template >
48
+ <openwb-base-alert
49
+ v-if =" foundFiles.length > 0"
50
+ subtype =" info"
51
+ >
52
+ Im {{ title }} stehen unterschiedliche Logauszüge zur Verfügung. Standardmässig werden Logs der letzten 3
53
+ Durchläufe geladen, für viele Fälle sollte dies ausreichen. Optional kann auch das gesamte Log geladen werden.<br />
54
+ Wurde eine Warnung oder ein Fehler protokolliert steht zusätzlich der letzte Durchlauf mit Warnungen und Fehlern
55
+ zur Verfügung.<br />
56
+ <openwb-base-select-input
57
+ v-model =" selectedVariant"
58
+ title =" Logfile"
59
+ required
60
+ :options =" foundFiles.map((file) => ({ value: file.suffix, text: file.title }))"
61
+ @change =" loadLog(logFile, selectedVariant)"
62
+ />
63
+ </openwb-base-alert >
20
64
<pre class =" log-data mb-0" >{{ logData }}</pre >
21
65
</openwb-base-card >
22
66
</template >
23
67
24
68
<script >
25
69
import { library } from " @fortawesome/fontawesome-svg-core" ;
26
- import { faFileDownload as fasFileDownload , faSpinner as fasSpinner } from " @fortawesome/free-solid-svg-icons" ;
70
+ import {
71
+ faClipboard as fasClipboard ,
72
+ faFileDownload as fasFileDownload ,
73
+ faSpinner as fasSpinner ,
74
+ faShareNodes as fasShareNodes ,
75
+ faCheck as fasCheck ,
76
+ } from " @fortawesome/free-solid-svg-icons" ;
27
77
import { FontAwesomeIcon } from " @fortawesome/vue-fontawesome" ;
78
+ import axios from " axios" ;
79
+ import pako from " pako" ;
28
80
29
- library .add (fasFileDownload, fasSpinner);
81
+ library .add (fasFileDownload, fasSpinner, fasClipboard, fasShareNodes, fasCheck );
30
82
31
83
export default {
32
84
name: " OpenwbLogCard" ,
@@ -47,22 +99,35 @@ export default {
47
99
return {
48
100
logData: " -- noch nicht geladen --" ,
49
101
loading: false ,
102
+ foundFiles: [], // Array to store found files with title, suffix, and description
103
+ selectedVariant: " " , // Selected file variant
104
+ copyMessage: false , // Flag to show copy message
105
+ pastebinLink: " " , // Link to the pastebin entry
50
106
};
51
107
},
52
108
methods: {
53
- async getFilePromise (myFile , ignore404 = false ) {
54
- return this . axios
55
- . get (location .protocol + " //" + location .host + myFile)
109
+ async getFilePromise (myFile , ignore404 = false , handleError = true , useHead = false ) {
110
+ const requestMethod = useHead ? " head " : " get " ;
111
+ return axios[requestMethod] (location .protocol + " //" + location .host + myFile)
56
112
.then ((response ) => {
57
- return response .data ;
113
+ if (useHead) {
114
+ // If the request is successful, the file exists
115
+ return true ;
116
+ } else {
117
+ const data = response .data ;
118
+ return data ? data : " log file is empty" ;
119
+ }
58
120
})
59
121
.catch ((error ) => {
122
+ if (! handleError) {
123
+ throw error;
124
+ }
60
125
if (error .response ) {
61
- // The request was made and the server responded with a status code
126
+ // The request was made but the server responded with a status code
62
127
// that falls out of the range of 2xx
63
128
if (error .response .status == 404 && ignore404) {
64
129
// ignore a 404 if requested, used for rotated log files which may not exist yet
65
- return " " ;
130
+ return useHead ? false : " " ;
66
131
}
67
132
return (
68
133
" A 404 is expected if running node.js dev server!\n " +
@@ -83,10 +148,14 @@ export default {
83
148
}
84
149
});
85
150
},
86
- async loadLog (fileName ) {
151
+ async loadLog (fileName , fileNameVariant = " " ) {
87
152
this .logData = " wird aktualisiert..." ;
88
153
this .loading = true ;
154
+ this .pastebinLink = " " ; // Clear the pastebin link
89
155
var logContents = " " ;
156
+ if (fileNameVariant) {
157
+ fileName = fileName .replace (" .log" , ` .${ fileNameVariant} .log` );
158
+ }
90
159
91
160
for (let i = 4 ; i >= 1 ; i-- ) {
92
161
const result = await this .getFilePromise (fileName + " ." + i, true );
@@ -99,6 +168,109 @@ export default {
99
168
this .logData = logContents;
100
169
this .loading = false ;
101
170
},
171
+ async checkLatestLog (fileName ) {
172
+ // Define file name variations
173
+ const fileVariations = [
174
+ { suffix: " latest" , title: " Letzten 3 Durchläufe" , description: " Logs der Letzten 3 Durchläufe laden" },
175
+ { suffix: " current" , title: " Letzter Durchlauf" , description: " Logs des letzten Durchlaufs laden" },
176
+ {
177
+ suffix: " latest-warning" ,
178
+ title: " Letzter Durchlauf mit Warnung oder Fehler" ,
179
+ description: " Fehlerprotokoll laden" ,
180
+ },
181
+ // Add more variations as needed
182
+ ];
183
+ // Check for the existence of the .latest log file
184
+ this .foundFiles = [];
185
+ for (const variation of fileVariations) {
186
+ const variantFileName = fileName .replace (" .log" , ` .${ variation .suffix } .log` );
187
+ try {
188
+ await this .getFilePromise (variantFileName, false , false , true );
189
+ this .foundFiles .push (variation);
190
+ if (variation .suffix === " latest" ) {
191
+ this .selectedVariant = " latest" ;
192
+ console .log (" Found latest log file: " , variantFileName);
193
+ }
194
+ } catch (error) {
195
+ console .log (error);
196
+ }
197
+ }
198
+ if (this .foundFiles .length > 0 ) {
199
+ this .foundFiles .push ({
200
+ suffix: " " ,
201
+ title: " Vollständiges Log" ,
202
+ description: " Vollständiges Log laden" ,
203
+ });
204
+ }
205
+ },
206
+ async onCardExpand () {
207
+ await this .checkLatestLog (this .logFile );
208
+ this .loadLog (this .logFile , this .selectedVariant );
209
+ },
210
+ copyToClipboard (text = this .logData , showMessage = true ) {
211
+ if (navigator .clipboard && navigator .clipboard .writeText ) {
212
+ navigator .clipboard
213
+ .writeText (text)
214
+ .then (() => {
215
+ if (showMessage) {
216
+ this .showCopyMessage ();
217
+ }
218
+ })
219
+ .catch ((err ) => {
220
+ console .error (" Fehler beim Kopieren in die Zwischenablage: " , err);
221
+ });
222
+ } else {
223
+ // Fallback method for older browsers and non-HTTPS contexts
224
+ const textArea = document .createElement (" textarea" );
225
+ textArea .value = text;
226
+ document .body .appendChild (textArea);
227
+ textArea .select ();
228
+ try {
229
+ document .execCommand (" copy" );
230
+ if (showMessage) {
231
+ this .showCopyMessage ();
232
+ }
233
+ } catch (err) {
234
+ console .error (" Fehler beim Kopieren in die Zwischenablage: " , err);
235
+ }
236
+ document .body .removeChild (textArea);
237
+ }
238
+ },
239
+ showCopyMessage () {
240
+ this .copyMessage = true ;
241
+ this .$root .postClientMessage (" Log in die Zwischenablage kopiert." , " info" );
242
+ setTimeout (() => {
243
+ this .copyMessage = false ;
244
+ }, 3000 ); // Message disappears after 3 seconds
245
+ },
246
+ async postToPastebin () {
247
+ try {
248
+ // Compress the log data using gzip
249
+ const compressedData = pako .gzip (this .logData );
250
+
251
+ const response = await axios .post (" https://bytebin.openwb.de/post" , compressedData, {
252
+ headers: {
253
+ " Content-Type" : " text/log" ,
254
+ " Content-Encoding" : " gzip" ,
255
+ },
256
+ });
257
+
258
+ if (! response .data .key ) {
259
+ throw new Error (" Key is missing in the response" );
260
+ }
261
+
262
+ const pastebinKey = response .data .key ;
263
+ this .pastebinLink = ` https://paste.openwb.de/${ pastebinKey} ` ;
264
+ console .log (" Pastebin link:" , this .pastebinLink );
265
+ this .copyToClipboard (this .pastebinLink , false );
266
+ this .$root .postClientMessage (
267
+ ` Log an Pastebin gesendet.<br>Key: <a href='${ this .pastebinLink } ' target='_blank' rel='noopener noreferrer'>${ pastebinKey} </a><br>Der Link wurde in die Zwischenablage kopiert.` ,
268
+ " info" ,
269
+ );
270
+ } catch (error) {
271
+ console .error (" Fehler beim Posten auf paste.openwb.de: " , error);
272
+ }
273
+ },
102
274
},
103
275
};
104
276
</script >
0 commit comments