mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-19 16:10:12 +01:00
This commit is contained in:
parent
df94050839
commit
12fccf9349
6 changed files with 112 additions and 21 deletions
|
|
@ -25,7 +25,7 @@ import {selectRow} from "./row";
|
||||||
import * as dayjs from "dayjs";
|
import * as dayjs from "dayjs";
|
||||||
import {openCalcMenu} from "./calc";
|
import {openCalcMenu} from "./calc";
|
||||||
import {avRender} from "./render";
|
import {avRender} from "./render";
|
||||||
import {openViewMenu} from "./view";
|
import {addView, openViewMenu} from "./view";
|
||||||
|
|
||||||
export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
|
export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
|
||||||
const blockElement = hasClosestBlock(event.target);
|
const blockElement = hasClosestBlock(event.target);
|
||||||
|
|
@ -82,7 +82,12 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return true;
|
return true;
|
||||||
} else if (type === "av-sort") {
|
} else if (type === "av-switcher") {
|
||||||
|
openMenuPanel({protyle, blockElement, type: "switcher"});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return true;
|
||||||
|
} else if (type === "av-sort") {
|
||||||
openMenuPanel({protyle, blockElement, type: "sorts"});
|
openMenuPanel({protyle, blockElement, type: "sorts"});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
@ -93,17 +98,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return true;
|
return true;
|
||||||
} else if (type === "av-add") {
|
} else if (type === "av-add") {
|
||||||
const id = Lute.NewNodeID();
|
addView(protyle, blockElement)
|
||||||
const avID = blockElement.getAttribute("data-av-id");
|
|
||||||
transaction(protyle, [{
|
|
||||||
action: "addAttrViewView",
|
|
||||||
avID,
|
|
||||||
id
|
|
||||||
}], [{
|
|
||||||
action: "removeAttrViewView",
|
|
||||||
avID,
|
|
||||||
id
|
|
||||||
}]);
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,15 @@ import {openAsset} from "../../../editor/util";
|
||||||
/// #endif
|
/// #endif
|
||||||
import {previewImage} from "../../preview/image";
|
import {previewImage} from "../../preview/image";
|
||||||
import {assetMenu} from "../../../menus/protyle";
|
import {assetMenu} from "../../../menus/protyle";
|
||||||
import {bindViewEvent, getViewHTML} from "./view";
|
import {addView, bindViewEvent, getSwitcherHTML, getViewHTML, openViewMenu} from "./view";
|
||||||
import {removeBlock} from "../../wysiwyg/remove";
|
import {removeBlock} from "../../wysiwyg/remove";
|
||||||
import {getEditorRange} from "../../util/selection";
|
import {getEditorRange} from "../../util/selection";
|
||||||
|
import {avRender} from "./render";
|
||||||
|
|
||||||
export const openMenuPanel = (options: {
|
export const openMenuPanel = (options: {
|
||||||
protyle: IProtyle,
|
protyle: IProtyle,
|
||||||
blockElement: Element,
|
blockElement: Element,
|
||||||
type: "select" | "properties" | "config" | "sorts" | "filters" | "edit" | "date" | "asset",
|
type: "select" | "properties" | "config" | "sorts" | "filters" | "edit" | "date" | "asset" | "switcher",
|
||||||
colId?: string, // for edit
|
colId?: string, // for edit
|
||||||
cellElements?: HTMLElement[], // for select & date
|
cellElements?: HTMLElement[], // for select & date
|
||||||
cb?: (avPanelElement: Element) => void
|
cb?: (avPanelElement: Element) => void
|
||||||
|
|
@ -51,6 +52,8 @@ export const openMenuPanel = (options: {
|
||||||
html = getPropertiesHTML(data.view);
|
html = getPropertiesHTML(data.view);
|
||||||
} else if (options.type === "sorts") {
|
} else if (options.type === "sorts") {
|
||||||
html = getSortsHTML(data.view.columns, data.view.sorts);
|
html = getSortsHTML(data.view.columns, data.view.sorts);
|
||||||
|
} else if (options.type === "switcher") {
|
||||||
|
html = getSwitcherHTML(data.views, data.viewID);
|
||||||
} else if (options.type === "filters") {
|
} else if (options.type === "filters") {
|
||||||
html = getFiltersHTML(data.view);
|
html = getFiltersHTML(data.view);
|
||||||
} else if (options.type === "select") {
|
} else if (options.type === "select") {
|
||||||
|
|
@ -130,6 +133,8 @@ export const openMenuPanel = (options: {
|
||||||
type = "sorts";
|
type = "sorts";
|
||||||
} else if (targetElement.querySelector('[data-type="removeFilter"]')) {
|
} else if (targetElement.querySelector('[data-type="removeFilter"]')) {
|
||||||
type = "filters";
|
type = "filters";
|
||||||
|
} else if (targetElement.querySelector('[data-type="av-view-edit"]')) {
|
||||||
|
type = "switcher";
|
||||||
} else if (targetElement.querySelector('[data-type="editAssetItem"]')) {
|
} else if (targetElement.querySelector('[data-type="editAssetItem"]')) {
|
||||||
type = "assets";
|
type = "assets";
|
||||||
} else if (targetElement.querySelector('[data-type="setColOption"]')) {
|
} else if (targetElement.querySelector('[data-type="setColOption"]')) {
|
||||||
|
|
@ -213,6 +218,21 @@ export const openMenuPanel = (options: {
|
||||||
bindSortsEvent(options.protyle, menuElement, data);
|
bindSortsEvent(options.protyle, menuElement, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (type === "switcher") {
|
||||||
|
transaction(options.protyle, [{
|
||||||
|
action: "sortAttrViewView",
|
||||||
|
avID,
|
||||||
|
id: sourceId,
|
||||||
|
previousID: isTop ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")
|
||||||
|
}], [{
|
||||||
|
action: "sortAttrViewView",
|
||||||
|
avID,
|
||||||
|
id: sourceId,
|
||||||
|
previousID: sourceElement.previousElementSibling?.getAttribute("data-id")
|
||||||
|
}]);
|
||||||
|
// TODO
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (type === "filters") {
|
if (type === "filters") {
|
||||||
const changeData = data.view.filters;
|
const changeData = data.view.filters;
|
||||||
const oldData = Object.assign([], changeData);
|
const oldData = Object.assign([], changeData);
|
||||||
|
|
@ -905,6 +925,34 @@ export const openMenuPanel = (options: {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
|
} else if (type === "av-add") {
|
||||||
|
addView(options.protyle, options.blockElement);
|
||||||
|
avPanelElement.remove();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (type === "av-view-edit") {
|
||||||
|
if (target.parentElement.querySelector(".b3-chip--primary")) {
|
||||||
|
openViewMenu({
|
||||||
|
protyle: options.protyle,
|
||||||
|
blockElement: options.blockElement as HTMLElement,
|
||||||
|
element: target.parentElement
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
options.blockElement.removeAttribute("data-render");
|
||||||
|
avRender(options.blockElement, options.protyle, () => {
|
||||||
|
openViewMenu({
|
||||||
|
protyle: options.protyle,
|
||||||
|
blockElement: options.blockElement as HTMLElement,
|
||||||
|
element: target.parentElement
|
||||||
|
});
|
||||||
|
avPanelElement.querySelector(".b3-chip--primary").classList.remove("b3-chip--primary")
|
||||||
|
target.parentElement.querySelector(".b3-chip").classList.add("b3-chip--primary")
|
||||||
|
}, target.parentElement.dataset.id);
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
target = target.parentElement;
|
target = target.parentElement;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,16 +221,21 @@ ${cell.color ? `color:${cell.color};` : ""}">${text}</div>`;
|
||||||
<span data-type="av-add" class="block__icon">
|
<span data-type="av-add" class="block__icon">
|
||||||
<svg><use xlink:href="#iconAdd"></use></svg>
|
<svg><use xlink:href="#iconAdd"></use></svg>
|
||||||
</span>
|
</span>
|
||||||
<div class="fn__flex-1 fn__space"></div>
|
<div class="fn__flex-1"></div>
|
||||||
<span data-type="av-filter" class="block__icon${data.filters.length > 0 ? " block__icon--active" : ""}" aria-label="${window.siyuan.languages.filter}">
|
<div class="fn__space"></div>
|
||||||
|
<span data-type="av-switcher" class="block__icon${response.data.views.length > 0 ? "" : " fn__none"}">
|
||||||
|
<svg><use xlink:href="#iconDown"></use></svg>
|
||||||
|
</span>
|
||||||
|
<div class="fn__space"></div>
|
||||||
|
<span data-type="av-filter" class="block__icon${data.filters.length > 0 ? " block__icon--active" : ""}">
|
||||||
<svg><use xlink:href="#iconFilter"></use></svg>
|
<svg><use xlink:href="#iconFilter"></use></svg>
|
||||||
</span>
|
</span>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
<span data-type="av-sort" class="block__icon${data.sorts.length > 0 ? " block__icon--active" : ""}" aria-label="${window.siyuan.languages.sort}">
|
<span data-type="av-sort" class="block__icon${data.sorts.length > 0 ? " block__icon--active" : ""}">
|
||||||
<svg><use xlink:href="#iconSort"></use></svg>
|
<svg><use xlink:href="#iconSort"></use></svg>
|
||||||
</span>
|
</span>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
<span data-type="av-more" class="block__icon" aria-label="${window.siyuan.languages.more}">
|
<span data-type="av-more" class="block__icon">
|
||||||
<svg><use xlink:href="#iconMore"></use></svg>
|
<svg><use xlink:href="#iconMore"></use></svg>
|
||||||
</span>
|
</span>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLEle
|
||||||
icon: "iconEdit",
|
icon: "iconEdit",
|
||||||
label: window.siyuan.languages.rename,
|
label: window.siyuan.languages.rename,
|
||||||
click() {
|
click() {
|
||||||
|
document.querySelector(".av__panel")?.remove();
|
||||||
openMenuPanel({
|
openMenuPanel({
|
||||||
protyle: options.protyle,
|
protyle: options.protyle,
|
||||||
blockElement: options.blockElement,
|
blockElement: options.blockElement,
|
||||||
|
|
@ -28,6 +29,7 @@ export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLEle
|
||||||
icon: "iconSettings",
|
icon: "iconSettings",
|
||||||
label: window.siyuan.languages.config,
|
label: window.siyuan.languages.config,
|
||||||
click() {
|
click() {
|
||||||
|
document.querySelector(".av__panel")?.remove();
|
||||||
openMenuPanel({
|
openMenuPanel({
|
||||||
protyle: options.protyle,
|
protyle: options.protyle,
|
||||||
blockElement: options.blockElement,
|
blockElement: options.blockElement,
|
||||||
|
|
@ -40,6 +42,7 @@ export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLEle
|
||||||
icon: "iconCopy",
|
icon: "iconCopy",
|
||||||
label: window.siyuan.languages.duplicate,
|
label: window.siyuan.languages.duplicate,
|
||||||
click() {
|
click() {
|
||||||
|
document.querySelector(".av__panel")?.remove();
|
||||||
const id = Lute.NewNodeID();
|
const id = Lute.NewNodeID();
|
||||||
transaction(options.protyle, [{
|
transaction(options.protyle, [{
|
||||||
action: "duplicateAttrViewView",
|
action: "duplicateAttrViewView",
|
||||||
|
|
@ -57,7 +60,8 @@ export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLEle
|
||||||
icon: "iconTrashcan",
|
icon: "iconTrashcan",
|
||||||
label: window.siyuan.languages.delete,
|
label: window.siyuan.languages.delete,
|
||||||
click() {
|
click() {
|
||||||
if (options.element.parentElement.querySelectorAll("item").length === 1) {
|
document.querySelector(".av__panel")?.remove();
|
||||||
|
if (options.blockElement.querySelectorAll(".layout-tab-bar .item").length === 1) {
|
||||||
removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement));
|
removeBlock(options.protyle, options.blockElement, getEditorRange(options.blockElement));
|
||||||
} else {
|
} else {
|
||||||
transaction(options.protyle, [{
|
transaction(options.protyle, [{
|
||||||
|
|
@ -147,3 +151,41 @@ export const getViewHTML = (data: IAVTable) => {
|
||||||
</button>
|
</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getSwitcherHTML = (views: IAVView[], viewId: string) => {
|
||||||
|
let html = ""
|
||||||
|
views.forEach((item) => {
|
||||||
|
html += `<button draggable="true" class="b3-menu__item" data-id="${item.id}">
|
||||||
|
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
<span class="b3-chip${item.id === viewId ? " b3-chip--primary" : ""}">
|
||||||
|
${item.icon ? unicode2Emoji(item.icon, "icon", true) : '<svg class="icon"><use xlink:href="#iconTable"></use></svg>'}
|
||||||
|
<span class="fn__ellipsis">${item.name}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<svg class="b3-menu__action" data-type="av-view-edit"><use xlink:href="#iconEdit"></use></svg>
|
||||||
|
</button>`;
|
||||||
|
});
|
||||||
|
return `<div class="b3-menu__items">
|
||||||
|
<button class="b3-menu__item" data-type="av-add">
|
||||||
|
<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__separator"></button>
|
||||||
|
${html}
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addView = (protyle: IProtyle, blockElement: Element) => {
|
||||||
|
const id = Lute.NewNodeID();
|
||||||
|
const avID = blockElement.getAttribute("data-av-id");
|
||||||
|
transaction(protyle, [{
|
||||||
|
action: "addAttrViewView",
|
||||||
|
avID,
|
||||||
|
id
|
||||||
|
}], [{
|
||||||
|
action: "removeAttrViewView",
|
||||||
|
avID,
|
||||||
|
id
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -712,7 +712,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo:
|
||||||
"setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters",
|
"setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters",
|
||||||
"setAttrViewSorts", "setAttrViewColCalc", "removeAttrViewCol", "updateAttrViewColNumberFormat", "removeAttrViewBlock",
|
"setAttrViewSorts", "setAttrViewColCalc", "removeAttrViewCol", "updateAttrViewColNumberFormat", "removeAttrViewBlock",
|
||||||
"replaceAttrViewBlock", "updateAttrViewColTemplate", "setAttrViewColIcon", "setAttrViewColPin", "addAttrViewView",
|
"replaceAttrViewBlock", "updateAttrViewColTemplate", "setAttrViewColIcon", "setAttrViewColPin", "addAttrViewView",
|
||||||
"removeAttrViewView", "setAttrViewViewName", "setAttrViewViewIcon", "duplicateAttrViewView"].includes(operation.action)) {
|
"removeAttrViewView", "setAttrViewViewName", "setAttrViewViewIcon", "duplicateAttrViewView", "sortAttrViewView"].includes(operation.action)) {
|
||||||
refreshAV(protyle, operation, isUndo);
|
refreshAV(protyle, operation, isUndo);
|
||||||
} else if (operation.action === "doUpdateUpdated") {
|
} else if (operation.action === "doUpdateUpdated") {
|
||||||
updateElements.forEach(item => {
|
updateElements.forEach(item => {
|
||||||
|
|
|
||||||
1
app/src/types/index.d.ts
vendored
1
app/src/types/index.d.ts
vendored
|
|
@ -47,6 +47,7 @@ type TOperation =
|
||||||
| "removeAttrViewView"
|
| "removeAttrViewView"
|
||||||
| "setAttrViewViewIcon"
|
| "setAttrViewViewIcon"
|
||||||
| "duplicateAttrViewView"
|
| "duplicateAttrViewView"
|
||||||
|
| "sortAttrViewView"
|
||||||
type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins"
|
type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins"
|
||||||
type TCardType = "doc" | "notebook" | "all"
|
type TCardType = "doc" | "notebook" | "all"
|
||||||
type TEventBus = "ws-main" |
|
type TEventBus = "ws-main" |
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue