Skip to content

Commit

Permalink
feat: create editable table to create batch queries
Browse files Browse the repository at this point in the history
  • Loading branch information
caro3801 committed Jan 6, 2025
1 parent d679083 commit 9162987
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 0 deletions.
77 changes: 77 additions & 0 deletions src/components/TableEditable/RowEditable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<div class="d-flex">
<div v-if="!isEditing" class="editable-row mx-3" @click="startEditing">
<i v-if="showPlaceholder">{{ placeholder }}</i>
<span v-else>{{ cellValue }}</span>
</div>
<b-form-input
v-else
ref="inputRef"
v-model="cellValue"
class="editable-row"
type="text"
@focus="$event.target.select()"
@focusout.prevent="stopEditing"
@keypressed.enter="stopEditing"
@keyup.esc="stopEditing"
/>
</div>
</template>

<script setup>
import { nextTick, useTemplateRef, computed, watch } from 'vue'
const cellValue = defineModel({
type: String,
default: ''
})
const isEditing = defineModel('focused', {
type: Boolean,
default: false
})
defineProps({
placeholder: {
type: String,
default: 'Enter your query here'
}
})
const inputRef = useTemplateRef('inputRef')
watch(
isEditing,
async (value) => {
if (value) {
await nextTick()
inputRef.value?.focus()
}
},
{ immediate: true }
)
const showPlaceholder = computed(() => {
return cellValue.value.length === 0
})
const startEditing = async () => {
isEditing.value = true
}
const stopEditing = () => {
isEditing.value = false
}
</script>
<style scoped>
div {
cursor: pointer;
}
.editable-row {
display: flex;
align-items: center;
cursor: pointer;
height: 40px;
width: 100%;
}
</style>
109 changes: 109 additions & 0 deletions src/components/TableEditable/TableEditable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<template>
<div class="table-editable">
<b-table-simple small>
<thead>
<tr>
<th>#</th>
<th><span class="mx-3">Query</span></th>
<th></th>
</tr>
</thead>

<b-tbody class="overflow-y-auto h-auto">
<b-tr v-for="(item, index) in items" :key="index" class="">
<b-td class="table-editable__index text">{{ index + 1 }}</b-td>
<b-td>
<row-editable
v-model:focused="item.focused"
:model-value="item.name"
@keyup.up="focusPreviousItem(index)"
@keyup.down="focusNextItem(index)"
@update:model-value="updateCellValue(index, $event)"
@keydown.enter="onEnter($event, index)"
@keydown.tab.exact="addItem(index)"
@focusout.prevent="addItem(index)"
/>
</b-td>
<b-td class="table-editable__action">
<button-icon
v-if="item.name?.length > 0"
icon-left="trash"
variant="outline-secondary"
square
hide-label
size="sm"
@click="removeItem(index)"
@keydown.tab.exact.prevent="focusNextItem(index)"
@keydown.enter.prevent="removeItem(index)"
@keydown.tab.shift.exact.prevent="focusCurrentItem(index)"
/>
</b-td>
</b-tr>
</b-tbody>
</b-table-simple>
</div>
</template>

<script setup>
import { reactive } from 'vue'
import RowEditable from './RowEditable.vue'
import ButtonIcon from '@/components/Button/ButtonIcon'
const items = defineModel('items', {
type: Array,
default: () => reactive([{ name: '', focused: false }])
})
defineProps({
maxHeight: {
type: Number,
default: 150
}
})
function onEnter(_, index) {
if (!items.value[index].name) {
return
}
addItem(index)
focusNextItem(index)
}
function focusPreviousItem(index) {
if (items.value.length === index || index < 1) {
return
}
items.value[index - 1].focused = true
}
function focusNextItem(index) {
if (items.value.length - 1 === index) {
return
}
items.value[index + 1].focused = true
}
function focusCurrentItem(index) {
items.value[index].focused = true
}
const addItem = (index) => {
if (index === items.value.length - 1 && items.value[index]?.name.length) {
items.value.push({ name: '' })
}
}
const removeItem = (index) => {
items.value.splice(index, 1)
}
function updateCellValue(index, val) {
items.value[index].name = val
}
</script>
<style scoped lang="scss">
.table-editable {
&__index,
&__action {
width: 50px;
vertical-align: middle;
}
}
</style>
18 changes: 18 additions & 0 deletions src/stories/components/TableEditable/RowEditable.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import RowEditable from '@/components/TableEditable/RowEditable.vue';

export default {
title: 'Components/TableEditable/RowEditable',
component: RowEditable,
tags: ['autodocs'],
args: {
modelValue: ''
}
};


export const Default = {};

export const WithValue = {
args: {modelValue:'tutu'}
}

17 changes: 17 additions & 0 deletions src/stories/components/TableEditable/TableEditable.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import TableEditable from '@/components/TableEditable/TableEditable.vue';

export default {
title: 'Components/TableEditable/TableEditable',
component: TableEditable,
tags: ['autodocs'],
args: {
}
};


export const Default = {};

export const WithValues = {
args: { items: [{name:'tutu'},{name:'toto'},{name:'titi'}] }
}

0 comments on commit 9162987

Please sign in to comment.