Commit 5461aeaa by Johannes Edmeier

fix navigating to sessions with parameter set

also fix table styling in httptraces, auditevents and sessions
parent ac420c8c
...@@ -149,7 +149,7 @@ class Instance { ...@@ -149,7 +149,7 @@ class Instance {
}); });
} }
async fetchSessions(username) { async fetchSessionsByUsername(username) {
return axios.get(uri`instances/${this.id}/actuator/sessions`, { return axios.get(uri`instances/${this.id}/actuator/sessions`, {
headers: {'Accept': actuatorMimeTypes}, headers: {'Accept': actuatorMimeTypes},
params: {username} params: {username}
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
--> -->
<template> <template>
<table class="table is-hoverable is-fullwidth"> <table class="auditevents table is-hoverable is-fullwidth">
<thead> <thead>
<tr> <tr>
<th>Timestamp</th> <th>Timestamp</th>
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<tbody> <tbody>
<template v-for="event in events"> <template v-for="event in events">
<tr class="is-selectable" <tr class="is-selectable"
:class="{ 'event--is-detailed' : showDetails[event.key] }" :class="{ 'auditevents__event--is-detailed' : showDetails[event.key] }"
@click="showDetails[event.key] ? $delete(showDetails, event.key) : $set(showDetails, event.key, true)" @click="showDetails[event.key] ? $delete(showDetails, event.key) : $set(showDetails, event.key, true)"
:key="event.key"> :key="event.key">
<td v-text="event.timestamp.format('L HH:mm:ss.SSS')"/> <td v-text="event.timestamp.format('L HH:mm:ss.SSS')"/>
...@@ -48,9 +48,9 @@ ...@@ -48,9 +48,9 @@
</td> </td>
<td v-else v-text="event.sessionId"/> <td v-else v-text="event.sessionId"/>
</tr> </tr>
<tr class="event__detail" :key="`${event.key}-detail`" v-if="showDetails[event.key]"> <tr :key="`${event.key}-detail`" v-if="showDetails[event.key]">
<td colspan="5"> <td colspan="5">
<pre v-text="toJson(event.data)"/> <pre class="auditevents__event-detail" v-text="toJson(event.data)"/>
</td> </td>
</tr> </tr>
</template> </template>
...@@ -94,14 +94,19 @@ ...@@ -94,14 +94,19 @@
</script> </script>
<style lang="scss"> <style lang="scss">
@import "~@/assets/css/utilities"; .auditevents {
table-layout: fixed;
.event--is-detailed td { td {
border: none !important; vertical-align: middle;
} }
.event__detail td { &__event--is-detailed td {
overflow-x: auto; border: none !important;
max-width: 1024px; }
&__event-detail {
overflow: auto;
}
} }
</style> </style>
...@@ -15,39 +15,40 @@ ...@@ -15,39 +15,40 @@
--> -->
<template> <template>
<table class="table is-hoverable is-fullwidth"> <table class="httptraces table is-hoverable is-fullwidth">
<thead> <thead>
<tr> <tr>
<th>Timestamp</th> <th class="httptraces__trace-timestamp">Timestamp</th>
<th>Method</th> <th class="httptraces__trace-method">Method</th>
<th>Path</th> <th class="httptraces__trace-uri">Path</th>
<th>Status</th> <th class="httptraces__trace-status">Status</th>
<th>Content-Type</th> <th class="httptraces__trace-contentType">Content-Type</th>
<th>Content-Length</th> <th class="httptraces__trace-contentLength">Length</th>
<th>Time</th> <th class="httptraces__trace-timeTaken">Time</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<template v-for="trace in traces"> <template v-for="trace in traces">
<tr class="is-selectable" <tr class="is-selectable"
:class="{ 'trace--is-detailed' : showDetails[trace.key] }" :class="{ 'httptraces__trace---is-detailed' : showDetails[trace.key] }"
@click="showDetails[trace.key] ? $delete(showDetails, trace.key) : $set(showDetails, trace.key, true)" @click="showDetails[trace.key] ? $delete(showDetails, trace.key) : $set(showDetails, trace.key, true)"
:key="trace.key"> :key="trace.key">
<td v-text="trace.timestamp.format('L HH:mm:ss.SSS')"/> <td class="httptraces__trace-timestamp" v-text="trace.timestamp.format('L HH:mm:ss.SSS')"/>
<td v-text="trace.request.method"/> <td class="httptraces__trace-method" v-text="trace.request.method"/>
<td v-text="trace.request.uri"/> <td class="httptraces__trace-uri" v-text="trace.request.uri"/>
<td> <td class="httptraces__trace-status">
<span v-text="trace.response.status" class="tag" <span v-text="trace.response.status" class="tag"
:class="{ 'is-success' : trace.isSuccess(), 'is-warning' : trace.isClientError(), 'is-danger' : trace.isServerError() }"/> :class="{ 'is-success' : trace.isSuccess(), 'is-warning' : trace.isClientError(), 'is-danger' : trace.isServerError() }"/>
</td> </td>
<td v-text="trace.contentType"/> <td class="httptraces__trace-contentType" v-text="trace.contentType"/>
<td v-text="trace.contentLength ? prettyBytes(trace.contentLength) : ''"/> <td class="httptraces__trace-contentLength"
<td v-text="trace.contentLength ? prettyBytes(trace.contentLength) : ''"/>
v-text="trace.timeTaken !== null && typeof trace.timeTaken !== 'undefined' ? `${trace.timeTaken} ms` : ''"/> <td class="httptraces__trace-timeTaken"
v-text="trace.timeTaken !== null && typeof trace.timeTaken !== 'undefined' ? `${trace.timeTaken} ms` : ''"/>
</tr> </tr>
<tr class="trace__detail" :key="`${trace.key}-detail`" v-if="showDetails[trace.key]"> <tr :key="`${trace.key}-detail`" v-if="showDetails[trace.key]">
<td colspan="7"> <td colspan="7">
<pre v-text="toJson(trace)"/> <pre class="httptraces__trace-detail" v-text="toJson(trace)"/>
</td> </td>
</tr> </tr>
</template> </template>
...@@ -83,12 +84,53 @@ ...@@ -83,12 +84,53 @@
<style lang="scss"> <style lang="scss">
@import "~@/assets/css/utilities"; @import "~@/assets/css/utilities";
.trace--is-detailed td { .httptraces {
border: none !important; table-layout: fixed;
}
td {
vertical-align: middle;
overflow: hidden;
word-wrap: break-word;
}
&__trace {
&--is-detailed td {
border: none !important;
}
&-timestamp {
width: 130px;
}
&-method {
width: 100px;
}
.trace__detail td { &-uri {
overflow-x: auto; width: auto;
max-width: 1024px; }
&-status {
width: 80px;
}
&-contentType {
width: 200px;
}
&-contentLength {
width: 100px;
}
&-timeTaken {
width: 120px;
}
&-detail {
overflow: auto;
}
}
} }
</style> </style>
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
</span> </span>
</div> </div>
<div class="control is-expanded"> <div class="control is-expanded">
<input class="input" type="text" v-model="filter.value" @keyup.enter="fetchSessions()"> <input class="input" type="text" v-model="filter.value"
@keyup.enter="fetchSessionsByUsername()" @paste="handlePaste">
</div> </div>
</div> </div>
<div v-if="error" class="message is-danger"> <div v-if="error" class="message is-danger">
...@@ -39,7 +40,7 @@ ...@@ -39,7 +40,7 @@
<p v-text="error.message"/> <p v-text="error.message"/>
</div> </div>
</div> </div>
<sba-sessions-list :instance="instance" :sessions="sessions" <sba-sessions-list :instance="instance" :sessions="sessions" :is-loading="isLoading"
@deleted="fetch"/> @deleted="fetch"/>
</div> </div>
</section> </section>
...@@ -88,14 +89,13 @@ ...@@ -88,14 +89,13 @@
if (this.filter.type === 'sessionId') { if (this.filter.type === 'sessionId') {
this.sessions = await this.fetchSession() this.sessions = await this.fetchSession()
} else { } else {
this.sessions = await this.fetchSessions() this.sessions = await this.fetchSessionsByUsername()
} }
} catch (error) { } catch (error) {
console.warn('Fetching sessions failed:', error); console.warn('Fetching sessions failed:', error);
this.error = error this.error = error
} finally {
this.isLoading = false
} }
this.isLoading = false
}, 250), }, 250),
async fetchSession() { async fetchSession() {
try { try {
...@@ -109,32 +109,33 @@ ...@@ -109,32 +109,33 @@
} }
} }
}, },
async fetchSessions() { async fetchSessionsByUsername() {
const response = await this.instance.fetchSessions(this.filter.value); const response = await this.instance.fetchSessionsByUsername(this.filter.value);
return response.data.sessions.map(session => new Session(session)) return response.data.sessions.map(session => new Session(session))
}, },
updateFilter() { handlePaste(event) {
this.filter = _.entries(this.$route.query) const looksLikeSessionId = event.clipboardData.getData('text').match(regexUuid);
.reduce((acc, [name, value]) => { if (looksLikeSessionId) {
acc.type = name; this.filter.type = 'sessionId';
acc.value = value; }
return acc;
}, {type: null, value: ''});
} }
}, },
watch: { watch: {
'$route.query': { '$route.query': {
handler: 'updateFilter', immediate: true,
immediate: true handler() {
this.filter = _.entries(this.$route.query)
.reduce((acc, [name, value]) => {
acc.type = name;
acc.value = value;
return acc;
}, {type: 'username', value: ''});
}
}, },
filter: { filter: {
deep: true, deep: true,
immediate: true,
handler() { handler() {
if (this.filter.type === null) {
const looksLikeSessionId = this.filter.value.match(regexUuid);
this.filter.type = looksLikeSessionId ? 'sessionId' : 'username';
}
const query = {[this.filter.type]: this.filter.value}; const query = {[this.filter.type]: this.filter.value};
if (!_.isEqual(query, !this.$route.query)) { if (!_.isEqual(query, !this.$route.query)) {
this.$router.replace({ this.$router.replace({
...@@ -142,7 +143,6 @@ ...@@ -142,7 +143,6 @@
query: query query: query
}); });
} }
this.fetch(); this.fetch();
} }
} }
......
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
--> -->
<template> <template>
<table class="table is-fullwidth"> <table class="sessions table is-fullwidth">
<thead> <thead>
<tr> <tr>
<th/>
<th>Session Id</th> <th>Session Id</th>
<th>Created at</th> <th>Created at</th>
<th>Last accessed at</th> <th>Last accessed at</th>
<th>Expiry</th>
<th>Max. inactive<br>interval <th>Max. inactive<br>interval
</th> </th>
<th>Attributes</th> <th>Attributes</th>
...@@ -39,15 +39,15 @@ ...@@ -39,15 +39,15 @@
</thead> </thead>
<tr v-for="session in sessions" :key="session.id"> <tr v-for="session in sessions" :key="session.id">
<td> <td>
<span v-if="session.expired" class="tag is-info">Expired</span>
</td>
<td>
<router-link v-text="session.id" <router-link v-text="session.id"
:to="{ name: 'instance/sessions', params: { 'instanceId' : instance.id}, query: { sessionId : session.id } }"/> :to="{ name: 'instance/sessions', params: { 'instanceId' : instance.id}, query: { sessionId : session.id } }"/>
</td> </td>
<td v-text="session.creationTime.format('L HH:mm:ss.SSS')"/> <td v-text="session.creationTime.format('L HH:mm:ss.SSS')"/>
<td v-text="session.lastAccessedTime.format('L HH:mm:ss.SSS')"/> <td v-text="session.lastAccessedTime.format('L HH:mm:ss.SSS')"/>
<td> <td>
<span v-if="session.expired" class="tag is-info">Expired</span>
</td>
<td>
<span v-if="session.maxInactiveInterval >= 0" v-text="`${session.maxInactiveInterval}s`"/> <span v-if="session.maxInactiveInterval >= 0" v-text="`${session.maxInactiveInterval}s`"/>
<span v-else>unlimited</span> <span v-else>unlimited</span>
</td> </td>
...@@ -66,7 +66,10 @@ ...@@ -66,7 +66,10 @@
</td> </td>
</tr> </tr>
<tr v-if="sessions.length === 0"> <tr v-if="sessions.length === 0">
<td class="is-muted" colspan="7 ">No sessions found.</td> <td class="is-muted" colspan="7 ">
<p v-if="isLoading" class="is-loading">Loading Sessions...</p>
<p v-else>No Sessions found.</p>
</td>
</tr> </tr>
</table> </table>
</template> </template>
...@@ -85,6 +88,10 @@ ...@@ -85,6 +88,10 @@
instance: { instance: {
type: Instance, type: Instance,
required: true required: true
},
isLoading: {
type: Boolean,
default: false
} }
}, },
data: () => ({ data: () => ({
...@@ -135,3 +142,10 @@ ...@@ -135,3 +142,10 @@
} }
} }
</script> </script>
<style lang="scss">
.sessions {
& td {
vertical-align: middle;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment