add editor modal + fix image not sending dirty
This commit is contained in:
parent
acaa9a18ae
commit
1eee6c0b4b
2 changed files with 150 additions and 1 deletions
|
@ -22,6 +22,7 @@ import {
|
||||||
type Row as DataRow,
|
type Row as DataRow,
|
||||||
type Column as DataColumn,
|
type Column as DataColumn,
|
||||||
} from 'src/types/data'
|
} from 'src/types/data'
|
||||||
|
import DataEditorModal from './DataEditorModal.vue'
|
||||||
import ImageEditor from './ImageEditor.vue'
|
import ImageEditor from './ImageEditor.vue'
|
||||||
import { type EditingRow } from './types'
|
import { type EditingRow } from './types'
|
||||||
|
|
||||||
|
@ -37,6 +38,8 @@ const editingRows = ref<DataRow[]>([])
|
||||||
const expandedRows = ref<DataRow[]>([])
|
const expandedRows = ref<DataRow[]>([])
|
||||||
const editingImage = ref(false)
|
const editingImage = ref(false)
|
||||||
const editingImageRow = ref(null as EditingRow | null)
|
const editingImageRow = ref(null as EditingRow | null)
|
||||||
|
const editingRow = ref(false)
|
||||||
|
const editingRowData = ref(null as EditingRow | null)
|
||||||
const columnsByKey = computed(() => Object.assign({}, ...props.columns.map(c => ({[c.name]: c}))))
|
const columnsByKey = computed(() => Object.assign({}, ...props.columns.map(c => ({[c.name]: c}))))
|
||||||
const columnsPrimary = computed(() => props.columns.filter(column => !column.secondary))
|
const columnsPrimary = computed(() => props.columns.filter(column => !column.secondary))
|
||||||
const selectedTemplate = ref(null as DataRow | null) // simply used to reset dropdown when selected
|
const selectedTemplate = ref(null as DataRow | null) // simply used to reset dropdown when selected
|
||||||
|
@ -86,6 +89,12 @@ const onEditImage = (event: Event, slotProps: EditingRow) => {
|
||||||
editingImageRow.value = slotProps
|
editingImageRow.value = slotProps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onEditRow = (event: Event, slotProps: EditingRow) => {
|
||||||
|
event.preventDefault()
|
||||||
|
editingRow.value = true
|
||||||
|
editingRowData.value = slotProps
|
||||||
|
}
|
||||||
|
|
||||||
const onRemoveImage = (event: Event, slotProps: EditingRow) => {
|
const onRemoveImage = (event: Event, slotProps: EditingRow) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const row = { ...model.value[slotProps.index] } as any
|
const row = { ...model.value[slotProps.index] } as any
|
||||||
|
@ -96,6 +105,7 @@ const onRemoveImage = (event: Event, slotProps: EditingRow) => {
|
||||||
let rows = editingRows.value
|
let rows = editingRows.value
|
||||||
rows.splice(indexOfEditing, 1)
|
rows.splice(indexOfEditing, 1)
|
||||||
editingRows.value = rows
|
editingRows.value = rows
|
||||||
|
emits('dirty')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +120,14 @@ const onSaveImage = (image: string) => {
|
||||||
let rows = editingRows.value
|
let rows = editingRows.value
|
||||||
rows.splice(indexOfEditing, 1)
|
rows.splice(indexOfEditing, 1)
|
||||||
editingRows.value = rows
|
editingRows.value = rows
|
||||||
|
emits('dirty')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onSaveRow = (row: DataRow, editingRow: EditingRow) => {
|
||||||
|
model.value[editingRow.index] = row
|
||||||
|
emits('dirty')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
|
@ -120,6 +136,12 @@ ImageEditor(
|
||||||
v-model:row='editingImageRow'
|
v-model:row='editingImageRow'
|
||||||
@saved='onSaveImage'
|
@saved='onSaveImage'
|
||||||
)
|
)
|
||||||
|
DataEditorModal(
|
||||||
|
v-model:visible='editingRow'
|
||||||
|
:row='editingRowData'
|
||||||
|
:fields='columns'
|
||||||
|
@saved='onSaveRow'
|
||||||
|
)
|
||||||
DataTable.data-editor(
|
DataTable.data-editor(
|
||||||
@row-edit-save='onRowEditSave'
|
@row-edit-save='onRowEditSave'
|
||||||
v-model:editingRows='editingRows'
|
v-model:editingRows='editingRows'
|
||||||
|
@ -258,6 +280,14 @@ DataTable.data-editor(
|
||||||
variant='text'
|
variant='text'
|
||||||
@click='slotProps.editorInitCallback'
|
@click='slotProps.editorInitCallback'
|
||||||
)
|
)
|
||||||
|
Button.edit(
|
||||||
|
icon='pi pi-pen-to-square'
|
||||||
|
aria-label='Row Edit Details'
|
||||||
|
rounded
|
||||||
|
severity='secondary'
|
||||||
|
variant='text'
|
||||||
|
@click='(e) => onEditRow(e, slotProps)'
|
||||||
|
)
|
||||||
Button(
|
Button(
|
||||||
icon='pi pi-trash'
|
icon='pi pi-trash'
|
||||||
aria-label='Delete'
|
aria-label='Delete'
|
||||||
|
@ -283,7 +313,7 @@ DataTable.data-editor(
|
||||||
rounded
|
rounded
|
||||||
severity='secondary'
|
severity='secondary'
|
||||||
variant='text'
|
variant='text'
|
||||||
@click'slotProps.editorCancelCallback(e)'
|
@click='slotProps.editorCancelCallback(e)'
|
||||||
)
|
)
|
||||||
template(
|
template(
|
||||||
#expansion='slotProps'
|
#expansion='slotProps'
|
||||||
|
|
119
src/views/Editor/DataEditorModal.vue
Normal file
119
src/views/Editor/DataEditorModal.vue
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
watch
|
||||||
|
} from 'vue'
|
||||||
|
import Button from 'primevue/button'
|
||||||
|
import Checkbox from 'primevue/checkbox'
|
||||||
|
import Dialog from 'primevue/dialog'
|
||||||
|
import ImageComponent from 'primevue/image'
|
||||||
|
import InputGroup from 'primevue/inputgroup'
|
||||||
|
import InputGroupAddon from 'primevue/inputgroupaddon'
|
||||||
|
import InputText from 'primevue/inputtext'
|
||||||
|
import MultiSelect from 'primevue/multiselect'
|
||||||
|
import Select from 'primevue/select'
|
||||||
|
|
||||||
|
import { useAppStore } from 'src/store'
|
||||||
|
import { type EditingRow } from './types'
|
||||||
|
import type { Row as DataRow, Column as DataColumn } from 'src/types/data'
|
||||||
|
|
||||||
|
const store = useAppStore()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
fields: DataColumn[],
|
||||||
|
row: EditingRow,
|
||||||
|
}>()
|
||||||
|
const visible = defineModel<boolean>('visible', { default: false })
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'saved', val: DataRow, editingRow: EditingRow): void
|
||||||
|
}>()
|
||||||
|
const editing = ref<DataRow>({} as any)
|
||||||
|
watch(() => props.row, async (newRow, oldRow) => {
|
||||||
|
editing.value = JSON.parse(JSON.stringify(props.row.data || {}))
|
||||||
|
})
|
||||||
|
|
||||||
|
const onCancel = (e: Event) => {
|
||||||
|
e.preventDefault()
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSave = async (e: Event) => {
|
||||||
|
e.preventDefault()
|
||||||
|
emit('saved', JSON.parse(JSON.stringify(editing.value || {})), props.row)
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template lang="pug">
|
||||||
|
ImageEditor(
|
||||||
|
v-model:visible='editingImage'
|
||||||
|
v-model:row='editingImageRow'
|
||||||
|
@saved='onSaveImage'
|
||||||
|
)
|
||||||
|
Dialog(
|
||||||
|
v-model:visible='visible'
|
||||||
|
modal
|
||||||
|
header='Edit Data'
|
||||||
|
)
|
||||||
|
.content
|
||||||
|
InputGroup(
|
||||||
|
v-for='field in fields'
|
||||||
|
)
|
||||||
|
InputGroupAddon
|
||||||
|
label
|
||||||
|
span {{ field.name }}
|
||||||
|
InputGroupAddon(
|
||||||
|
v-if='field.type === "image"'
|
||||||
|
)
|
||||||
|
p Image editing in data modal not yet supported
|
||||||
|
InputGroupAddon(
|
||||||
|
v-else-if='field.type === "toggle"'
|
||||||
|
)
|
||||||
|
Checkbox(
|
||||||
|
v-model='editing[field.name]'
|
||||||
|
:name='`toggle for ${editing.name || editing._id} ${field.name}`'
|
||||||
|
binary
|
||||||
|
)
|
||||||
|
InputGroupAddon(
|
||||||
|
v-else-if='field.type === "dropdown"'
|
||||||
|
)
|
||||||
|
Select(
|
||||||
|
v-model='editing[field.name]'
|
||||||
|
:options='field.options'
|
||||||
|
placeholder='Select from Options'
|
||||||
|
filter
|
||||||
|
showClear
|
||||||
|
fluid
|
||||||
|
)
|
||||||
|
InputGroupAddon(
|
||||||
|
v-else-if='field.type === "multiselect"'
|
||||||
|
)
|
||||||
|
MultiSelect(
|
||||||
|
v-model='editing[field.name]'
|
||||||
|
:options='field.options'
|
||||||
|
placeholder='Select from Options'
|
||||||
|
filter
|
||||||
|
showClear
|
||||||
|
fluid
|
||||||
|
display='chip'
|
||||||
|
)
|
||||||
|
InputGroupAddon(
|
||||||
|
v-else
|
||||||
|
)
|
||||||
|
InputText(
|
||||||
|
v-model='editing[field.name]'
|
||||||
|
)
|
||||||
|
template(#footer)
|
||||||
|
Button(
|
||||||
|
label='Save'
|
||||||
|
@click='onSave'
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
label='Cancel'
|
||||||
|
@click='onCancel'
|
||||||
|
)
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="sass">
|
||||||
|
|
||||||
|
</style>
|
Loading…
Add table
Reference in a new issue