<commit_before><template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
  <div v-if="items != null">
    <v-toolbar flat color="white">
      <v-app-bar-nav-icon @click="showDrawer()"></v-app-bar-nav-icon>
      <v-toolbar-title>Dashboard</v-toolbar-title>
      <v-spacer></v-spacer>
      <div>
        <v-tabs centered>
          <v-tab key="history" :to="`/project/${projectId}/history`">History</v-tab>
          <v-tab key="activity" :to="`/project/${projectId}/activity`">Activity</v-tab>
          <v-tab key="settings" :to="`/project/${projectId}/settings`">Settings</v-tab>
        </v-tabs>
      </div>
    </v-toolbar>
    <v-data-table
        :headers="headers"
        :items="items"
        :footer-props="{ itemsPerPageOptions: [20] }"
        class="mt-4"
    >
      <template v-slot:item.tpl_alias="{ item }">
        <v-icon class="mr-3" small>
          {{ TEMPLATE_TYPE_ICONS[item.tpl_type] }}
        </v-icon>
        <a :href="
          '/project/' + item.project_id +
          '/templates/' + item.template_id"
        >{{ item.tpl_alias }}</a>
        <v-icon small class="ml-1 mr-1">mdi-arrow-right</v-icon>
        <a @click="showTaskLog(item.id)">#{{ item.id }}</a>
      </template>

      <template v-slot:item.version="{ item }">
        <div v-if="item.version != null">
          <v-icon
              v-if="item.status === 'success'"
              small
              color="success"
          >mdi-check</v-icon>
          <v-icon
              v-else
              small
              color="red"
          >mdi-close</v-icon>
          <span class="ml-1">{{ item.version }}</span>
        </div>
        <div v-else>&mdash;</div>
      </template>

      <template v-slot:item.status="{ item }">
        <TaskStatus :status="item.status"/>
      </template>

      <template v-slot:item.start="{ item }">
        {{ item.start | formatDate }}
      </template>

      <template v-slot:item.end="{ item }">
        {{ [item.start, item.end] | formatMilliseconds }}
      </template>
    </v-data-table>
  </div>
</template>

<script>
import ItemListPageBase from '@/components/ItemListPageBase';
import EventBus from '@/event-bus';
import TaskStatus from '@/components/TaskStatus.vue';
import socket from '@/socket';
import { TEMPLATE_TYPE_ICONS } from '@/lib/constants';

