summary history files

frontend/src/components/Logs.vue
<template>
  <div class="logs-container">
    <div class="logs-header">
      <span>Logs: {{ selectedPod?.metadata?.name }}</span>
      <button @click="$emit('close')" class="close-btn">×</button>
    </div>
    <div class="logs-content" ref="logsContent">
      <pre v-html="logContent"></pre>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Logs',

  props: {
    selectedPod: {
      type: Object,
      required: true
    },
    selectedNamespace: {
      type: Object,
      required: true
    },
    selectedCluster: {
      type: Object,
      required: true
    },
    selectedContainer: {
      type: String,
      required: true
    }
  },

  data() {
    return {
      socket: null,
      logContent: '',
      isConnected: false,
      reconnectAttempts: 0,
      maxReconnectAttempts: 3,
      isReconnecting: false
    }
  },

  mounted() {
    this.connectWebSocket();
  },

  beforeUnmount() {
    this.cleanup();
  },

  methods: {
    connectWebSocket() {
      if (this.isReconnecting) {
        return;
      }

      this.isReconnecting = true;

      if (this.socket) {
        this.socket.close();
        this.socket = null;
      }

      const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const wsUrl = `${wsProtocol}//${window.location.hostname}:8081/api/pods/logs?` + 
        `cluster=${encodeURIComponent(this.selectedCluster.server)}&` +
        `namespace=${encodeURIComponent(this.selectedNamespace.name)}&` +
        `pod=${encodeURIComponent(this.selectedPod.metadata.name)}&` +
        `container=${encodeURIComponent(this.selectedContainer)}`;

      try {
        this.socket = new WebSocket(wsUrl);

        this.socket.onopen = () => {
          this.isConnected = true;
          this.reconnectAttempts = 0;
          this.isReconnecting = false;
          this.logContent += 'Connected to pod logs...\n';
          this.scrollToBottom();
        };

        this.socket.onmessage = (event) => {
          this.logContent += event.data;
          this.scrollToBottom();
        };

        this.socket.onclose = () => {
          this.isConnected = false;
          this.isReconnecting = false;
          this.logContent += '\nConnection closed\n';
          this.scrollToBottom();
        };

        this.socket.onerror = (error) => {
          console.error('WebSocket error:', error);
          this.isReconnecting = false;
          this.logContent += '\nError: Failed to connect to pod logs\n';
          this.scrollToBottom();
        };

      } catch (error) {
        console.error('Failed to connect to WebSocket:', error);
        this.isReconnecting = false;
        this.logContent += 'Failed to connect to pod logs\n';
        this.scrollToBottom();
      }
    },

    scrollToBottom() {
      if (this.$refs.logsContent) {
        this.$refs.logsContent.scrollTop = this.$refs.logsContent.scrollHeight;
      }
    },

    cleanup() {
      if (this.socket) {
        this.socket.close();
        this.socket = null;
      }
      this.isConnected = false;
      this.isReconnecting = false;
      this.reconnectAttempts = 0;
    }
  }
}
</script>

<style scoped>
.logs-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  width: 800px;
  height: 500px;
  background: #1e1e1e;
  border: 1px solid #333;
  border-radius: 6px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.logs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: #333;
  color: white;
  font-size: 14px;
  user-select: none;
}

.close-btn {
  background: none;
  border: none;
  color: white;
  font-size: 20px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
}

.close-btn:hover {
  color: #ff5252;
}

.logs-content {
  flex: 1;
  padding: 12px;
  overflow-y: auto;
  background-color: #1e1e1e;
  color: #ffffff;
  font-family: monospace;
  white-space: pre-wrap;
  word-wrap: break-word;
  text-align: left;
}

pre {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
}
</style>