Browse Source

[frontend] Add an autoscrolling log panel Vue component

Johan Ahlen 4 years ago
parent
commit
be516aecbe
1 changed files with 85 additions and 0 deletions
  1. 85 0
      desktop/core/src/desktop/js/components/LogsPanel.vue

+ 85 - 0
desktop/core/src/desktop/js/components/LogsPanel.vue

@@ -0,0 +1,85 @@
+<!--
+  Licensed to Cloudera, Inc. under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  Cloudera, Inc. licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<template>
+  <div ref="logsContainer" class="logs-panel" @scroll="onScroll">
+    <span v-if="logs">{{ logs }}</span>
+    <span v-else>{{ I18n('There are currently no logs available.') }}</span>
+  </div>
+</template>
+
+<script lang="ts">
+  import Vue from 'vue';
+  import Component from 'vue-class-component';
+  import { Prop, Watch } from 'vue-property-decorator';
+
+  import I18n from 'utils/i18n';
+
+  @Component({
+    methods: { I18n }
+  })
+  export default class LogsPanel extends Vue {
+    @Prop()
+    logs = '';
+    @Prop({ required: false })
+    autoScroll = true;
+
+    ignoreNextScrollEvent = false;
+    userScrolled = false;
+
+    onScroll(): void {
+      if (!this.autoScroll) {
+        return;
+      }
+      const containerEl = <HTMLDivElement>this.$refs.logsContainer;
+      if (!this.ignoreNextScrollEvent && containerEl) {
+        this.userScrolled =
+          containerEl &&
+          containerEl.scrollHeight - containerEl.clientHeight - containerEl.scrollTop > 10;
+      }
+      this.ignoreNextScrollEvent = false;
+    }
+
+    @Watch('logs', { immediate: true })
+    scrollToLatest(): void {
+      if (!this.autoScroll) {
+        return;
+      }
+      const containerEl = <HTMLDivElement>this.$refs.logsContainer;
+      if (
+        !this.userScrolled &&
+        containerEl &&
+        containerEl.scrollHeight > containerEl.clientHeight
+      ) {
+        this.ignoreNextScrollEvent = true;
+        containerEl.scrollTop = containerEl.scrollHeight - containerEl.clientHeight;
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .logs-panel {
+    height: 100%;
+    width: 100%;
+    white-space: pre;
+    overflow: auto;
+    font-family: monospace;
+    padding: 5px;
+  }
+</style>