siyuan/app/src/protyle/render/av/sort.ts
Silent Lee 8a354da50a
Add database lineNumber field type (#11008)
* 🎨 add database lineNumber type

* 🎨 fix https://github.com/siyuan-note/siyuan/issues/10896

* 🎨 Improve mobile app appearance language https://github.com/siyuan-note/siyuan/issues/11009

* 🎨 Improve database template field calc https://github.com/siyuan-note/siyuan/issues/11011

* ⬆️ Upgrade kernel deps

* ⬆️ Upgrade kernel deps

* 🎨 fix https://github.com/siyuan-note/siyuan/issues/10896

* 🎨 fix https://github.com/siyuan-note/siyuan/issues/10896

* 🐛 https://github.com/siyuan-note/siyuan/issues/11015

* 🐛 https://github.com/siyuan-note/siyuan/issues/11018

* 🐛 https://github.com/siyuan-note/siyuan/issues/11018

* 🎨 刚创建时无 id,更新需和 oldValue 保持一致

* 🐛 Database date field between filter calculation error Fix https://github.com/siyuan-note/siyuan/issues/10979

* 🐛 Primary key value unexpectedly updated when database adds row https://github.com/siyuan-note/siyuan/issues/11018

* 🎨 https://github.com/siyuan-note/siyuan/issues/11013

* 🎨 搜索可汇总字段时排除行号类型字段 https://github.com/siyuan-note/siyuan/pull/11008

* 🎨 lineNumber no need to join the calc op and remove useless todo tag

---------

Co-authored-by: Vanessa <lly219@gmail.com>
Co-authored-by: Daniel <845765@qq.com>
2024-04-15 00:49:48 +08:00

139 lines
5.7 KiB
TypeScript

import {Menu} from "../../../plugin/Menu";
import {getColIconByType} from "./col";
import {transaction} from "../../wysiwyg/transaction";
import {setPosition} from "../../../util/setPosition";
import {unicode2Emoji} from "../../../emoji";
export const addSort = (options: {
data: IAV,
rect: DOMRect,
menuElement: HTMLElement,
tabRect: DOMRect,
avId: string,
protyle: IProtyle,
blockID: string,
}) => {
const menu = new Menu("av-add-sort");
options.data.view.columns.forEach((column) => {
let hasSort = false;
// 如果该列是行号类型列,不允许添加排序
if (column.type === "lineNumber") {
hasSort = true;
} else {
options.data.view.sorts.find((sort) => {
if (sort.column === column.id) {
hasSort = true;
return true;
}
});
}
if (!hasSort) {
menu.addItem({
label: column.name,
iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`,
click: () => {
const oldSorts = Object.assign([], options.data.view.sorts);
options.data.view.sorts.push({
column: column.id,
order: "ASC",
});
transaction(options.protyle, [{
action: "setAttrViewSorts",
avID: options.data.id,
data: options.data.view.sorts,
blockID: options.blockID,
}], [{
action: "setAttrViewSorts",
avID: options.data.id,
data: oldSorts,
blockID: options.blockID,
}]);
options.menuElement.innerHTML = getSortsHTML(options.data.view.columns, options.data.view.sorts);
bindSortsEvent(options.protyle, options.menuElement, options.data, options.blockID);
setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height);
}
});
}
});
menu.open({
x: options.rect.left,
y: options.rect.bottom,
h: options.rect.height,
});
};
export const bindSortsEvent = (protyle: IProtyle, menuElement: HTMLElement, data: IAV, blockID: string) => {
menuElement.querySelectorAll("select").forEach((item: HTMLSelectElement) => {
item.addEventListener("change", () => {
const colId = item.parentElement.getAttribute("data-id");
const oldSort = JSON.parse(JSON.stringify(data.view.sorts));
if (item.previousElementSibling.classList.contains("b3-menu__icon")) {
data.view.sorts.find((sort: IAVSort) => {
if (sort.column === colId) {
sort.column = item.value;
item.parentElement.setAttribute("data-id", item.value);
return true;
}
});
} else {
data.view.sorts.find((sort: IAVSort) => sort.column === colId).order = item.value as "ASC" | "DESC";
}
transaction(protyle, [{
action: "setAttrViewSorts",
avID: data.id,
data: data.view.sorts,
blockID
}], [{
action: "setAttrViewSorts",
avID: data.id,
data: oldSort,
blockID
}]);
});
});
};
export const getSortsHTML = (columns: IAVColumn[], sorts: IAVSort[]) => {
let html = "";
const genSortItem = (id: string) => {
let sortHTML = "";
columns.forEach((item) => {
sortHTML += `<option value="${item.id}" ${item.id === id ? "selected" : ""}>${item.icon && unicode2Emoji(item.icon)}${item.name}</option>`;
});
return sortHTML;
};
sorts.forEach((item: IAVSort) => {
html += `<button draggable="true" class="b3-menu__item" data-id="${item.column}">
<svg class="b3-menu__icon fn__grab"><use xlink:href="#iconDrag"></use></svg>
<select class="b3-select" style="margin: 4px 0">
${genSortItem(item.column)}
</select>
<span class="fn__space"></span>
<select class="b3-select" style="margin: 4px 0">
<option value="ASC" ${item.order === "ASC" ? "selected" : ""}>${window.siyuan.languages.asc}</option>
<option value="DESC" ${item.order === "DESC" ? "selected" : ""}>${window.siyuan.languages.desc}</option>
</select>
<svg class="b3-menu__action" data-type="removeSort"><use xlink:href="#iconTrashcan"></use></svg>
</button>`;
});
return `<div class="b3-menu__items">
<button class="b3-menu__item" data-type="nobg">
<span class="block__icon" style="padding: 8px;margin-left: -4px;" data-type="go-config">
<svg><use xlink:href="#iconLeft"></use></svg>
</span>
<span class="b3-menu__label ft__center">${window.siyuan.languages.sort}</span>
</button>
<button class="b3-menu__separator"></button>
${html}
<button class="b3-menu__item${sorts.length === columns.length ? " fn__none" : ""}" data-type="addSort">
<svg class="b3-menu__icon"><use xlink:href="#iconAdd"></use></svg>
<span class="b3-menu__label">${window.siyuan.languages.new}</span>
</button>
<button class="b3-menu__item${html ? "" : " fn__none"}" data-type="removeSorts">
<svg class="b3-menu__icon"><use xlink:href="#iconTrashcan"></use></svg>
<span class="b3-menu__label">${window.siyuan.languages.delete}</span>
</button>
</div>`;
};