add topic sorting & js to support it
This commit is contained in:
@@ -859,6 +859,53 @@ a.mention {
|
||||
}
|
||||
}
|
||||
|
||||
ol.sortable-list {
|
||||
display: flex;
|
||||
gap: var(--base-padding);
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
gap: var(--big-padding);
|
||||
}
|
||||
|
||||
li.immovable .dragger {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.plank.dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/*background-color: var(--bg-color-tertiary);*/
|
||||
padding: var(--base-padding);
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.sortable-item-inner {
|
||||
display: flex;
|
||||
gap: var(--base-padding);
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
|
||||
& > * {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&:not(.row) > * {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
margin-left: 0;
|
||||
|
||||
46
data/static/icons/dragger.svg
Normal file
46
data/static/icons/dragger.svg
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#000000;stroke:none;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect1"
|
||||
width="16"
|
||||
height="2"
|
||||
x="4"
|
||||
y="8" />
|
||||
<rect
|
||||
style="fill:#000000;stroke:none;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect2"
|
||||
width="16"
|
||||
height="2"
|
||||
x="4"
|
||||
y="11" />
|
||||
<rect
|
||||
style="fill:#000000;stroke:none;stroke-width:0.999996;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect3"
|
||||
width="16"
|
||||
height="2"
|
||||
x="4"
|
||||
y="14" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 6,6 6,-6 6,6 H 16 L 12,2 8,6 Z"
|
||||
id="path3" />
|
||||
<path
|
||||
style="fill:#000000;stroke:none;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 6,18 6,6 6,-6 h -2 l -4,4 -4,-4 z"
|
||||
id="path4" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
97
data/static/js/ui.js
Normal file
97
data/static/js/ui.js
Normal file
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
{
|
||||
function isBefore(el1, el2) {
|
||||
if (el2.parentNode === el1.parentNode) {
|
||||
for (let cur = el1.previousSibling; cur; cur = cur.previousSibling) {
|
||||
if (cur === el2) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
let draggedItem = null;
|
||||
|
||||
function sortableItemDragStart(e, item) {
|
||||
const box = item.getBoundingClientRect();
|
||||
const oX = e.clientX - box.left;
|
||||
const oY = e.clientY - box.top;
|
||||
draggedItem = item;
|
||||
item.classList.add('contrast-bg');
|
||||
e.dataTransfer.setDragImage(item, oX, oY);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
|
||||
function sortableItemDragEnd(e, item) {
|
||||
draggedItem = null;
|
||||
item.classList.remove('contrast-bg');
|
||||
}
|
||||
|
||||
function sortableItemDragOver(e, item) {
|
||||
const target = e.target.closest('.sortable-item');
|
||||
if (!target || target === draggedItem) {
|
||||
return;
|
||||
}
|
||||
const inSameList = draggedItem.dataset.sortableListKey === target.dataset.sortableListKey;
|
||||
if (!inSameList) {
|
||||
return;
|
||||
}
|
||||
const targetList = draggedItem.closest('.sortable-list');
|
||||
if (isBefore(draggedItem, target)) {
|
||||
targetList.insertBefore(draggedItem, target);
|
||||
} else {
|
||||
targetList.insertBefore(draggedItem, target.nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
const listItemsHandled = new Map();
|
||||
|
||||
const getListItemsHandled = (list) => {
|
||||
return listItemsHandled.get(list) || new Set();
|
||||
}
|
||||
|
||||
function registerSortableList(list) {
|
||||
list.querySelectorAll('li:not(.immovable)').forEach(item => {
|
||||
const listItems = getListItemsHandled(list);
|
||||
listItems.add(item);
|
||||
listItemsHandled.set(list, listItems);
|
||||
const dragger = item.querySelector('.dragger');
|
||||
dragger.addEventListener('dragstart', e => { sortableItemDragStart(e, item) });
|
||||
dragger.addEventListener('dragend', e => { sortableItemDragEnd(e, item) });
|
||||
item.addEventListener('dragover', e => { sortableItemDragOver(e, item) });
|
||||
});
|
||||
|
||||
const obs = new MutationObserver(records => {
|
||||
for (const mutation of records) {
|
||||
mutation.addedNodes.forEach(node => {
|
||||
if (!(node instanceof HTMLElement)) return;
|
||||
if (!node.classList.contains('sortable-item')) return;
|
||||
const listItems = getListItemsHandled(list);
|
||||
if (listItems.has(node)) return;
|
||||
|
||||
const dragger = node.querySelector('.dragger');
|
||||
dragger.addEventListener('dragstart', e => { sortableItemDragStart(e, item) });
|
||||
dragger.addEventListener('dragend', e => { sortableItemDragEnd(e, item) });
|
||||
node.addEventListener('dragover', e => { sortableItemDragOver(e, node) });
|
||||
listItems.add(node);
|
||||
listItemsHandled.set(list, listItems);
|
||||
});
|
||||
}
|
||||
});
|
||||
obs.observe(list, { childList: true });
|
||||
}
|
||||
|
||||
document.querySelectorAll('.sortable-list').forEach(registerSortableList);
|
||||
|
||||
const listsObs = new MutationObserver(records => {
|
||||
for (const mutation of records) {
|
||||
mutation.addedNodes.forEach(node => {
|
||||
if (!(node instanceof HTMLElement)) return;
|
||||
if (!node.classList.contains('sortable-list')) return;
|
||||
|
||||
registerSortableList(node);
|
||||
});
|
||||
}
|
||||
});
|
||||
listsObs.observe(document.body, { childList: true, subtree: true })
|
||||
}
|
||||
Reference in New Issue
Block a user