summary history files

frontend/src/components/ConfigMapsList.vue
<script lang="ts">
import { defineComponent, ref, computed, PropType, onBeforeUnmount } from 'vue';
import { KubernetesCluster, KubernetesConfigMap } from '../types/kubernetes';
import SearchBar from './SearchBar.vue';
import { formatAge } from '../lib/format';

export default defineComponent({
    name: 'ConfigMapsList',
    components: {
        SearchBar
    },
    props: {
        selectedCluster: {
            type: Object as PropType<KubernetesCluster>,
            required: false,
            default: null
        },
        configMaps: {
            type: Array as PropType<KubernetesConfigMap[]>,
            required: false,
            default: () => []
        }
    },
    emits: ['configmap-selected'],
    data() {
        return {
            selectedConfigMap: null as KubernetesConfigMap | null
        };
    },
    setup(props, { emit }) {
        const searchQuery = ref('');
        const filteredConfigMaps = computed(() => {
            if (!searchQuery.value) {
                return props.configMaps;
            }

            const query = searchQuery.value.toLowerCase();

            const nameSpecificMatch = query.match(/^name:(.+)$/);
            if (nameSpecificMatch) {
                const nameQuery = nameSpecificMatch[1].trim();
                return props.configMaps.filter(configMap => {
                    const name = configMap.metadata.name.toLowerCase();
                    return name.includes(nameQuery);
                });
            }

            const namespaceSpecificMatch = query.match(/^namespace:(.+)$/);
            if (namespaceSpecificMatch) {
                const namespaceQuery = namespaceSpecificMatch[1].trim();
                return props.configMaps.filter(configMap => {
                    const namespace = configMap.metadata.namespace.toLowerCase();
                    return namespace.includes(namespaceQuery);
                });
            }

            return props.configMaps.filter(configMap => {
                const name = configMap.metadata.name.toLowerCase();
                return name.includes(query);
            });
        });

        return {
            searchQuery,
            filteredConfigMaps,
            formatAge
        };
    },
    methods: {
      isSelected(configMap: KubernetesConfigMap): boolean {
        if (!this.selectedConfigMap) return false;
        return this.selectedConfigMap.metadata.name === configMap.metadata.name &&
          this.selectedConfigMap.metadata.namespace === configMap.metadata.namespace &&
          this.selectedConfigMap.metadata.uid === configMap.metadata.uid;
      },
      selectConfigMap(configMap: KubernetesConfigMap): void {
        const configMapToEmit = { ...configMap }
        if (!configMapToEmit.kind) {
          configMapToEmit.kind = 'ConfigMap';
        }
        this.selectedConfigMap = configMapToEmit;
        this.$emit('configmap-selected', configMapToEmit);
      },
      getUniqueKey(configMap: KubernetesConfigMap): string {
          const namespace = configMap.metadata.namespace || 'default';
          let key;
          key = namespace + '-' + configMap.metadata.name + '-' + (configMap.metadata.uid || '');
          return key;
      }
    },
});
</script>

<template>
  <div class="configmaps-container">
    <div class="search-bar-container">
      <SearchBar
        :value="searchQuery"
        @update:value="searchQuery = $event"
        placeholder="Search configmaps..."
      />
    </div>
    <div class="table-scroll-container">
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Namespace</th>
            <th>Age</th>
          </tr>
        </thead>
        <tbody>
          <tr 
            v-for="configMap in filteredConfigMaps" 
            :key="getUniqueKey(configMap)"
            :class="{ selected: isSelected(configMap) }"
            @click="selectConfigMap(configMap)"
          >
            <td>{{ configMap.metadata.name }}</td>
            <td>{{ configMap.metadata.namespace || 'default' }}</td>
            <td>{{ formatAge(configMap.metadata.creationTimestamp) }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<style src="@/assets/css/ConfigMapsList.css" scoped></style>