mirror of
https://github.com/zadam/trilium.git
synced 2025-10-08 14:42:29 +08:00
chore(react):start porting note map
This commit is contained in:
parent
08fae19d19
commit
b41042fec4
5 changed files with 115 additions and 96 deletions
|
@ -13,85 +13,18 @@ import type FNote from "../entities/fnote.js";
|
||||||
const esc = utils.escapeHtml;
|
const esc = utils.escapeHtml;
|
||||||
|
|
||||||
const TPL = /*html*/`<div class="note-map-widget">
|
const TPL = /*html*/`<div class="note-map-widget">
|
||||||
<style>
|
|
||||||
.note-detail-note-map {
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Style Ui Element to Drag Nodes */
|
|
||||||
.fixnodes-type-switcher {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 10; /* should be below dropdown (note actions) */
|
|
||||||
border-radius: .2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixnodes-type-switcher button.toggled {
|
|
||||||
background: var(--active-item-background-color);
|
|
||||||
color: var(--active-item-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start of styling the slider */
|
|
||||||
.fixnodes-type-switcher input[type="range"] {
|
|
||||||
|
|
||||||
/* removing default appearance */
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
margin-left: 15px;
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Changing slider tracker */
|
|
||||||
.fixnodes-type-switcher input[type="range"]::-webkit-slider-runnable-track {
|
|
||||||
height: 4px;
|
|
||||||
background-color: var(--main-border-color);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Changing Slider Thumb */
|
|
||||||
.fixnodes-type-switcher input[type="range"]::-webkit-slider-thumb {
|
|
||||||
/* removing default appearance */
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
/* creating a custom design */
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
margin-top:-5px;
|
|
||||||
background-color: var(--accented-background-color);
|
|
||||||
border: 1px solid var(--main-text-color);
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixnodes-type-switcher input[type="range"]::-moz-range-track {
|
|
||||||
background-color: var(--main-border-color);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixnodes-type-switcher input[type="range"]::-moz-range-thumb {
|
|
||||||
background-color: var(--accented-background-color);
|
|
||||||
border-color: var(--main-text-color);
|
|
||||||
height: 10px;
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End of styling the slider */
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="btn-group btn-group-sm map-type-switcher content-floating-buttons top-left" role="group">
|
<div class="btn-group btn-group-sm map-type-switcher content-floating-buttons top-left" role="group">
|
||||||
<button type="button" class="btn bx bx-network-chart tn-tool-button" title="${t("note-map.button-link-map")}" data-type="link"></button>
|
<button type="button" class="btn bx bx-network-chart tn-tool-button" title="${t("note-map.button-link-map")}" data-type="link"></button>
|
||||||
<button type="button" class="btn bx bx-sitemap tn-tool-button" title="${t("note-map.button-tree-map")}" data-type="tree"></button>
|
<button type="button" class="btn bx bx-sitemap tn-tool-button" title="${t("note-map.button-tree-map")}" data-type="tree"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<! UI for dragging Notes and link force >
|
<!-- UI for dragging Notes and link force -->
|
||||||
|
|
||||||
<div class="btn-group-sm fixnodes-type-switcher content-floating-buttons bottom-left" role="group">
|
<div class="btn-group-sm fixnodes-type-switcher content-floating-buttons bottom-left" role="group">
|
||||||
<button type="button" data-toggle="button" class="btn bx bx-lock-alt tn-tool-button" title="${t("note_map.fix-nodes")}" data-type="moveable"></button>
|
<button type="button" data-toggle="button" class="btn bx bx-lock-alt tn-tool-button" title="${t("note_map.fix-nodes")}" data-type="moveable"></button>
|
||||||
<input type="range" class="slider" min="1" title="${t("note_map.link-distance")}" max="100" value="40" >
|
<input type="range" class="slider" min="1" title="${t("note_map.link-distance")}" max="100" value="40" >
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="style-resolver"></div>
|
|
||||||
|
|
||||||
<div class="note-map-container"></div>
|
<div class="note-map-container"></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
@ -148,12 +81,6 @@ interface GroupedLink {
|
||||||
names: string[];
|
names: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CssData {
|
|
||||||
fontFamily: string;
|
|
||||||
textColor: string;
|
|
||||||
mutedTextColor: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class NoteMapWidget extends NoteContextAwareWidget {
|
export default class NoteMapWidget extends NoteContextAwareWidget {
|
||||||
|
|
||||||
private fixNodes: boolean;
|
private fixNodes: boolean;
|
||||||
|
@ -220,12 +147,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
|
||||||
async refreshWithNote(note: FNote) {
|
async refreshWithNote(note: FNote) {
|
||||||
this.$widget.show();
|
this.$widget.show();
|
||||||
|
|
||||||
this.cssData = {
|
|
||||||
fontFamily: this.$container.css("font-family"),
|
|
||||||
textColor: this.rgb2hex(this.$container.css("color")),
|
|
||||||
mutedTextColor: this.rgb2hex(this.$styleResolver.css("color"))
|
|
||||||
};
|
|
||||||
|
|
||||||
this.mapType = note.getLabelValue("mapType") === "tree" ? "tree" : "link";
|
this.mapType = note.getLabelValue("mapType") === "tree" ? "tree" : "link";
|
||||||
|
|
||||||
//variables for the hover effekt. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
|
//variables for the hover effekt. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
|
||||||
|
@ -397,13 +318,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb2hex(rgb: string) {
|
|
||||||
return `#${(rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) || [])
|
|
||||||
.slice(1)
|
|
||||||
.map((n) => parseInt(n, 10).toString(16).padStart(2, "0"))
|
|
||||||
.join("")}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setZoomLevel(level: number) {
|
setZoomLevel(level: number) {
|
||||||
this.zoomLevel = level;
|
this.zoomLevel = level;
|
||||||
}
|
}
|
||||||
|
|
62
apps/client/src/widgets/note_map/NoteMap.css
Normal file
62
apps/client/src/widgets/note_map/NoteMap.css
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
.note-detail-note-map {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style Ui Element to Drag Nodes */
|
||||||
|
.fixnodes-type-switcher {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 10; /* should be below dropdown (note actions) */
|
||||||
|
border-radius: .2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixnodes-type-switcher button.toggled {
|
||||||
|
background: var(--active-item-background-color);
|
||||||
|
color: var(--active-item-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start of styling the slider */
|
||||||
|
.fixnodes-type-switcher input[type="range"] {
|
||||||
|
|
||||||
|
/* removing default appearance */
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
margin-left: 15px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Changing slider tracker */
|
||||||
|
.fixnodes-type-switcher input[type="range"]::-webkit-slider-runnable-track {
|
||||||
|
height: 4px;
|
||||||
|
background-color: var(--main-border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Changing Slider Thumb */
|
||||||
|
.fixnodes-type-switcher input[type="range"]::-webkit-slider-thumb {
|
||||||
|
/* removing default appearance */
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
/* creating a custom design */
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
margin-top:-5px;
|
||||||
|
background-color: var(--accented-background-color);
|
||||||
|
border: 1px solid var(--main-text-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixnodes-type-switcher input[type="range"]::-moz-range-track {
|
||||||
|
background-color: var(--main-border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixnodes-type-switcher input[type="range"]::-moz-range-thumb {
|
||||||
|
background-color: var(--accented-background-color);
|
||||||
|
border-color: var(--main-text-color);
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of styling the slider */
|
42
apps/client/src/widgets/note_map/NoteMap.tsx
Normal file
42
apps/client/src/widgets/note_map/NoteMap.tsx
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
import "./NoteMap.css";
|
||||||
|
import { rgb2hex } from "./utils";
|
||||||
|
|
||||||
|
interface CssData {
|
||||||
|
fontFamily: string;
|
||||||
|
textColor: string;
|
||||||
|
mutedTextColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NoteMap() {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const styleResolverRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [ cssData, setCssData ] = useState<CssData>();
|
||||||
|
console.log("Got CSS ", cssData);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!containerRef.current || !styleResolverRef.current) return;
|
||||||
|
setCssData(getCssData(containerRef.current, styleResolverRef.current));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="note-map-widget">
|
||||||
|
<div ref={styleResolverRef} class="style-resolver" />
|
||||||
|
|
||||||
|
<div ref={containerRef} className="note-map-container">
|
||||||
|
Container goes here.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCssData(container: HTMLElement, styleResolver: HTMLElement): CssData {
|
||||||
|
const containerStyle = window.getComputedStyle(container);
|
||||||
|
const styleResolverStyle = window.getComputedStyle(styleResolver);
|
||||||
|
|
||||||
|
return {
|
||||||
|
fontFamily: containerStyle.fontFamily,
|
||||||
|
textColor: rgb2hex(containerStyle.color),
|
||||||
|
mutedTextColor: rgb2hex(styleResolverStyle.color)
|
||||||
|
}
|
||||||
|
}
|
6
apps/client/src/widgets/note_map/utils.ts
Normal file
6
apps/client/src/widgets/note_map/utils.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export function rgb2hex(rgb: string) {
|
||||||
|
return `#${(rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) || [])
|
||||||
|
.slice(1)
|
||||||
|
.map((n) => parseInt(n, 10).toString(16).padStart(2, "0"))
|
||||||
|
.join("")}`;
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
import { TabContext } from "./ribbon-interface";
|
import { TabContext } from "./ribbon-interface";
|
||||||
import NoteMapWidget from "../note_map";
|
|
||||||
import { useElementSize, useLegacyWidget, useWindowSize } from "../react/hooks";
|
import { useElementSize, useLegacyWidget, useWindowSize } from "../react/hooks";
|
||||||
import ActionButton from "../react/ActionButton";
|
import ActionButton from "../react/ActionButton";
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
import NoteMap from "../note_map/NoteMap";
|
||||||
|
|
||||||
const SMALL_SIZE_HEIGHT = "300px";
|
const SMALL_SIZE_HEIGHT = "300px";
|
||||||
|
|
||||||
|
@ -14,11 +14,6 @@ export default function NoteMapTab({ noteContext }: TabContext) {
|
||||||
const { windowHeight } = useWindowSize();
|
const { windowHeight } = useWindowSize();
|
||||||
const containerSize = useElementSize(containerRef);
|
const containerSize = useElementSize(containerRef);
|
||||||
|
|
||||||
const [ noteMapContainer, noteMapWidget ] = useLegacyWidget(() => new NoteMapWidget("ribbon"), {
|
|
||||||
noteContext,
|
|
||||||
containerClassName: "note-map-container"
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isExpanded && containerRef.current && containerSize) {
|
if (isExpanded && containerRef.current && containerSize) {
|
||||||
const height = windowHeight - containerSize.top;
|
const height = windowHeight - containerSize.top;
|
||||||
|
@ -27,11 +22,11 @@ export default function NoteMapTab({ noteContext }: TabContext) {
|
||||||
setHeight(SMALL_SIZE_HEIGHT);
|
setHeight(SMALL_SIZE_HEIGHT);
|
||||||
}
|
}
|
||||||
}, [ isExpanded, containerRef, windowHeight, containerSize?.top ]);
|
}, [ isExpanded, containerRef, windowHeight, containerSize?.top ]);
|
||||||
useEffect(() => noteMapWidget.setDimensions(), [ containerSize?.width, height ]);
|
// useEffect(() => noteMapWidget.setDimensions(), [ containerSize?.width, height ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="note-map-ribbon-widget" style={{ height }} ref={containerRef}>
|
<div className="note-map-ribbon-widget" style={{ height }} ref={containerRef}>
|
||||||
{noteMapContainer}
|
<NoteMap />
|
||||||
|
|
||||||
{!isExpanded ? (
|
{!isExpanded ? (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
|
@ -50,4 +45,4 @@ export default function NoteMapTab({ noteContext }: TabContext) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue