Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'web/html/xui/component')
-rw-r--r--web/html/xui/component/sortableTable.html218
1 files changed, 218 insertions, 0 deletions
diff --git a/web/html/xui/component/sortableTable.html b/web/html/xui/component/sortableTable.html
new file mode 100644
index 00000000..010d8011
--- /dev/null
+++ b/web/html/xui/component/sortableTable.html
@@ -0,0 +1,218 @@
+{{define "component/sortableTableTrigger"}}
+ <a-icon type="drag"
+ style="cursor: move;"
+ @mouseup="mouseUpHandler"
+ @mousedown="mouseDownHandler"
+ @click="clickHandler" />
+{{end}}
+
+{{define "component/sortableTable"}}
+<script>
+ const DRAGGABLE_ROW_CLASS = 'draggable-row';
+
+ const findParentRowElement = (el) => {
+ if (!el || !el.tagName) {
+ return null;
+ } else if (el.classList.contains(DRAGGABLE_ROW_CLASS)) {
+ return el;
+ } else if (el.parentNode) {
+ return findParentRowElement(el.parentNode);
+ } else {
+ return null;
+ }
+ }
+
+ Vue.component('a-table-sortable', {
+ data() {
+ return {
+ sortingElementIndex: null,
+ newElementIndex: null,
+ };
+ },
+ props: ['data-source', 'customRow'],
+ inheritAttrs: false,
+ provide() {
+ const sortable = {}
+
+ Object.defineProperty(sortable, "setSortableIndex", {
+ enumerable: true,
+ get: () => this.setCurrentSortableIndex,
+ });
+
+ Object.defineProperty(sortable, "resetSortableIndex", {
+ enumerable: true,
+ get: () => this.resetSortableIndex,
+ });
+
+ return {
+ sortable,
+ }
+ },
+ render: function (createElement) {
+ return createElement(
+ 'a-table',
+ {
+ class: {
+ 'ant-table-is-sorting': this.isDragging(),
+ },
+ props: {
+ ...this.$attrs,
+ 'data-source': this.records,
+ customRow: (record, index) => this.customRowRender(record, index),
+ },
+ on: this.$listeners,
+ nativeOn: {
+ drop: (e) => this.dropHandler(e),
+ },
+ scopedSlots: this.$scopedSlots,
+ },
+ this.$slots.default,
+ )
+ },
+ created() {
+ this.$memoSort = {};
+ },
+ methods: {
+ isDragging() {
+ const currentIndex = this.sortingElementIndex;
+ return currentIndex !== null && currentIndex !== undefined;
+ },
+ resetSortableIndex(e, index) {
+ this.sortingElementIndex = null;
+ this.newElementIndex = null;
+ this.$memoSort = {};
+ },
+ setCurrentSortableIndex(e, index) {
+ this.sortingElementIndex = index;
+ },
+ dragStartHandler(e, index) {
+ if (!this.isDragging()) {
+ e.preventDefault();
+ return;
+ }
+ },
+ dragStopHandler(e, index) {
+ this.resetSortableIndex(e, index);
+ },
+ dragOverHandler(e, index) {
+ if (!this.isDragging()) {
+ return;
+ }
+
+ e.preventDefault();
+
+ const currentIndex = this.sortingElementIndex;
+ if (index === currentIndex) {
+ this.newElementIndex = null;
+ return;
+ }
+
+ const row = findParentRowElement(e.target);
+ if (!row) {
+ return;
+ }
+
+ const rect = row.getBoundingClientRect();
+ const offsetTop = e.pageY - rect.top;
+
+ if (offsetTop < rect.height / 2) {
+ this.newElementIndex = Math.max(index - 1, 0);
+ } else {
+ this.newElementIndex = index;
+ }
+ },
+ dropHandler(e) {
+ if (this.isDragging()) {
+ this.$emit('onsort', this.sortingElementIndex, this.newElementIndex);
+ }
+ },
+ customRowRender(record, index) {
+ const parentMethodResult = this.customRow?.(record, index) || {};
+ const newIndex = this.newElementIndex;
+ const currentIndex = this.sortingElementIndex;
+
+ return {
+ ...parentMethodResult,
+ attrs: {
+ ...(parentMethodResult?.attrs || {}),
+ draggable: true,
+ },
+ on: {
+ ...(parentMethodResult?.on || {}),
+ dragstart: (e) => this.dragStartHandler(e, index),
+ dragend: (e) => this.dragStopHandler(e, index),
+ dragover: (e) => this.dragOverHandler(e, index),
+ },
+ class: {
+ ...(parentMethodResult?.class || {}),
+ [DRAGGABLE_ROW_CLASS]: true,
+ ['dragging']: this.isDragging()
+ ? (newIndex === null ? index === currentIndex : index === newIndex)
+ : false,
+ },
+ };
+ }
+ },
+ computed: {
+ records() {
+ const newIndex = this.newElementIndex;
+ const currentIndex = this.sortingElementIndex;
+
+ if (!this.isDragging() || newIndex === null || currentIndex === newIndex) {
+ return this.dataSource;
+ }
+
+ if (this.$memoSort.newIndex === newIndex) {
+ return this.$memoSort.list;
+ }
+
+ let list = [...this.dataSource];
+ list.splice(newIndex, 0, list.splice(currentIndex, 1)[0]);
+
+ this.$memoSort = {
+ newIndex,
+ list,
+ };
+
+ return list;
+ }
+ }
+ });
+
+ Vue.component('table-sort-trigger', {
+ template: `{{template "component/sortableTableTrigger"}}`,
+ props: ['item-index'],
+ inject: ['sortable'],
+ methods: {
+ mouseDownHandler(e) {
+ if (this.sortable) {
+ this.sortable.setSortableIndex(e, this.itemIndex);
+ }
+ },
+ mouseUpHandler(e) {
+ if (this.sortable) {
+ this.sortable.resetSortableIndex(e, this.itemIndex);
+ }
+ },
+ clickHandler(e) {
+ e.preventDefault();
+ },
+ }
+ })
+</script>
+
+<style>
+ .ant-table-is-sorting .draggable-row td {
+ background-color: white !important;
+ }
+ .dark .ant-table-is-sorting .draggable-row td {
+ background-color: var(--dark-color-surface-100) !important;
+ }
+ .ant-table-is-sorting .dragging {
+ opacity: 0.5;
+ }
+ .ant-table-is-sorting .dragging .ant-table-row-index {
+ opacity: 0;
+ }
+</style>
+{{end}} \ No newline at end of file