|
@@ -1,17 +1,17 @@
|
|
|
-import { message } from 'ant-design-vue'
|
|
|
+import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
|
|
+import type { Key } from 'ant-design-vue/es/_util/type'
|
|
|
import type { Ref } from 'vue'
|
|
|
+import { message } from 'ant-design-vue'
|
|
|
import sortable from 'sortablejs'
|
|
|
-import type { Key } from 'ant-design-vue/es/_util/type'
|
|
|
-import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
|
|
|
|
|
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+// eslint-disable-next-line ts/no-explicit-any
|
|
|
function getRowKey(item: any) {
|
|
|
return item.dataset.rowKey
|
|
|
}
|
|
|
|
|
|
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+// eslint-disable-next-line ts/no-explicit-any
|
|
|
function getTargetData(data: any, indexList: number[]): any {
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
let target: any = { children: data }
|
|
|
indexList.forEach((index: number) => {
|
|
|
target.children[index].parent = target
|
|
@@ -21,112 +21,116 @@ function getTargetData(data: any, indexList: number[]): any {
|
|
|
return target
|
|
|
}
|
|
|
|
|
|
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
-function useSortable(props: StdTableProps, randomId: Ref<string>, dataSource: Ref<any[]>,
|
|
|
- rowsKeyIndexMap: Ref<Record<number, number[]>>, expandKeysList: Ref<Key[]>) {
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+// eslint-disable-next-line ts/no-explicit-any
|
|
|
+function useSortable(props: StdTableProps, randomId: Ref<string>, dataSource: Ref<any[]>, rowsKeyIndexMap: Ref<Record<number, number[]>>, expandKeysList: Ref<Key[]>) {
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
const table: any = document.querySelector(`#std-table-${randomId.value} tbody`)
|
|
|
|
|
|
- // eslint-disable-next-line no-new,new-cap
|
|
|
- new sortable(table, {
|
|
|
- handle: '.ant-table-drag-icon',
|
|
|
- animation: 150,
|
|
|
- sort: true,
|
|
|
- forceFallback: true,
|
|
|
- setData(dataTransfer) {
|
|
|
- dataTransfer.setData('Text', '')
|
|
|
- },
|
|
|
- onStart({ item }) {
|
|
|
- const targetRowKey = Number(getRowKey(item))
|
|
|
- if (targetRowKey)
|
|
|
- expandKeysList.value = expandKeysList.value.filter((_item: Key) => _item !== targetRowKey)
|
|
|
- },
|
|
|
- onMove({
|
|
|
- dragged,
|
|
|
- related,
|
|
|
- }) {
|
|
|
- const oldRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(dragged))]
|
|
|
- const newRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(related))]
|
|
|
-
|
|
|
- if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] !== newRow[newRow.length - 2])
|
|
|
- return false
|
|
|
-
|
|
|
- if (props.sortableMoveHook)
|
|
|
- return props.sortableMoveHook(oldRow, newRow)
|
|
|
- },
|
|
|
- async onEnd({
|
|
|
- item,
|
|
|
- newIndex,
|
|
|
- oldIndex,
|
|
|
- }) {
|
|
|
- if (newIndex === oldIndex)
|
|
|
- return
|
|
|
-
|
|
|
- const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
|
|
- const direction: number = indexDelta > 0 ? +1 : -1
|
|
|
-
|
|
|
- const rowIndex: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(item))]
|
|
|
- const newRow = getTargetData(dataSource.value, rowIndex)
|
|
|
- const newRowParent = newRow.parent
|
|
|
- const level: number = newRow.level
|
|
|
-
|
|
|
- const currentRowIndex: number[] = [...rowsKeyIndexMap.value?.
|
|
|
- [Number(getRowKey(table.children[Number(newIndex) + direction]))]]
|
|
|
-
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
- const currentRow: any = getTargetData(dataSource.value, currentRowIndex)
|
|
|
-
|
|
|
- // Reset parent
|
|
|
- currentRow.parent = newRow.parent = null
|
|
|
- newRowParent.children.splice(rowIndex[level], 1)
|
|
|
- newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
|
|
-
|
|
|
- const changeIds: number[] = []
|
|
|
-
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
- function processChanges(row: any, children = false, _newIndex: number | undefined = undefined) {
|
|
|
- // Build changes ID list expect new row
|
|
|
- if (children || _newIndex === undefined)
|
|
|
- changeIds.push(row.id)
|
|
|
-
|
|
|
- if (_newIndex !== undefined)
|
|
|
- rowsKeyIndexMap.value[row.id][level] = _newIndex
|
|
|
- else if (children)
|
|
|
- rowsKeyIndexMap.value[row.id][level] += direction
|
|
|
-
|
|
|
- row.parent = null
|
|
|
- if (row.children) {
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
- row.children.forEach((v: any) => processChanges(v, true, _newIndex))
|
|
|
+ try {
|
|
|
+ // eslint-disable-next-line no-new,new-cap
|
|
|
+ new sortable(table, {
|
|
|
+ handle: '.ant-table-drag-icon',
|
|
|
+ animation: 150,
|
|
|
+ sort: true,
|
|
|
+ forceFallback: true,
|
|
|
+ setData(dataTransfer) {
|
|
|
+ dataTransfer.setData('Text', '')
|
|
|
+ },
|
|
|
+ onStart({ item }) {
|
|
|
+ const targetRowKey = Number(getRowKey(item))
|
|
|
+ if (targetRowKey)
|
|
|
+ expandKeysList.value = expandKeysList.value.filter((_item: Key) => _item !== targetRowKey)
|
|
|
+ },
|
|
|
+ onMove({
|
|
|
+ dragged,
|
|
|
+ related,
|
|
|
+ }) {
|
|
|
+ const oldRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(dragged))]
|
|
|
+ const newRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(related))]
|
|
|
+
|
|
|
+ if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] !== newRow[newRow.length - 2])
|
|
|
+ return false
|
|
|
+
|
|
|
+ if (props.sortableMoveHook)
|
|
|
+ return props.sortableMoveHook(oldRow, newRow)
|
|
|
+ },
|
|
|
+ async onEnd({
|
|
|
+ item,
|
|
|
+ newIndex,
|
|
|
+ oldIndex,
|
|
|
+ }) {
|
|
|
+ if (newIndex === oldIndex || newIndex === undefined)
|
|
|
+ return
|
|
|
+
|
|
|
+ const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
|
|
+ const direction: number = indexDelta > 0 ? +1 : -1
|
|
|
+
|
|
|
+ const rowIndex: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(item))]
|
|
|
+ const newRow = getTargetData(dataSource.value, rowIndex)
|
|
|
+ const newRowParent = newRow.parent
|
|
|
+ const level: number = newRow.level
|
|
|
+
|
|
|
+ const currentRowIndex: number[] = [...rowsKeyIndexMap.value?.
|
|
|
+ [Number(getRowKey(table.children[Number(newIndex) + direction]))]]
|
|
|
+
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
+ const currentRow: any = getTargetData(dataSource.value, currentRowIndex)
|
|
|
+
|
|
|
+ // Reset parent
|
|
|
+ currentRow.parent = newRow.parent = null
|
|
|
+ newRowParent.children.splice(rowIndex[level], 1)
|
|
|
+ newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
|
|
+
|
|
|
+ const changeIds: number[] = []
|
|
|
+
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
+ function processChanges(row: any, children = false, _newIndex: number | undefined = undefined) {
|
|
|
+ // Build changes ID list expect new row
|
|
|
+ if (children || _newIndex === undefined)
|
|
|
+ changeIds.push(row.id)
|
|
|
+
|
|
|
+ if (_newIndex !== undefined)
|
|
|
+ rowsKeyIndexMap.value[row.id][level] = _newIndex
|
|
|
+ else if (children)
|
|
|
+ rowsKeyIndexMap.value[row.id][level] += direction
|
|
|
+
|
|
|
+ row.parent = null
|
|
|
+ if (row.children) {
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
+ row.children.forEach((v: any) => processChanges(v, true, _newIndex))
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // Replace row index for new row
|
|
|
- processChanges(newRow, false, currentRowIndex[level])
|
|
|
-
|
|
|
- // Rebuild row index maps for changes row
|
|
|
- for (let i = Number(oldIndex); i !== newIndex; i -= direction) {
|
|
|
- const _rowIndex: number[] = rowsKeyIndexMap.value?.[getRowKey(table.children[i])]
|
|
|
-
|
|
|
- _rowIndex[level] += direction
|
|
|
- processChanges(getTargetData(dataSource.value, _rowIndex))
|
|
|
- }
|
|
|
-
|
|
|
- // console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
|
|
- // ', changes IDs:', changeIds
|
|
|
-
|
|
|
- props.api.update_order({
|
|
|
- target_id: newRow.id,
|
|
|
- direction,
|
|
|
- affected_ids: changeIds,
|
|
|
- }).then(() => {
|
|
|
- message.success($gettext('Updated successfully'))
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
- }).catch((e: any) => {
|
|
|
- message.error(e?.message ?? $gettext('Server error'))
|
|
|
- })
|
|
|
- },
|
|
|
- })
|
|
|
+
|
|
|
+ // Replace row index for new row
|
|
|
+ processChanges(newRow, false, currentRowIndex[level])
|
|
|
+
|
|
|
+ // Rebuild row index maps for changes row
|
|
|
+ for (let i = Number(oldIndex); i >= newIndex; i -= direction) {
|
|
|
+ const _rowIndex: number[] = rowsKeyIndexMap.value?.[getRowKey(table.children[i])]
|
|
|
+
|
|
|
+ _rowIndex[level] += direction
|
|
|
+ processChanges(getTargetData(dataSource.value, _rowIndex))
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
|
|
+ // ', changes IDs:', changeIds
|
|
|
+
|
|
|
+ props.api.update_order({
|
|
|
+ target_id: newRow.id,
|
|
|
+ direction,
|
|
|
+ affected_ids: changeIds,
|
|
|
+ }).then(() => {
|
|
|
+ message.success($gettext('Updated successfully'))
|
|
|
+ // eslint-disable-next-line ts/no-explicit-any
|
|
|
+ }).catch((e: any) => {
|
|
|
+ message.error(e?.message ?? $gettext('Server error'))
|
|
|
+ })
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ catch (e) {
|
|
|
+ console.error(e)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
export default useSortable
|