export default {
  mixins: [ItemListPageBase],

  data() {
    return { TEMPLATE_TYPE_ICONS };
  },

  components: { TaskStatus },

  watch: {
    async projectId() {
      await this.loadItems();
    },
  },

  created() {
    socket.addListener((data) => this.onWebsocketDataReceived(data));
  },

  methods: {
    showTaskLog(taskId) {
      EventBus.$emit('i-show-task', {
        taskId,
      });
    },

    async onWebsocketDataReceived(data) {
      if (data.project_id !== this.projectId || data.type !== 'update') {
        return;
      }

      if (!this.items.some((item) => item.id === data.task_id)) {
        await this.loadItems();
      }

      const task = this.items.find((item) => item.id === data.task_id);

      Object.assign(task, {
        ...data,
        type: undefined,
      });
    },

    getHeaders() {
      return [
        {
          text: 'Task',
          value: 'tpl_alias',
          sortable: false,
        },
        {
          text: 'Version',
          value: 'version',
          sortable: false,
        },
        {
          text: 'Status',
          value: 'status',
          sortable: false,
        },
        {
          text: 'User',
          value: 'user_name',
          sortable: false,
        },
        {
          text: 'Start',
          value: 'start',
          sortable: false,
        },
        {
          text: 'Duration',
          value: 'end',
          sortable: false,
        },
      ];
    },

    getItemsUrl() {
      return `/api/project/${this.projectId}/tasks/last`;
    },
  },
};
</script>
<commit_msg>chore(fe): small ui changes<commit_after><template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
  <div v-if="items != null">
    <v-toolbar flat color="white">
      <v-app-bar-nav-icon @click="showDrawer()"></v-app-bar-nav-icon>
      <v-toolbar-title>Dashboard</v-toolbar-title>
      <v-spacer></v-spacer>
      <div>
        <v-tabs centered>
          <v-tab key="history" :to="`/project/${projectId}/history`">History</v-tab>
          <v-tab key="activity" :to="`/project/${projectId}/activity`">Activity</v-tab>
          <v-tab key="settings" :to="`/project/${projectId}/settings`">Settings</v-tab>
        </v-tabs>
      </div>
    </v-toolbar>
    <v-data-table
        :headers="headers"
        :items="items"
        :footer-props="{ itemsPerPageOptions: [20] }"
        class="mt-4"
    >
      <template v-slot:item.tpl_alias="{ item }">
        <div style="display: flex; justify-content: left; align-items: center;">
          <v-icon class="mr-3" small>
            {{ TEMPLATE_TYPE_ICONS[item.tpl_type] }}
          </v-icon>
          <a :href="
          '/project/' + item.project_id +
          '/templates/' + item.template_id"
          >{{ item.tpl_alias }}</a>
          <v-icon small class="ml-1 mr-1">mdi-arrow-right</v-icon>
          <a @click="showTaskLog(item.id)">#{{ item.id }}</a>
          <div class="ml-2" v-if="item.version != null">
            <v-icon
                v-if="item.status === 'success'"
                small
                color="success"
            >mdi-check</v-icon>
            <v-icon
                v-else
                small
                color="red"
            >mdi-close</v-icon>
            <span class="ml-1">{{ item.version }}</span>
          </div>
        </div>
      </template>

      <template v-slot:item.status="{ item }">
        <TaskStatus :status="item.status"/>
      </template>

      <template v-slot:item.start="{ item }">
        {{ item.start | formatDate }}
      </template>

      <template v-slot:item.end="{ item }">
        {{ [item.start, item.end] | formatMilliseconds }}
      </template>
    </v-data-table>
  </div>
</template>

<script>
import ItemListPageBase from '@/components/ItemListPageBase';
import EventBus from '@/event-bus';
import TaskStatus from '@/components/TaskStatus.vue';
import socket from '@/socket';
import { TEMPLATE_TYPE_ICONS } from '@/lib/constants';

export default {
  mixins: [ItemListPageBase],

  data() {
    return { TEMPLATE_TYPE_ICONS };
  },

  components: { TaskStatus },

  watch: {
    async projectId() {
      await this.loadItems();
    },
  },

  created() {
    socket.addListener((data) => this.onWebsocketDataReceived(data));
  },

  methods: {
    showTaskLog(taskId) {
      EventBus.$emit('i-show-task', {
        taskId,
      });
    },

    async onWebsocketDataReceived(data) {
      if (data.project_id !== this.projectId || data.type !== 'update') {
        return;
      }

      if (!this.items.some((item) => item.id === data.task_id)) {
        await this.loadItems();
      }

      const task = this.items.find((item) => item.id === data.task_id);

      Object.assign(task, {
        ...data,
        type: undefined,
      });
    },

    getHeaders() {
      return [
        {
          text: 'Task',
          value: 'tpl_alias',
          sortable: false,
        },
        {
          text: 'Status',
          value: 'status',
          sortable: false,
        },
        {
          text: 'User',
          value: 'user_name',
          sortable: false,
        },
        {
          text: 'Start',
          value: 'start',
          sortable: false,
        },
        {
          text: 'Duration',
          value: 'end',
          sortable: false,
        },
      ];
    },

    getItemsUrl() {
      return `/api/project/${this.projectId}/tasks/last`;
    },
  },
};
</script>

{'fraction_non_alphanumeric': 0.1788878900731989, 'fraction_numerical': 0.003210479003467317, 'mean_word_length': 1.8278867102396514, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4992651', 'n_tokens_mistral': 2574, 'n_tokens_neox': 2528, 'n_words': 426}