gitlab-ce/app/assets/javascripts/glql/components/presenters/table.vue

83 lines
2.1 KiB
Vue

<script>
import { GlIcon } from '@gitlab/ui';
import Sorter from '../../core/sorter';
import ThResizable from '../common/th_resizable.vue';
export default {
name: 'TablePresenter',
components: {
GlIcon,
ThResizable,
},
inject: ['presenter'],
props: {
data: {
required: true,
type: Object,
validator: ({ nodes }) => Array.isArray(nodes),
},
config: {
required: true,
type: Object,
validator: ({ fields }) => Array.isArray(fields) && fields.length > 0,
},
},
data() {
const items = this.data.nodes.slice();
return {
items,
fields: this.config.fields,
sorter: new Sorter(items),
table: null,
};
},
async mounted() {
await this.$nextTick();
this.table = this.$refs.table;
},
};
</script>
<template>
<div class="!gl-my-4">
<table ref="table" class="!gl-mb-2 !gl-mt-0 gl-overflow-y-hidden">
<thead>
<tr v-if="table">
<th-resizable v-for="(field, fieldIndex) in fields" :key="field.key" :table="table">
<div
:data-testid="`column-${fieldIndex}`"
class="gl-cursor-pointer"
@click="sorter.sortBy(field.key)"
>
{{ field.label }}
<gl-icon
v-if="sorter.options.fieldName === field.key"
:name="sorter.options.ascending ? 'arrow-up' : 'arrow-down'"
/>
</div>
</th-resizable>
</tr>
</thead>
<tbody>
<tr
v-for="(item, itemIndex) in items"
:key="item.id"
:data-testid="`table-row-${itemIndex}`"
>
<td v-for="field in fields" :key="field.key">
<component :is="presenter.forField(item, field.key)" />
</td>
</tr>
<tr v-if="!items.length">
<td :colspan="fields.length" class="gl-text-center">
<em>{{ __('No data found for this query') }}</em>
</td>
</tr>
</tbody>
</table>
<small>{{ __('Generated by GLQL') }}</small>
</div>
</template>