mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-31 10:07:22 +01:00
Add clear logs functionality (#1584)
* Add clear logs functionality Other Changes: - Add actions toolbar for actions pertaining to container logs - Move Download button to actions toolbar, remove text and margin to match clear logs button - Move search box below actions toolbar - Turn off pointer events for scroll progress component so that Download button can be clicked - Adjust spacing of container bar to accomodate the new actions toolbar * Change actions toolbar into a floating menu Other Changes: - Move actions toolbar into its own component - Move clear hotkey from LogEventSource to LogActionsToolbar, where the button is - Move search back to where it was before - Add tooltip component from buefy to annotate action buttons - Add CSS variable for action toolbar background color, changes based on theme
This commit is contained in:
92
assets/components/LogActionsToolbar.vue
Normal file
92
assets/components/LogActionsToolbar.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="toolbar mr-0 is-vcentered is-hidden-mobile">
|
||||
<div class="is-flex">
|
||||
<b-tooltip type="is-dark" label="Clear">
|
||||
<a @click="onClearClicked" class="button is-small is-light is-inverted" id="clear">
|
||||
<span class="icon">
|
||||
<icon name="bin"></icon>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
<div class="is-flex-grow-1"></div>
|
||||
<b-tooltip type="is-dark" label="Download">
|
||||
<a
|
||||
class="button is-small is-light is-inverted"
|
||||
id="download"
|
||||
:href="`${base}/api/logs/download?id=${container.id}`"
|
||||
download
|
||||
>
|
||||
<span class="icon">
|
||||
<icon name="save"></icon>
|
||||
</span>
|
||||
</a>
|
||||
</b-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "../store/config";
|
||||
import hotkeys from "hotkeys-js";
|
||||
import Icon from "./Icon";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
onClearClicked: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
container: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
name: "LogActionsToolbar",
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
computed: {
|
||||
base() {
|
||||
return config.base;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
hotkeys("shift+command+l, shift+ctrl+l", (event, handler) => {
|
||||
this.onClearClicked();
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#download.button,
|
||||
#clear.button {
|
||||
.icon {
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 200px;
|
||||
background-color: var(--action-toolbar-background-color);
|
||||
border-radius: 8em;
|
||||
margin-top: 0.5em;
|
||||
|
||||
& > div {
|
||||
margin: 0 2em;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,43 +1,32 @@
|
||||
<template>
|
||||
<scrollable-view :scrollable="scrollable" v-if="container">
|
||||
<template v-slot:header v-if="showTitle">
|
||||
<div class="mr-0 columns is-vcentered is-hidden-mobile">
|
||||
<div class="column is-clipped">
|
||||
<div class="mr-0 columns is-vcentered is-marginless is-hidden-mobile">
|
||||
<div class="column is-clipped is-paddingless">
|
||||
<container-title :container="container" @close="$emit('close')"></container-title>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="column is-narrow is-paddingless">
|
||||
<container-stat :stat="container.stat" :state="container.state"></container-stat>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<a
|
||||
class="button is-small is-outlined"
|
||||
id="download"
|
||||
:href="`${base}/api/logs/download?id=${container.id}`"
|
||||
download
|
||||
>
|
||||
<span class="icon">
|
||||
<icon name="save"></icon>
|
||||
</span>
|
||||
Download
|
||||
</a>
|
||||
</div>
|
||||
<div class="column is-narrow" v-if="closable">
|
||||
<div class="column is-clipped is-paddingless"></div>
|
||||
<div class="column is-narrow is-paddingless" v-if="closable">
|
||||
<button class="delete is-medium" @click="$emit('close')"></button>
|
||||
</div>
|
||||
</div>
|
||||
<log-actions-toolbar :container="container" :onClearClicked="onClearClicked"></log-actions-toolbar>
|
||||
</template>
|
||||
<template v-slot="{ setLoading }">
|
||||
<log-viewer-with-source :id="id" @loading-more="setLoading($event)"></log-viewer-with-source>
|
||||
<log-viewer-with-source ref="logViewer" :id="id" @loading-more="setLoading($event)"></log-viewer-with-source>
|
||||
</template>
|
||||
</scrollable-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LogViewerWithSource from "./LogViewerWithSource";
|
||||
import LogActionsToolbar from "./LogActionsToolbar";
|
||||
import ScrollableView from "./ScrollableView";
|
||||
import ContainerTitle from "./ContainerTitle";
|
||||
import ContainerStat from "./ContainerStat";
|
||||
import Icon from "./Icon";
|
||||
import config from "../store/config";
|
||||
import containerMixin from "./mixins/container";
|
||||
|
||||
@@ -63,14 +52,14 @@ export default {
|
||||
name: "LogContainer",
|
||||
components: {
|
||||
LogViewerWithSource,
|
||||
LogActionsToolbar,
|
||||
ScrollableView,
|
||||
ContainerTitle,
|
||||
ContainerStat,
|
||||
Icon,
|
||||
},
|
||||
computed: {
|
||||
base() {
|
||||
return config.base;
|
||||
methods: {
|
||||
onClearClicked() {
|
||||
this.$refs.logViewer.clear();
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -88,16 +77,4 @@ button.delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#download.button {
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -70,6 +70,9 @@ export default {
|
||||
this.messages.push(...this.buffer);
|
||||
this.buffer = [];
|
||||
},
|
||||
clear() {
|
||||
this.messages = [];
|
||||
},
|
||||
reset() {
|
||||
if (this.es) {
|
||||
this.es.close();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<log-event-source :id="id" v-slot="eventSource" @loading-more="$emit('loading-more', $event)">
|
||||
<log-event-source ref="logEventSource" :id="id" v-slot="eventSource" @loading-more="$emit('loading-more', $event)">
|
||||
<log-viewer :messages="eventSource.messages"></log-viewer>
|
||||
</log-event-source>
|
||||
</template>
|
||||
@@ -15,5 +15,10 @@ export default {
|
||||
LogEventSource,
|
||||
LogViewer,
|
||||
},
|
||||
methods: {
|
||||
clear() {
|
||||
this.$refs.logEventSource.clear();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -90,6 +90,7 @@ export default {
|
||||
.scroll-progress {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
|
||||
svg {
|
||||
filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.2));
|
||||
|
||||
@@ -83,6 +83,14 @@
|
||||
d="M224 1536h608V384H192v1120q0 13 9.5 22.5t22.5 9.5zm1376-32V384H960v1152h608q13 0 22.5-9.5t9.5-22.5zm128-1216v1216q0 66-47 113t-113 47H224q-66 0-113-47t-47-113V288q0-66 47-113t113-47h1344q66 0 113 47t47 113z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icon-bin" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M2 5v10c0 0.55 0.45 1 1 1h9c0.55 0 1-0.45 1-1v-10h-11zM5 14h-1v-7h1v7zM7 14h-1v-7h1v7zM9 14h-1v-7h1v7zM11 14h-1v-7h1v7z"
|
||||
></path>
|
||||
<path
|
||||
d="M13.25 2h-3.25v-1.25c0-0.412-0.338-0.75-0.75-0.75h-3.5c-0.412 0-0.75 0.338-0.75 0.75v1.25h-3.25c-0.413 0-0.75 0.337-0.75 0.75v1.25h13v-1.25c0-0.413-0.338-0.75-0.75-0.75zM9 2h-3v-0.987h3v0.987z"
|
||||
></path>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import Switch from "buefy/dist/esm/switch";
|
||||
import Radio from "buefy/dist/esm/radio";
|
||||
import Field from "buefy/dist/esm/field";
|
||||
import Modal from "buefy/dist/esm/modal";
|
||||
import Tooltip from "buefy/dist/esm/tooltip";
|
||||
import Autocomplete from "buefy/dist/esm/autocomplete";
|
||||
|
||||
import store from "./store";
|
||||
@@ -18,6 +19,7 @@ Vue.use(Switch);
|
||||
Vue.use(Radio);
|
||||
Vue.use(Field);
|
||||
Vue.use(Modal);
|
||||
Vue.use(Tooltip);
|
||||
Vue.use(Autocomplete);
|
||||
|
||||
const routes = [
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@charset "utf-8";
|
||||
@import "~bulma/sass/utilities/initial-variables.sass";
|
||||
|
||||
|
||||
$body-background-color: var(--body-background-color);
|
||||
|
||||
$scheme-main: var(--scheme-main);
|
||||
@@ -25,12 +24,16 @@ $panel-heading-color: var(--panel-heading-color);
|
||||
$link: $turquoise;
|
||||
$link-active: $grey-dark;
|
||||
|
||||
$dark-toolbar-color: rgba($black-bis, 0.7);
|
||||
$light-toolbar-color: rgba($grey-darker, 0.7);
|
||||
|
||||
@import "~bulma";
|
||||
@import "../node_modules/splitpanes/dist/splitpanes.css";
|
||||
@import "~buefy/src/scss/utils/_all";
|
||||
@import "~buefy/src/scss/components/_switch";
|
||||
@import "~buefy/src/scss/components/_radio";
|
||||
@import "~buefy/src/scss/components/_modal";
|
||||
@import "~buefy/src/scss/components/_tooltip";
|
||||
@import "~buefy/src/scss/components/_autocomplete";
|
||||
|
||||
html {
|
||||
@@ -46,6 +49,7 @@ html {
|
||||
--secondary-color: #{$yellow};
|
||||
|
||||
--body-background-color: #{$black-bis};
|
||||
--action-toolbar-background-color: #{$dark-toolbar-color};
|
||||
|
||||
--menu-item-active-background-color: var(--primary-color);
|
||||
--menu-item-color: hsl(0, 6%, 87%);
|
||||
@@ -72,6 +76,7 @@ html {
|
||||
--secondary-color: #d8f0ca;
|
||||
|
||||
--body-background-color: #{$white-bis};
|
||||
--action-toolbar-background-color: #{$light-toolbar-color};
|
||||
--body-color: #{$grey-darker};
|
||||
|
||||
--menu-item-color: #{$grey-dark};
|
||||
|
||||
Reference in New Issue
Block a user