kyp-mem 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +227 -78
- package/kyp_mem/__init__.py +1 -1
- package/kyp_mem/cli.py +30 -4
- package/kyp_mem/hooks.py +73 -1
- package/kyp_mem/server.py +76 -2
- package/kyp_mem/static/index.html +683 -177
- package/kyp_mem/ui.py +22 -0
- package/kyp_mem/vault.py +15 -0
- package/kyp_mem/vector.py +43 -0
- package/package.json +1 -1
- package/pyproject.toml +2 -1
|
@@ -34,16 +34,16 @@
|
|
|
34
34
|
|
|
35
35
|
--text-primary: #d8d5cf;
|
|
36
36
|
--text-secondary: #807b73;
|
|
37
|
-
--text-muted: #
|
|
38
|
-
--border:
|
|
39
|
-
--border-subtle:
|
|
37
|
+
--text-muted: #55514a;
|
|
38
|
+
--border: rgba(255,255,255,0.06);
|
|
39
|
+
--border-subtle: rgba(255,255,255,0.03);
|
|
40
40
|
|
|
41
41
|
--font: 'Inter', -apple-system, sans-serif;
|
|
42
42
|
--font-mono: 'JetBrains Mono', monospace;
|
|
43
43
|
|
|
44
44
|
--radius-sm: 4px;
|
|
45
|
-
--radius:
|
|
46
|
-
--radius-lg:
|
|
45
|
+
--radius: 8px;
|
|
46
|
+
--radius-lg: 12px;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
body {
|
|
52
52
|
font-family: var(--font);
|
|
53
53
|
background: var(--bg-void);
|
|
54
|
+
background-image: radial-gradient(circle at 50% 0%, var(--bg-secondary) 0%, var(--bg-void) 70%);
|
|
54
55
|
color: var(--text-primary);
|
|
55
56
|
height: 100vh;
|
|
56
57
|
overflow: hidden;
|
|
@@ -62,8 +63,8 @@ body::before {
|
|
|
62
63
|
position: fixed;
|
|
63
64
|
inset: 0;
|
|
64
65
|
background-image:
|
|
65
|
-
linear-gradient(rgba(217,119,87,0.
|
|
66
|
-
linear-gradient(90deg, rgba(217,119,87,0.
|
|
66
|
+
linear-gradient(rgba(217,119,87,0.012) 1px, transparent 1px),
|
|
67
|
+
linear-gradient(90deg, rgba(217,119,87,0.012) 1px, transparent 1px);
|
|
67
68
|
background-size: 48px 48px;
|
|
68
69
|
pointer-events: none;
|
|
69
70
|
z-index: 0;
|
|
@@ -113,7 +114,9 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
113
114
|
/* ============ HEADER ============ */
|
|
114
115
|
.header {
|
|
115
116
|
grid-column: 1 / -1;
|
|
116
|
-
background:
|
|
117
|
+
background: rgba(8,8,10,0.6);
|
|
118
|
+
backdrop-filter: blur(12px);
|
|
119
|
+
-webkit-backdrop-filter: blur(12px);
|
|
117
120
|
border-bottom: 1px solid var(--border);
|
|
118
121
|
display: flex;
|
|
119
122
|
align-items: center;
|
|
@@ -309,24 +312,27 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
309
312
|
.quick-switcher-overlay {
|
|
310
313
|
position: fixed;
|
|
311
314
|
inset: 0;
|
|
312
|
-
background: rgba(6,6,12,0.
|
|
315
|
+
background: rgba(6,6,12,0.6);
|
|
313
316
|
z-index: 200;
|
|
314
317
|
display: none;
|
|
315
318
|
align-items: flex-start;
|
|
316
319
|
justify-content: center;
|
|
317
320
|
padding-top: 15vh;
|
|
318
|
-
backdrop-filter: blur(
|
|
321
|
+
backdrop-filter: blur(12px);
|
|
322
|
+
-webkit-backdrop-filter: blur(12px);
|
|
319
323
|
}
|
|
320
324
|
|
|
321
325
|
.quick-switcher-overlay.active { display: flex; }
|
|
322
326
|
|
|
323
327
|
.quick-switcher {
|
|
324
328
|
width: 480px;
|
|
325
|
-
background:
|
|
329
|
+
background: rgba(17,17,22,0.85);
|
|
326
330
|
border: 1px solid var(--border);
|
|
327
331
|
border-radius: var(--radius-lg);
|
|
328
|
-
box-shadow: 0
|
|
332
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.8), 0 0 0 1px rgba(217,119,87,0.1);
|
|
329
333
|
overflow: hidden;
|
|
334
|
+
backdrop-filter: blur(20px);
|
|
335
|
+
-webkit-backdrop-filter: blur(20px);
|
|
330
336
|
}
|
|
331
337
|
|
|
332
338
|
.quick-switcher input {
|
|
@@ -657,119 +663,132 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
657
663
|
|
|
658
664
|
/* ============ MARKDOWN ============ */
|
|
659
665
|
.md-body h1 {
|
|
660
|
-
font-size:
|
|
666
|
+
font-size: 28px;
|
|
661
667
|
font-weight: 700;
|
|
662
|
-
margin: 0 0
|
|
668
|
+
margin: 0 0 28px;
|
|
663
669
|
color: var(--text-primary);
|
|
664
|
-
letter-spacing: -0.
|
|
670
|
+
letter-spacing: -0.5px;
|
|
671
|
+
text-shadow: 0 0 15px rgba(255,255,255,0.05);
|
|
665
672
|
}
|
|
666
673
|
|
|
667
674
|
.md-body h2 {
|
|
668
|
-
font-size:
|
|
675
|
+
font-size: 20px;
|
|
669
676
|
font-weight: 600;
|
|
670
|
-
margin:
|
|
677
|
+
margin: 40px 0 16px;
|
|
671
678
|
color: var(--text-primary);
|
|
672
|
-
padding-bottom:
|
|
673
|
-
border-bottom: 1px solid var(--border
|
|
679
|
+
padding-bottom: 10px;
|
|
680
|
+
border-bottom: 1px solid var(--border);
|
|
674
681
|
}
|
|
675
682
|
|
|
676
683
|
.md-body h3 {
|
|
677
|
-
font-size:
|
|
684
|
+
font-size: 16px;
|
|
678
685
|
font-weight: 600;
|
|
679
|
-
margin:
|
|
686
|
+
margin: 32px 0 12px;
|
|
680
687
|
color: var(--neon-purple);
|
|
688
|
+
text-shadow: 0 0 8px rgba(168,139,250,0.2);
|
|
681
689
|
}
|
|
682
690
|
|
|
683
691
|
.md-body p {
|
|
684
|
-
line-height: 1.
|
|
685
|
-
margin:
|
|
692
|
+
line-height: 1.9;
|
|
693
|
+
margin: 12px 0;
|
|
686
694
|
color: var(--text-secondary);
|
|
687
|
-
font-size:
|
|
695
|
+
font-size: 14px;
|
|
688
696
|
}
|
|
689
697
|
|
|
690
|
-
.md-body ul, .md-body ol { padding-left: 24px; margin:
|
|
698
|
+
.md-body ul, .md-body ol { padding-left: 24px; margin: 12px 0; }
|
|
691
699
|
|
|
692
700
|
.md-body li {
|
|
693
|
-
line-height: 1.
|
|
701
|
+
line-height: 1.9;
|
|
694
702
|
color: var(--text-secondary);
|
|
695
|
-
margin:
|
|
696
|
-
font-size:
|
|
703
|
+
margin: 4px 0;
|
|
704
|
+
font-size: 14px;
|
|
697
705
|
}
|
|
698
706
|
|
|
699
707
|
.md-body li::marker { color: var(--text-muted); }
|
|
700
708
|
|
|
701
|
-
.md-body a { color: var(--neon-blue); text-decoration: none; }
|
|
702
|
-
.md-body a:hover { text-decoration: underline; }
|
|
709
|
+
.md-body a { color: var(--neon-blue); text-decoration: none; transition: color 0.2s; }
|
|
710
|
+
.md-body a:hover { color: var(--neon-cyan); text-decoration: underline; }
|
|
703
711
|
|
|
704
712
|
.md-body strong { color: var(--text-primary); font-weight: 600; }
|
|
705
713
|
|
|
706
714
|
.md-body code {
|
|
707
|
-
background: var(--bg-
|
|
708
|
-
padding:
|
|
709
|
-
border-radius:
|
|
715
|
+
background: var(--bg-hover);
|
|
716
|
+
padding: 3px 6px;
|
|
717
|
+
border-radius: 4px;
|
|
710
718
|
font-family: var(--font-mono);
|
|
711
|
-
font-size:
|
|
719
|
+
font-size: 12.5px;
|
|
712
720
|
color: var(--neon-orange);
|
|
713
|
-
border: 1px solid var(--border
|
|
721
|
+
border: 1px solid var(--border);
|
|
714
722
|
}
|
|
715
723
|
|
|
716
724
|
.md-body pre {
|
|
717
|
-
background:
|
|
725
|
+
background: rgba(8,8,10,0.4);
|
|
718
726
|
border: 1px solid var(--border);
|
|
719
|
-
border-radius: var(--radius);
|
|
720
|
-
padding:
|
|
727
|
+
border-radius: var(--radius-lg);
|
|
728
|
+
padding: 20px;
|
|
721
729
|
overflow-x: auto;
|
|
722
|
-
margin:
|
|
730
|
+
margin: 20px 0;
|
|
731
|
+
box-shadow: inset 0 2px 10px rgba(0,0,0,0.2);
|
|
723
732
|
}
|
|
724
733
|
|
|
725
734
|
.md-body pre code {
|
|
726
735
|
background: none;
|
|
727
736
|
padding: 0;
|
|
728
737
|
border: none;
|
|
729
|
-
color:
|
|
730
|
-
font-size:
|
|
731
|
-
line-height: 1.
|
|
738
|
+
color: #c9c7c2;
|
|
739
|
+
font-size: 12.5px;
|
|
740
|
+
line-height: 1.8;
|
|
732
741
|
}
|
|
733
742
|
|
|
734
743
|
.md-body table {
|
|
735
744
|
width: 100%;
|
|
736
|
-
border-collapse:
|
|
737
|
-
|
|
738
|
-
|
|
745
|
+
border-collapse: separate;
|
|
746
|
+
border-spacing: 0;
|
|
747
|
+
margin: 24px 0;
|
|
748
|
+
font-size: 13px;
|
|
749
|
+
border: 1px solid var(--border);
|
|
750
|
+
border-radius: var(--radius);
|
|
751
|
+
overflow: hidden;
|
|
739
752
|
}
|
|
740
753
|
|
|
741
754
|
.md-body th {
|
|
742
755
|
text-align: left;
|
|
743
|
-
padding:
|
|
756
|
+
padding: 12px 16px;
|
|
744
757
|
border-bottom: 1px solid var(--border);
|
|
745
|
-
|
|
758
|
+
background: rgba(255,255,255,0.02);
|
|
759
|
+
color: var(--text-primary);
|
|
746
760
|
font-family: var(--font-mono);
|
|
747
761
|
font-weight: 600;
|
|
748
|
-
font-size:
|
|
762
|
+
font-size: 11px;
|
|
749
763
|
text-transform: uppercase;
|
|
750
764
|
letter-spacing: 0.5px;
|
|
751
765
|
}
|
|
752
766
|
|
|
753
767
|
.md-body td {
|
|
754
|
-
padding:
|
|
755
|
-
border-bottom: 1px solid var(--border
|
|
768
|
+
padding: 12px 16px;
|
|
769
|
+
border-bottom: 1px solid var(--border);
|
|
756
770
|
color: var(--text-secondary);
|
|
771
|
+
transition: background 0.15s;
|
|
757
772
|
}
|
|
758
773
|
|
|
759
|
-
.md-body tr:
|
|
774
|
+
.md-body tr:last-child td { border-bottom: none; }
|
|
775
|
+
.md-body tr:hover td { background: var(--bg-hover); color: var(--text-primary); }
|
|
760
776
|
|
|
761
777
|
.md-body blockquote {
|
|
762
|
-
border-left:
|
|
763
|
-
padding
|
|
764
|
-
margin:
|
|
765
|
-
color: var(--text-
|
|
778
|
+
border-left: 3px solid var(--neon-purple);
|
|
779
|
+
padding: 12px 20px;
|
|
780
|
+
margin: 20px 0;
|
|
781
|
+
color: var(--text-secondary);
|
|
782
|
+
background: linear-gradient(90deg, rgba(168,139,250,0.05), transparent);
|
|
783
|
+
border-radius: 0 var(--radius) var(--radius) 0;
|
|
784
|
+
font-style: italic;
|
|
766
785
|
}
|
|
767
786
|
|
|
768
787
|
.md-body hr {
|
|
769
788
|
border: none;
|
|
770
789
|
height: 1px;
|
|
771
|
-
background: var(--border);
|
|
772
|
-
margin:
|
|
790
|
+
background: linear-gradient(90deg, transparent, var(--border), transparent);
|
|
791
|
+
margin: 36px 0;
|
|
773
792
|
}
|
|
774
793
|
|
|
775
794
|
.wikilink {
|
|
@@ -840,15 +859,40 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
840
859
|
|
|
841
860
|
.rp-section-title {
|
|
842
861
|
font-family: var(--font-mono);
|
|
843
|
-
font-size:
|
|
862
|
+
font-size: 10px;
|
|
844
863
|
font-weight: 600;
|
|
845
864
|
text-transform: uppercase;
|
|
846
865
|
letter-spacing: 1.5px;
|
|
847
|
-
color: var(--text-
|
|
866
|
+
color: var(--text-secondary);
|
|
848
867
|
margin-bottom: 8px;
|
|
849
868
|
display: flex;
|
|
850
869
|
align-items: center;
|
|
851
870
|
gap: 6px;
|
|
871
|
+
cursor: pointer;
|
|
872
|
+
padding: 4px 6px;
|
|
873
|
+
border-radius: var(--radius-sm);
|
|
874
|
+
transition: background 0.15s;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
.rp-section-title:hover {
|
|
878
|
+
background: var(--bg-hover);
|
|
879
|
+
color: var(--text-primary);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.rp-section-title .arrow {
|
|
883
|
+
margin-left: auto;
|
|
884
|
+
font-size: 8px;
|
|
885
|
+
color: var(--text-muted);
|
|
886
|
+
transition: transform 0.2s;
|
|
887
|
+
transform: rotate(90deg);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.rp-section.collapsed .rp-section-title .arrow {
|
|
891
|
+
transform: rotate(0deg);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
.rp-section.collapsed .rp-section-body {
|
|
895
|
+
display: none;
|
|
852
896
|
}
|
|
853
897
|
|
|
854
898
|
.rp-section-title .rp-count {
|
|
@@ -915,16 +959,37 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
915
959
|
.outline-item.h3 { padding-left: 20px; font-size: 10px; color: var(--text-muted); }
|
|
916
960
|
|
|
917
961
|
/* ============ GRAPH ============ */
|
|
918
|
-
#graph-section { margin-bottom: 12px; }
|
|
962
|
+
#graph-section { margin-bottom: 12px; transition: all 0.3s; }
|
|
919
963
|
#graph-section.hidden { display: none; }
|
|
920
964
|
|
|
965
|
+
#graph-section.maximized {
|
|
966
|
+
position: fixed;
|
|
967
|
+
inset: 40px;
|
|
968
|
+
z-index: 250;
|
|
969
|
+
background: rgba(17,17,22,0.95);
|
|
970
|
+
border: 1px solid var(--border);
|
|
971
|
+
border-radius: var(--radius-lg);
|
|
972
|
+
padding: 20px;
|
|
973
|
+
display: flex;
|
|
974
|
+
flex-direction: column;
|
|
975
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.8), 0 0 0 1px rgba(217,119,87,0.3);
|
|
976
|
+
backdrop-filter: blur(20px);
|
|
977
|
+
-webkit-backdrop-filter: blur(20px);
|
|
978
|
+
}
|
|
979
|
+
|
|
921
980
|
#graph-container {
|
|
922
981
|
width: 100%;
|
|
923
982
|
height: 200px;
|
|
924
|
-
border: 1px solid var(--border
|
|
983
|
+
border: 1px solid var(--border);
|
|
925
984
|
border-radius: var(--radius);
|
|
926
985
|
overflow: hidden;
|
|
927
|
-
background:
|
|
986
|
+
background: transparent;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
#graph-section.maximized #graph-container {
|
|
990
|
+
flex: 1;
|
|
991
|
+
height: auto !important;
|
|
992
|
+
border: none;
|
|
928
993
|
}
|
|
929
994
|
|
|
930
995
|
#graph-container svg { width: 100%; height: 100%; }
|
|
@@ -933,30 +998,39 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
933
998
|
|
|
934
999
|
.graph-node circle {
|
|
935
1000
|
fill: var(--neon-purple);
|
|
936
|
-
filter: drop-shadow(0 0
|
|
937
|
-
transition: all 0.
|
|
1001
|
+
filter: drop-shadow(0 0 3px rgba(168,139,250,0.5));
|
|
1002
|
+
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
938
1003
|
}
|
|
939
1004
|
|
|
940
1005
|
.graph-node:hover circle {
|
|
941
1006
|
fill: var(--neon-cyan);
|
|
942
|
-
|
|
1007
|
+
r: 8;
|
|
1008
|
+
filter: drop-shadow(0 0 8px rgba(217,119,87,0.7));
|
|
943
1009
|
}
|
|
944
1010
|
|
|
945
1011
|
.graph-node.active circle {
|
|
946
1012
|
fill: var(--neon-cyan);
|
|
947
|
-
|
|
948
|
-
filter: drop-shadow(0 0 6px rgba(217,119,87,0.5));
|
|
1013
|
+
filter: drop-shadow(0 0 10px rgba(217,119,87,0.9));
|
|
949
1014
|
}
|
|
950
1015
|
|
|
951
1016
|
.graph-node text {
|
|
952
1017
|
fill: var(--text-muted);
|
|
953
1018
|
font-family: var(--font-mono);
|
|
954
|
-
font-size:
|
|
1019
|
+
font-size: 11px;
|
|
1020
|
+
pointer-events: none;
|
|
1021
|
+
transition: all 0.2s;
|
|
1022
|
+
text-shadow: 0 0 2px var(--bg-primary), 0 0 4px var(--bg-primary);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.graph-node:hover text, .graph-node.active text {
|
|
1026
|
+
fill: var(--text-primary);
|
|
1027
|
+
font-size: 13px;
|
|
955
1028
|
}
|
|
956
1029
|
|
|
957
1030
|
.graph-link {
|
|
958
|
-
stroke:
|
|
959
|
-
stroke-width: 1;
|
|
1031
|
+
stroke: var(--neon-purple);
|
|
1032
|
+
stroke-width: 1.5;
|
|
1033
|
+
transition: opacity 0.3s;
|
|
960
1034
|
}
|
|
961
1035
|
|
|
962
1036
|
.graph-size-controls {
|
|
@@ -1011,10 +1085,186 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1011
1085
|
background: var(--neon-cyan);
|
|
1012
1086
|
}
|
|
1013
1087
|
|
|
1014
|
-
/* ============ SESSIONS ============ */
|
|
1015
|
-
.
|
|
1088
|
+
/* ============ SESSIONS PILLAR ============ */
|
|
1089
|
+
.pillar-divider {
|
|
1090
|
+
height: 1px;
|
|
1091
|
+
margin: 4px 12px;
|
|
1092
|
+
background: linear-gradient(90deg, transparent, var(--border), transparent);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.pillar-label {
|
|
1096
|
+
font-family: var(--font-mono);
|
|
1097
|
+
font-size: 8px;
|
|
1098
|
+
font-weight: 700;
|
|
1099
|
+
text-transform: uppercase;
|
|
1100
|
+
letter-spacing: 2px;
|
|
1101
|
+
color: var(--text-muted);
|
|
1102
|
+
padding: 10px 18px 4px;
|
|
1103
|
+
display: flex;
|
|
1104
|
+
align-items: center;
|
|
1105
|
+
justify-content: space-between;
|
|
1106
|
+
user-select: none;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
.pillar-label .pillar-accent {
|
|
1110
|
+
width: 6px;
|
|
1111
|
+
height: 6px;
|
|
1112
|
+
border-radius: 50%;
|
|
1113
|
+
display: inline-block;
|
|
1114
|
+
margin-right: 6px;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
.pillar-label .pillar-accent.sessions { background: var(--neon-green); box-shadow: 0 0 6px var(--neon-green); }
|
|
1118
|
+
.pillar-label .pillar-accent.projects { background: var(--neon-cyan); box-shadow: 0 0 6px var(--neon-cyan); }
|
|
1119
|
+
|
|
1120
|
+
.pillar-label .pillar-action {
|
|
1121
|
+
font-size: 9px;
|
|
1122
|
+
font-weight: 500;
|
|
1123
|
+
color: var(--text-muted);
|
|
1124
|
+
cursor: pointer;
|
|
1125
|
+
padding: 1px 6px;
|
|
1126
|
+
border-radius: 3px;
|
|
1127
|
+
border: 1px solid transparent;
|
|
1128
|
+
transition: all 0.15s;
|
|
1129
|
+
letter-spacing: 0.5px;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
.pillar-label .pillar-action:hover {
|
|
1133
|
+
color: var(--neon-green);
|
|
1134
|
+
border-color: rgba(91,185,140,0.3);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
.session-search-box {
|
|
1138
|
+
padding: 6px 12px 4px;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
.session-search-box input {
|
|
1142
|
+
width: 100%;
|
|
1143
|
+
background: rgba(8,8,10,0.4);
|
|
1144
|
+
border: 1px solid var(--border);
|
|
1145
|
+
color: var(--text-primary);
|
|
1146
|
+
font-family: var(--font-mono);
|
|
1147
|
+
font-size: 10px;
|
|
1148
|
+
padding: 5px 10px 5px 24px;
|
|
1149
|
+
border-radius: var(--radius);
|
|
1150
|
+
outline: none;
|
|
1151
|
+
transition: all 0.2s;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
.session-search-box input::placeholder { color: var(--text-muted); }
|
|
1155
|
+
|
|
1156
|
+
.session-search-box input:focus {
|
|
1157
|
+
border-color: rgba(91,185,140,0.4);
|
|
1158
|
+
box-shadow: 0 0 8px rgba(91,185,140,0.08);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
.session-search-box {
|
|
1162
|
+
position: relative;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
.session-search-box .ss-icon {
|
|
1166
|
+
position: absolute;
|
|
1167
|
+
left: 20px;
|
|
1168
|
+
top: 50%;
|
|
1169
|
+
transform: translateY(-50%);
|
|
1170
|
+
color: var(--text-muted);
|
|
1171
|
+
font-size: 10px;
|
|
1172
|
+
pointer-events: none;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
.session-search-results {
|
|
1176
|
+
padding: 0 8px;
|
|
1177
|
+
max-height: 180px;
|
|
1178
|
+
overflow-y: auto;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
.session-search-results:empty { display: none; }
|
|
1182
|
+
|
|
1183
|
+
.ss-result {
|
|
1184
|
+
padding: 5px 10px;
|
|
1185
|
+
border-radius: var(--radius-sm);
|
|
1186
|
+
cursor: pointer;
|
|
1187
|
+
margin: 1px 0;
|
|
1188
|
+
transition: background 0.1s;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
.ss-result:hover { background: var(--bg-hover); }
|
|
1192
|
+
|
|
1193
|
+
.ss-result .ss-title {
|
|
1194
|
+
font-size: 11px;
|
|
1195
|
+
color: var(--neon-green);
|
|
1196
|
+
font-weight: 500;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
.ss-result .ss-meta {
|
|
1200
|
+
font-family: var(--font-mono);
|
|
1201
|
+
font-size: 9px;
|
|
1202
|
+
color: var(--text-muted);
|
|
1203
|
+
margin-top: 1px;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
.ss-result .ss-snippet {
|
|
1207
|
+
font-size: 10px;
|
|
1208
|
+
color: var(--text-secondary);
|
|
1209
|
+
margin-top: 2px;
|
|
1210
|
+
overflow: hidden;
|
|
1211
|
+
text-overflow: ellipsis;
|
|
1212
|
+
white-space: nowrap;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.session-project-group {
|
|
1216
|
+
padding: 0 8px;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
.session-project-header {
|
|
1220
|
+
display: flex;
|
|
1221
|
+
align-items: center;
|
|
1222
|
+
padding: 5px 10px;
|
|
1223
|
+
border-radius: var(--radius-sm);
|
|
1224
|
+
cursor: pointer;
|
|
1225
|
+
gap: 6px;
|
|
1226
|
+
user-select: none;
|
|
1227
|
+
transition: background 0.1s;
|
|
1228
|
+
margin: 1px 0;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
.session-project-header:hover { background: var(--bg-hover); }
|
|
1232
|
+
|
|
1233
|
+
.session-project-header .sp-arrow {
|
|
1234
|
+
width: 12px;
|
|
1235
|
+
font-size: 8px;
|
|
1236
|
+
color: var(--text-muted);
|
|
1237
|
+
text-align: center;
|
|
1238
|
+
flex-shrink: 0;
|
|
1239
|
+
transition: transform 0.15s;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.session-project-header .sp-arrow.open { transform: rotate(90deg); }
|
|
1243
|
+
|
|
1244
|
+
.session-project-header .sp-icon {
|
|
1245
|
+
font-size: 11px;
|
|
1246
|
+
color: var(--neon-green);
|
|
1247
|
+
flex-shrink: 0;
|
|
1248
|
+
opacity: 0.7;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
.session-project-header .sp-name {
|
|
1252
|
+
font-size: 12px;
|
|
1253
|
+
color: var(--text-primary);
|
|
1254
|
+
font-weight: 500;
|
|
1255
|
+
flex: 1;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
.session-project-header .sp-count {
|
|
1259
|
+
font-family: var(--font-mono);
|
|
1260
|
+
font-size: 9px;
|
|
1261
|
+
color: var(--text-muted);
|
|
1262
|
+
background: rgba(91,185,140,0.06);
|
|
1263
|
+
padding: 1px 5px;
|
|
1264
|
+
border-radius: 3px;
|
|
1265
|
+
}
|
|
1016
1266
|
|
|
1017
|
-
.session-
|
|
1267
|
+
.session-project-header .sp-add {
|
|
1018
1268
|
background: transparent;
|
|
1019
1269
|
border: 1px solid var(--border);
|
|
1020
1270
|
color: var(--text-muted);
|
|
@@ -1024,7 +1274,6 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1024
1274
|
height: 16px;
|
|
1025
1275
|
border-radius: 3px;
|
|
1026
1276
|
cursor: pointer;
|
|
1027
|
-
margin-left: auto;
|
|
1028
1277
|
display: none;
|
|
1029
1278
|
align-items: center;
|
|
1030
1279
|
justify-content: center;
|
|
@@ -1033,13 +1282,62 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1033
1282
|
line-height: 1;
|
|
1034
1283
|
}
|
|
1035
1284
|
|
|
1036
|
-
.
|
|
1285
|
+
.session-project-header:hover .sp-add { display: flex; }
|
|
1286
|
+
.session-project-header .sp-add:hover { border-color: var(--neon-green); color: var(--neon-green); }
|
|
1037
1287
|
|
|
1038
|
-
.session-
|
|
1039
|
-
|
|
1288
|
+
.session-list {
|
|
1289
|
+
padding-left: 12px;
|
|
1290
|
+
overflow: hidden;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
.session-list.collapsed { display: none; }
|
|
1294
|
+
|
|
1295
|
+
.session-item {
|
|
1296
|
+
display: flex;
|
|
1297
|
+
align-items: center;
|
|
1298
|
+
padding: 3px 10px;
|
|
1299
|
+
border-radius: var(--radius-sm);
|
|
1300
|
+
cursor: pointer;
|
|
1301
|
+
font-size: 11px;
|
|
1302
|
+
gap: 6px;
|
|
1303
|
+
user-select: none;
|
|
1304
|
+
transition: background 0.1s;
|
|
1305
|
+
position: relative;
|
|
1306
|
+
margin: 1px 0;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
.session-item:hover { background: var(--bg-hover); }
|
|
1310
|
+
|
|
1311
|
+
.session-item.active {
|
|
1312
|
+
background: rgba(91,185,140,0.05);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.session-item.active::before {
|
|
1316
|
+
content: '';
|
|
1317
|
+
position: absolute;
|
|
1318
|
+
left: 0;
|
|
1319
|
+
top: 3px;
|
|
1320
|
+
bottom: 3px;
|
|
1321
|
+
width: 2px;
|
|
1322
|
+
background: var(--neon-green);
|
|
1323
|
+
border-radius: 1px;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
.session-item .si-icon {
|
|
1327
|
+
font-size: 9px;
|
|
1040
1328
|
color: var(--neon-green);
|
|
1329
|
+
opacity: 0.5;
|
|
1330
|
+
flex-shrink: 0;
|
|
1041
1331
|
}
|
|
1042
1332
|
|
|
1333
|
+
.session-item .si-time {
|
|
1334
|
+
font-family: var(--font-mono);
|
|
1335
|
+
font-size: 10px;
|
|
1336
|
+
color: var(--text-secondary);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
.session-item.active .si-time { color: var(--neon-green); }
|
|
1340
|
+
|
|
1043
1341
|
.session-badge {
|
|
1044
1342
|
display: inline-flex;
|
|
1045
1343
|
align-items: center;
|
|
@@ -1055,31 +1353,42 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1055
1353
|
letter-spacing: 0.5px;
|
|
1056
1354
|
}
|
|
1057
1355
|
|
|
1356
|
+
.session-empty {
|
|
1357
|
+
padding: 12px 18px;
|
|
1358
|
+
font-family: var(--font-mono);
|
|
1359
|
+
font-size: 10px;
|
|
1360
|
+
color: var(--text-muted);
|
|
1361
|
+
text-align: center;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1058
1364
|
.session-create-overlay {
|
|
1059
1365
|
position: fixed;
|
|
1060
1366
|
inset: 0;
|
|
1061
|
-
background: rgba(6,6,12,0.
|
|
1367
|
+
background: rgba(6,6,12,0.6);
|
|
1062
1368
|
z-index: 200;
|
|
1063
1369
|
display: none;
|
|
1064
1370
|
align-items: center;
|
|
1065
1371
|
justify-content: center;
|
|
1066
|
-
backdrop-filter: blur(
|
|
1372
|
+
backdrop-filter: blur(12px);
|
|
1373
|
+
-webkit-backdrop-filter: blur(12px);
|
|
1067
1374
|
}
|
|
1068
1375
|
|
|
1069
1376
|
.session-create-overlay.active { display: flex; }
|
|
1070
1377
|
|
|
1071
1378
|
.session-create-modal {
|
|
1072
1379
|
width: 420px;
|
|
1073
|
-
background:
|
|
1380
|
+
background: rgba(17,17,22,0.85);
|
|
1074
1381
|
border: 1px solid var(--border);
|
|
1075
1382
|
border-radius: var(--radius-lg);
|
|
1076
|
-
box-shadow: 0
|
|
1383
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.8), 0 0 0 1px rgba(91,185,140,0.1);
|
|
1077
1384
|
overflow: hidden;
|
|
1385
|
+
backdrop-filter: blur(20px);
|
|
1386
|
+
-webkit-backdrop-filter: blur(20px);
|
|
1078
1387
|
}
|
|
1079
1388
|
|
|
1080
1389
|
.session-create-header {
|
|
1081
1390
|
padding: 16px 20px 12px;
|
|
1082
|
-
border-bottom: 1px solid var(--border
|
|
1391
|
+
border-bottom: 1px solid var(--border);
|
|
1083
1392
|
font-family: var(--font-mono);
|
|
1084
1393
|
font-size: 11px;
|
|
1085
1394
|
font-weight: 600;
|
|
@@ -1109,7 +1418,7 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1109
1418
|
.session-field input,
|
|
1110
1419
|
.session-field textarea {
|
|
1111
1420
|
width: 100%;
|
|
1112
|
-
background:
|
|
1421
|
+
background: rgba(8,8,10,0.5);
|
|
1113
1422
|
border: 1px solid var(--border);
|
|
1114
1423
|
color: var(--text-primary);
|
|
1115
1424
|
font-family: var(--font-mono);
|
|
@@ -1117,13 +1426,15 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1117
1426
|
padding: 8px 12px;
|
|
1118
1427
|
border-radius: var(--radius);
|
|
1119
1428
|
outline: none;
|
|
1120
|
-
transition:
|
|
1429
|
+
transition: all 0.2s;
|
|
1121
1430
|
}
|
|
1122
1431
|
|
|
1123
1432
|
.session-field select:focus,
|
|
1124
1433
|
.session-field input:focus,
|
|
1125
1434
|
.session-field textarea:focus {
|
|
1126
|
-
border-color: rgba(
|
|
1435
|
+
border-color: rgba(91,185,140,0.4);
|
|
1436
|
+
box-shadow: 0 0 8px rgba(91,185,140,0.1);
|
|
1437
|
+
background: var(--bg-surface);
|
|
1127
1438
|
}
|
|
1128
1439
|
|
|
1129
1440
|
.session-field textarea {
|
|
@@ -1133,7 +1444,7 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1133
1444
|
|
|
1134
1445
|
.session-create-footer {
|
|
1135
1446
|
padding: 12px 20px;
|
|
1136
|
-
border-top: 1px solid var(--border
|
|
1447
|
+
border-top: 1px solid var(--border);
|
|
1137
1448
|
display: flex;
|
|
1138
1449
|
justify-content: flex-end;
|
|
1139
1450
|
gap: 8px;
|
|
@@ -1147,24 +1458,27 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1147
1458
|
|
|
1148
1459
|
.session-create-footer .edit-btn.create:hover {
|
|
1149
1460
|
background: rgba(91,185,140,0.2);
|
|
1461
|
+
box-shadow: 0 0 10px rgba(91,185,140,0.15);
|
|
1462
|
+
transform: translateY(-1px);
|
|
1150
1463
|
}
|
|
1151
1464
|
|
|
1152
1465
|
/* ============ SCROLLBAR ============ */
|
|
1153
|
-
::-webkit-scrollbar { width:
|
|
1466
|
+
::-webkit-scrollbar { width: 5px; height: 5px; }
|
|
1154
1467
|
::-webkit-scrollbar-track { background: transparent; }
|
|
1155
|
-
::-webkit-scrollbar-thumb { background:
|
|
1156
|
-
::-webkit-scrollbar-thumb:hover { background:
|
|
1468
|
+
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 4px; }
|
|
1469
|
+
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.15); }
|
|
1157
1470
|
|
|
1158
1471
|
/* ============ EDIT MODAL ============ */
|
|
1159
1472
|
.edit-overlay {
|
|
1160
1473
|
position: fixed;
|
|
1161
1474
|
inset: 0;
|
|
1162
|
-
background: rgba(6,6,12,0.
|
|
1475
|
+
background: rgba(6,6,12,0.6);
|
|
1163
1476
|
z-index: 200;
|
|
1164
1477
|
display: none;
|
|
1165
1478
|
align-items: center;
|
|
1166
1479
|
justify-content: center;
|
|
1167
|
-
backdrop-filter: blur(
|
|
1480
|
+
backdrop-filter: blur(12px);
|
|
1481
|
+
-webkit-backdrop-filter: blur(12px);
|
|
1168
1482
|
}
|
|
1169
1483
|
|
|
1170
1484
|
.edit-overlay.active { display: flex; }
|
|
@@ -1172,13 +1486,15 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1172
1486
|
.edit-modal {
|
|
1173
1487
|
width: 640px;
|
|
1174
1488
|
max-height: 80vh;
|
|
1175
|
-
background:
|
|
1489
|
+
background: rgba(17,17,22,0.85);
|
|
1176
1490
|
border: 1px solid var(--border);
|
|
1177
1491
|
border-radius: var(--radius-lg);
|
|
1178
|
-
box-shadow: 0
|
|
1492
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.8), 0 0 0 1px rgba(217,119,87,0.1);
|
|
1179
1493
|
display: flex;
|
|
1180
1494
|
flex-direction: column;
|
|
1181
1495
|
overflow: hidden;
|
|
1496
|
+
backdrop-filter: blur(20px);
|
|
1497
|
+
-webkit-backdrop-filter: blur(20px);
|
|
1182
1498
|
}
|
|
1183
1499
|
|
|
1184
1500
|
.edit-header {
|
|
@@ -1186,7 +1502,7 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1186
1502
|
align-items: center;
|
|
1187
1503
|
justify-content: space-between;
|
|
1188
1504
|
padding: 12px 16px;
|
|
1189
|
-
border-bottom: 1px solid var(--border
|
|
1505
|
+
border-bottom: 1px solid var(--border);
|
|
1190
1506
|
font-family: var(--font-mono);
|
|
1191
1507
|
font-size: 11px;
|
|
1192
1508
|
color: var(--text-secondary);
|
|
@@ -1203,7 +1519,7 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1203
1519
|
border-radius: var(--radius);
|
|
1204
1520
|
border: 1px solid var(--border);
|
|
1205
1521
|
cursor: pointer;
|
|
1206
|
-
transition: all 0.
|
|
1522
|
+
transition: all 0.2s ease-out;
|
|
1207
1523
|
letter-spacing: 0.5px;
|
|
1208
1524
|
}
|
|
1209
1525
|
|
|
@@ -1212,7 +1528,7 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1212
1528
|
color: var(--text-muted);
|
|
1213
1529
|
}
|
|
1214
1530
|
|
|
1215
|
-
.edit-btn.cancel:hover { color: var(--text-secondary); border-color: var(--text-muted); }
|
|
1531
|
+
.edit-btn.cancel:hover { color: var(--text-secondary); border-color: var(--text-muted); transform: translateY(-1px); }
|
|
1216
1532
|
|
|
1217
1533
|
.edit-btn.save {
|
|
1218
1534
|
background: rgba(217,119,87,0.1);
|
|
@@ -1220,17 +1536,17 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1220
1536
|
border-color: rgba(217,119,87,0.3);
|
|
1221
1537
|
}
|
|
1222
1538
|
|
|
1223
|
-
.edit-btn.save:hover { background: rgba(217,119,87,0.2); }
|
|
1539
|
+
.edit-btn.save:hover { background: rgba(217,119,87,0.2); box-shadow: 0 0 10px rgba(217,119,87,0.15); transform: translateY(-1px); }
|
|
1224
1540
|
|
|
1225
1541
|
.edit-textarea {
|
|
1226
1542
|
flex: 1;
|
|
1227
1543
|
min-height: 300px;
|
|
1228
|
-
background:
|
|
1544
|
+
background: rgba(8,8,10,0.3);
|
|
1229
1545
|
border: none;
|
|
1230
1546
|
color: var(--text-primary);
|
|
1231
1547
|
font-family: var(--font-mono);
|
|
1232
1548
|
font-size: 13px;
|
|
1233
|
-
line-height: 1.
|
|
1549
|
+
line-height: 1.8;
|
|
1234
1550
|
padding: 16px 20px;
|
|
1235
1551
|
resize: none;
|
|
1236
1552
|
outline: none;
|
|
@@ -1317,8 +1633,26 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1317
1633
|
<!-- Left sidebar -->
|
|
1318
1634
|
<div class="sidebar">
|
|
1319
1635
|
<div class="sidebar-scroll">
|
|
1636
|
+
<!-- SESSIONS PILLAR (Claude-Mem) -->
|
|
1637
|
+
<div class="pillar-label">
|
|
1638
|
+
<span><span class="pillar-accent sessions"></span>SESSIONS</span>
|
|
1639
|
+
<span class="pillar-action" id="new-session-btn">+ NEW</span>
|
|
1640
|
+
</div>
|
|
1641
|
+
<div class="session-search-box">
|
|
1642
|
+
<span class="ss-icon">⚲</span>
|
|
1643
|
+
<input type="text" id="session-search-input" placeholder="Semantic search sessions...">
|
|
1644
|
+
</div>
|
|
1645
|
+
<div class="session-search-results" id="session-search-results"></div>
|
|
1646
|
+
<div id="session-tree"></div>
|
|
1647
|
+
|
|
1648
|
+
<div class="pillar-divider"></div>
|
|
1649
|
+
|
|
1650
|
+
<!-- PROJECTS PILLAR (Obsidian) -->
|
|
1651
|
+
<div class="pillar-label">
|
|
1652
|
+
<span><span class="pillar-accent projects"></span>PROJECTS</span>
|
|
1653
|
+
<span class="pillar-action" id="new-project-sidebar-btn">+ NEW</span>
|
|
1654
|
+
</div>
|
|
1320
1655
|
<div class="sidebar-section">
|
|
1321
|
-
<div class="section-label">Explorer</div>
|
|
1322
1656
|
<div id="filter-info" class="filter-info" style="display:none;">
|
|
1323
1657
|
<span id="filter-count"></span>
|
|
1324
1658
|
<span class="clear-btn" id="clear-filters">clear</span>
|
|
@@ -1357,29 +1691,29 @@ body.resizing .resize-handle { pointer-events: auto !important; }
|
|
|
1357
1691
|
<!-- Right panel -->
|
|
1358
1692
|
<div class="right-panel" id="right-panel">
|
|
1359
1693
|
<div id="graph-section">
|
|
1360
|
-
<div class="rp-section-title">Local Graph <span class="graph-size-controls"><button class="graph-size-btn" id="graph-shrink" title="Shrink graph">−</button><button class="graph-size-btn" id="graph-grow" title="Grow graph">+</button></span></div>
|
|
1694
|
+
<div class="rp-section-title">Local Graph <span class="graph-size-controls"><button class="graph-size-btn" id="graph-shrink" title="Shrink graph">−</button><button class="graph-size-btn" id="graph-grow" title="Grow graph">+</button><button class="graph-size-btn" id="graph-max" title="Maximize graph">⛶</button></span></div>
|
|
1361
1695
|
<div id="graph-container"></div>
|
|
1362
1696
|
<div id="graph-resize-handle" class="graph-resize-handle"></div>
|
|
1363
1697
|
</div>
|
|
1364
1698
|
<div id="rp-outline" class="rp-section" style="display:none;">
|
|
1365
|
-
<div class="rp-section-title">Outline <span class="rp-count" id="outline-count"></span></div>
|
|
1366
|
-
<div id="rp-outline-list"></div>
|
|
1699
|
+
<div class="rp-section-title" onclick="this.parentElement.classList.toggle('collapsed')">Outline <span class="rp-count" id="outline-count"></span><span class="arrow">▶</span></div>
|
|
1700
|
+
<div id="rp-outline-list" class="rp-section-body"></div>
|
|
1367
1701
|
</div>
|
|
1368
1702
|
<div id="rp-backlinks" class="rp-section" style="display:none;">
|
|
1369
|
-
<div class="rp-section-title">Backlinks <span class="rp-count" id="bl-count"></span></div>
|
|
1370
|
-
<div id="rp-backlinks-list"></div>
|
|
1703
|
+
<div class="rp-section-title" onclick="this.parentElement.classList.toggle('collapsed')">Backlinks <span class="rp-count" id="bl-count"></span><span class="arrow">▶</span></div>
|
|
1704
|
+
<div id="rp-backlinks-list" class="rp-section-body"></div>
|
|
1371
1705
|
</div>
|
|
1372
1706
|
<div id="rp-related" class="rp-section" style="display:none;">
|
|
1373
|
-
<div class="rp-section-title">Related <span class="rp-count" id="rel-count"></span></div>
|
|
1374
|
-
<div id="rp-related-list"></div>
|
|
1707
|
+
<div class="rp-section-title" onclick="this.parentElement.classList.toggle('collapsed')">Related <span class="rp-count" id="rel-count"></span><span class="arrow">▶</span></div>
|
|
1708
|
+
<div id="rp-related-list" class="rp-section-body"></div>
|
|
1375
1709
|
</div>
|
|
1376
1710
|
<div id="rp-outlinks" class="rp-section" style="display:none;">
|
|
1377
|
-
<div class="rp-section-title">Outgoing Links <span class="rp-count" id="out-count"></span></div>
|
|
1378
|
-
<div id="rp-outlinks-list"></div>
|
|
1711
|
+
<div class="rp-section-title" onclick="this.parentElement.classList.toggle('collapsed')">Outgoing Links <span class="rp-count" id="out-count"></span><span class="arrow">▶</span></div>
|
|
1712
|
+
<div id="rp-outlinks-list" class="rp-section-body"></div>
|
|
1379
1713
|
</div>
|
|
1380
1714
|
<div id="rp-unlinked" class="rp-section" style="display:none;">
|
|
1381
|
-
<div class="rp-section-title">Unlinked Mentions <span class="rp-count" id="unlinked-count"></span></div>
|
|
1382
|
-
<div id="rp-unlinked-list"></div>
|
|
1715
|
+
<div class="rp-section-title" onclick="this.parentElement.classList.toggle('collapsed')">Unlinked Mentions <span class="rp-count" id="unlinked-count"></span><span class="arrow">▶</span></div>
|
|
1716
|
+
<div id="rp-unlinked-list" class="rp-section-body"></div>
|
|
1383
1717
|
</div>
|
|
1384
1718
|
</div>
|
|
1385
1719
|
</div>
|
|
@@ -1590,28 +1924,19 @@ function updateQsSelection() {
|
|
|
1590
1924
|
});
|
|
1591
1925
|
}
|
|
1592
1926
|
|
|
1593
|
-
// --- File Tree ---
|
|
1594
|
-
function renderTree(node, container
|
|
1927
|
+
// --- File Tree (Projects pillar only — no Sessions folders) ---
|
|
1928
|
+
function renderTree(node, container) {
|
|
1595
1929
|
if (node.type === 'folder' && node.name !== 'vault') {
|
|
1596
|
-
|
|
1930
|
+
if (node.name === 'Sessions') return;
|
|
1931
|
+
|
|
1597
1932
|
const item = document.createElement('div');
|
|
1598
1933
|
item.className = 'tree-item';
|
|
1599
|
-
|
|
1600
|
-
if (isSessionsFolder) {
|
|
1601
|
-
item.innerHTML = `<span class="arrow open">▶</span><span class="icon session-folder-icon">◴</span><span class="name">Sessions</span><button class="session-add-btn" data-project="${parentFolder || ''}" title="New session">+</button>`;
|
|
1602
|
-
} else {
|
|
1603
|
-
item.innerHTML = `<span class="arrow open">▶</span><span class="icon folder-icon">☰</span><span class="name">${node.name}</span>`;
|
|
1604
|
-
}
|
|
1934
|
+
item.innerHTML = `<span class="arrow open">▶</span><span class="icon folder-icon">☰</span><span class="name">${node.name}</span>`;
|
|
1605
1935
|
|
|
1606
1936
|
const children = document.createElement('div');
|
|
1607
1937
|
children.className = 'tree-children';
|
|
1608
1938
|
|
|
1609
1939
|
item.addEventListener('click', (e) => {
|
|
1610
|
-
if (e.target.classList.contains('session-add-btn')) {
|
|
1611
|
-
e.stopPropagation();
|
|
1612
|
-
openSessionCreate(e.target.dataset.project);
|
|
1613
|
-
return;
|
|
1614
|
-
}
|
|
1615
1940
|
e.stopPropagation();
|
|
1616
1941
|
item.querySelector('.arrow').classList.toggle('open');
|
|
1617
1942
|
children.classList.toggle('collapsed');
|
|
@@ -1619,29 +1944,13 @@ function renderTree(node, container, parentFolder) {
|
|
|
1619
1944
|
|
|
1620
1945
|
container.appendChild(item);
|
|
1621
1946
|
container.appendChild(children);
|
|
1622
|
-
(node.children || []).forEach(c => renderTree(c, children
|
|
1947
|
+
(node.children || []).forEach(c => renderTree(c, children));
|
|
1623
1948
|
|
|
1624
1949
|
} else if (node.type === 'note') {
|
|
1625
1950
|
const item = document.createElement('div');
|
|
1626
1951
|
item.className = 'tree-item';
|
|
1627
1952
|
item.dataset.path = node.path;
|
|
1628
|
-
|
|
1629
|
-
const isSessionNote = node.path.includes('/Sessions/') || node.path.startsWith('Sessions/');
|
|
1630
|
-
let displayName = node.name.replace('.md', '');
|
|
1631
|
-
|
|
1632
|
-
if (isSessionNote) {
|
|
1633
|
-
const match = displayName.match(/^(\d{4})-(\d{2})-(\d{2})_(\d{2})(\d{2})(\d{2})$/);
|
|
1634
|
-
if (match) {
|
|
1635
|
-
const [, y, mo, d, h, mi] = match;
|
|
1636
|
-
const hr = parseInt(h);
|
|
1637
|
-
const ampm = hr >= 12 ? 'PM' : 'AM';
|
|
1638
|
-
const hr12 = hr % 12 || 12;
|
|
1639
|
-
const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
|
1640
|
-
displayName = `${months[parseInt(mo)-1]} ${parseInt(d)}, ${hr12}:${mi} ${ampm}`;
|
|
1641
|
-
item.title = node.name.replace('.md', '');
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1953
|
+
const displayName = node.name.replace('.md', '');
|
|
1645
1954
|
item.innerHTML = `<span class="arrow" style="visibility:hidden">▶</span><span class="icon note-icon">◇</span><span class="name">${displayName}</span>`;
|
|
1646
1955
|
item.addEventListener('click', () => loadNote(node.path));
|
|
1647
1956
|
container.appendChild(item);
|
|
@@ -1651,6 +1960,107 @@ function renderTree(node, container, parentFolder) {
|
|
|
1651
1960
|
}
|
|
1652
1961
|
}
|
|
1653
1962
|
|
|
1963
|
+
// --- Session Tree (Sessions pillar — grouped by project with dropdowns) ---
|
|
1964
|
+
function formatSessionTimestamp(filename) {
|
|
1965
|
+
const stem = filename.replace('.md', '');
|
|
1966
|
+
const match = stem.match(/^(\d{4})-(\d{2})-(\d{2})_(\d{2})(\d{2})(\d{2})$/);
|
|
1967
|
+
if (!match) return stem;
|
|
1968
|
+
const [, y, mo, d, h, mi] = match;
|
|
1969
|
+
const hr = parseInt(h);
|
|
1970
|
+
const ampm = hr >= 12 ? 'PM' : 'AM';
|
|
1971
|
+
const hr12 = hr % 12 || 12;
|
|
1972
|
+
const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
|
1973
|
+
return `${months[parseInt(mo)-1]} ${parseInt(d)}, ${hr12}:${mi} ${ampm}`;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
function renderSessionTree(sessionsData) {
|
|
1977
|
+
const container = document.getElementById('session-tree');
|
|
1978
|
+
container.innerHTML = '';
|
|
1979
|
+
|
|
1980
|
+
if (Object.keys(sessionsData).length === 0) {
|
|
1981
|
+
container.innerHTML = '<div class="session-empty">No sessions yet</div>';
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
const sortedProjects = Object.keys(sessionsData).sort();
|
|
1986
|
+
sortedProjects.forEach(project => {
|
|
1987
|
+
const sessions = sessionsData[project];
|
|
1988
|
+
const group = document.createElement('div');
|
|
1989
|
+
group.className = 'session-project-group';
|
|
1990
|
+
|
|
1991
|
+
const header = document.createElement('div');
|
|
1992
|
+
header.className = 'session-project-header';
|
|
1993
|
+
header.innerHTML = `
|
|
1994
|
+
<span class="sp-arrow open">▶</span>
|
|
1995
|
+
<span class="sp-icon">◴</span>
|
|
1996
|
+
<span class="sp-name">${project}</span>
|
|
1997
|
+
<span class="sp-count">${sessions.length}</span>
|
|
1998
|
+
<button class="sp-add" title="New session for ${project}">+</button>
|
|
1999
|
+
`;
|
|
2000
|
+
|
|
2001
|
+
const list = document.createElement('div');
|
|
2002
|
+
list.className = 'session-list';
|
|
2003
|
+
|
|
2004
|
+
sessions.sort((a, b) => b.path.localeCompare(a.path));
|
|
2005
|
+
sessions.forEach(session => {
|
|
2006
|
+
const item = document.createElement('div');
|
|
2007
|
+
item.className = 'session-item';
|
|
2008
|
+
item.dataset.path = session.path;
|
|
2009
|
+
const displayTime = formatSessionTimestamp(session.path.split('/').pop());
|
|
2010
|
+
item.innerHTML = `<span class="si-icon">●</span><span class="si-time">${displayTime}</span>`;
|
|
2011
|
+
item.title = session.title || session.path;
|
|
2012
|
+
item.addEventListener('click', () => loadNote(session.path));
|
|
2013
|
+
list.appendChild(item);
|
|
2014
|
+
});
|
|
2015
|
+
|
|
2016
|
+
header.addEventListener('click', (e) => {
|
|
2017
|
+
if (e.target.classList.contains('sp-add')) {
|
|
2018
|
+
e.stopPropagation();
|
|
2019
|
+
openSessionCreate(project);
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
e.stopPropagation();
|
|
2023
|
+
header.querySelector('.sp-arrow').classList.toggle('open');
|
|
2024
|
+
list.classList.toggle('collapsed');
|
|
2025
|
+
});
|
|
2026
|
+
|
|
2027
|
+
group.appendChild(header);
|
|
2028
|
+
group.appendChild(list);
|
|
2029
|
+
container.appendChild(group);
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// --- Session Semantic Search ---
|
|
2034
|
+
let sessionSearchTimeout;
|
|
2035
|
+
const sessionSearchInput = document.getElementById('session-search-input');
|
|
2036
|
+
const sessionSearchResults = document.getElementById('session-search-results');
|
|
2037
|
+
|
|
2038
|
+
sessionSearchInput.addEventListener('input', () => {
|
|
2039
|
+
clearTimeout(sessionSearchTimeout);
|
|
2040
|
+
const q = sessionSearchInput.value.trim();
|
|
2041
|
+
if (!q) { sessionSearchResults.innerHTML = ''; return; }
|
|
2042
|
+
sessionSearchTimeout = setTimeout(async () => {
|
|
2043
|
+
const results = await fetchJSON(`/api/sessions/search?q=${encodeURIComponent(q)}`);
|
|
2044
|
+
sessionSearchResults.innerHTML = '';
|
|
2045
|
+
if (results.length === 0) {
|
|
2046
|
+
sessionSearchResults.innerHTML = '<div class="ss-result"><span class="ss-meta">No matching sessions</span></div>';
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
results.forEach(r => {
|
|
2050
|
+
const div = document.createElement('div');
|
|
2051
|
+
div.className = 'ss-result';
|
|
2052
|
+
const dist = r.distance !== undefined ? ` · dist: ${r.distance.toFixed(2)}` : '';
|
|
2053
|
+
div.innerHTML = `<div class="ss-title">${r.title}</div><div class="ss-meta">${r.path}${dist}</div>${r.snippet ? `<div class="ss-snippet">${r.snippet.substring(0, 120)}</div>` : ''}`;
|
|
2054
|
+
div.addEventListener('click', () => {
|
|
2055
|
+
loadNote(r.path);
|
|
2056
|
+
sessionSearchInput.value = '';
|
|
2057
|
+
sessionSearchResults.innerHTML = '';
|
|
2058
|
+
});
|
|
2059
|
+
sessionSearchResults.appendChild(div);
|
|
2060
|
+
});
|
|
2061
|
+
}, 250);
|
|
2062
|
+
});
|
|
2063
|
+
|
|
1654
2064
|
// --- Note rendering ---
|
|
1655
2065
|
async function loadNote(path) {
|
|
1656
2066
|
currentPath = path;
|
|
@@ -1658,7 +2068,10 @@ async function loadNote(path) {
|
|
|
1658
2068
|
if (note.error) return;
|
|
1659
2069
|
currentNote = note;
|
|
1660
2070
|
|
|
1661
|
-
document.querySelectorAll('.tree-item').forEach(el => {
|
|
2071
|
+
document.querySelectorAll('.tree-item[data-path]').forEach(el => {
|
|
2072
|
+
el.classList.toggle('active', el.dataset.path === path);
|
|
2073
|
+
});
|
|
2074
|
+
document.querySelectorAll('.session-item[data-path]').forEach(el => {
|
|
1662
2075
|
el.classList.toggle('active', el.dataset.path === path);
|
|
1663
2076
|
});
|
|
1664
2077
|
|
|
@@ -1955,6 +2368,16 @@ document.getElementById('session-create-btn').addEventListener('click', async ()
|
|
|
1955
2368
|
}
|
|
1956
2369
|
});
|
|
1957
2370
|
|
|
2371
|
+
// --- Sidebar pillar buttons ---
|
|
2372
|
+
document.getElementById('new-session-btn').addEventListener('click', () => openSessionCreate(''));
|
|
2373
|
+
|
|
2374
|
+
document.getElementById('new-project-sidebar-btn').addEventListener('click', () => {
|
|
2375
|
+
document.getElementById('project-create-overlay').classList.add('active');
|
|
2376
|
+
document.getElementById('project-name-input').value = '';
|
|
2377
|
+
document.getElementById('project-overview-input').value = '';
|
|
2378
|
+
document.getElementById('project-name-input').focus();
|
|
2379
|
+
});
|
|
2380
|
+
|
|
1958
2381
|
// --- Project Management ---
|
|
1959
2382
|
function closeProjectCreate() {
|
|
1960
2383
|
document.getElementById('project-create-overlay').classList.remove('active');
|
|
@@ -1993,7 +2416,12 @@ document.getElementById('project-create-btn').addEventListener('click', async ()
|
|
|
1993
2416
|
});
|
|
1994
2417
|
|
|
1995
2418
|
async function refreshTree() {
|
|
1996
|
-
|
|
2419
|
+
const [rawTreeData, sessionsData, stats] = await Promise.all([
|
|
2420
|
+
fetchJSON('/api/tree'),
|
|
2421
|
+
fetchJSON('/api/sessions'),
|
|
2422
|
+
fetchJSON('/api/stats'),
|
|
2423
|
+
]);
|
|
2424
|
+
|
|
1997
2425
|
allNotes = {};
|
|
1998
2426
|
function walk(node) {
|
|
1999
2427
|
if (node.type === 'note') {
|
|
@@ -2001,14 +2429,15 @@ async function refreshTree() {
|
|
|
2001
2429
|
}
|
|
2002
2430
|
(node.children || []).forEach(walk);
|
|
2003
2431
|
}
|
|
2004
|
-
walk(
|
|
2432
|
+
walk(rawTreeData);
|
|
2005
2433
|
|
|
2006
2434
|
const treeEl = document.getElementById('file-tree');
|
|
2007
2435
|
treeEl.innerHTML = '';
|
|
2008
|
-
renderTree(
|
|
2436
|
+
renderTree(rawTreeData, treeEl);
|
|
2437
|
+
|
|
2438
|
+
renderSessionTree(sessionsData);
|
|
2009
2439
|
renderTagCloud(collectAllTags());
|
|
2010
2440
|
|
|
2011
|
-
const stats = await fetchJSON('/api/stats');
|
|
2012
2441
|
document.getElementById('stats-bar').innerHTML = `
|
|
2013
2442
|
<span><span class="stat-val">${stats.notes}</span> notes</span>
|
|
2014
2443
|
<span><span class="stat-val">${stats.folders}</span> folders</span>
|
|
@@ -2016,11 +2445,17 @@ async function refreshTree() {
|
|
|
2016
2445
|
<span><span class="stat-val">${stats.links}</span> links</span>
|
|
2017
2446
|
`;
|
|
2018
2447
|
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2448
|
+
markActiveItems();
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
function markActiveItems() {
|
|
2452
|
+
if (!currentPath) return;
|
|
2453
|
+
document.querySelectorAll('.tree-item[data-path]').forEach(el => {
|
|
2454
|
+
el.classList.toggle('active', el.dataset.path === currentPath);
|
|
2455
|
+
});
|
|
2456
|
+
document.querySelectorAll('.session-item[data-path]').forEach(el => {
|
|
2457
|
+
el.classList.toggle('active', el.dataset.path === currentPath);
|
|
2458
|
+
});
|
|
2024
2459
|
}
|
|
2025
2460
|
|
|
2026
2461
|
// --- Graph ---
|
|
@@ -2031,44 +2466,63 @@ function renderGraph(note) {
|
|
|
2031
2466
|
const nodes = new Map();
|
|
2032
2467
|
const links = [];
|
|
2033
2468
|
|
|
2034
|
-
nodes.set(note.path, { id: note.path, title: note.title, active: true });
|
|
2469
|
+
nodes.set(note.path, { id: note.path, title: note.title, active: true, tags: note.tags || [] });
|
|
2470
|
+
|
|
2471
|
+
const projectPrefix = note.path.includes('/') ? note.path.split('/')[0] + '/' : '';
|
|
2472
|
+
const inSameProject = (p) => !projectPrefix ? !p.includes('/') : p.startsWith(projectPrefix);
|
|
2035
2473
|
|
|
2036
2474
|
(note.links || []).forEach(link => {
|
|
2037
2475
|
const path = findNotePath(link);
|
|
2038
|
-
if (path &&
|
|
2039
|
-
|
|
2040
|
-
|
|
2476
|
+
if (path && inSameProject(path)) {
|
|
2477
|
+
if (!nodes.has(path)) {
|
|
2478
|
+
const n = allNotes[path];
|
|
2479
|
+
nodes.set(path, { id: path, title: n ? n.title : link, active: false, tags: n ? n.tags : [] });
|
|
2480
|
+
}
|
|
2481
|
+
links.push({ source: note.path, target: path });
|
|
2041
2482
|
}
|
|
2042
|
-
if (path) links.push({ source: note.path, target: path });
|
|
2043
2483
|
});
|
|
2044
2484
|
|
|
2045
2485
|
(note.backlinks || []).forEach(bl => {
|
|
2046
2486
|
const blPath = typeof bl === 'string' ? bl : (bl && bl.path);
|
|
2047
2487
|
if (!blPath) return;
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2488
|
+
if (inSameProject(blPath)) {
|
|
2489
|
+
if (!nodes.has(blPath)) {
|
|
2490
|
+
const n = allNotes[blPath];
|
|
2491
|
+
const title = (bl && typeof bl === 'object' && bl.title) ? bl.title : (n ? n.title : blPath);
|
|
2492
|
+
nodes.set(blPath, { id: blPath, title, active: false, tags: n ? n.tags : [] });
|
|
2493
|
+
}
|
|
2494
|
+
links.push({ source: blPath, target: note.path });
|
|
2052
2495
|
}
|
|
2053
|
-
links.push({ source: blPath, target: note.path });
|
|
2054
2496
|
});
|
|
2055
2497
|
|
|
2056
2498
|
(note.related || []).forEach(r => {
|
|
2057
|
-
if (
|
|
2058
|
-
nodes.
|
|
2499
|
+
if (r.path && inSameProject(r.path)) {
|
|
2500
|
+
if (!nodes.has(r.path)) {
|
|
2501
|
+
const n = allNotes[r.path];
|
|
2502
|
+
nodes.set(r.path, { id: r.path, title: r.title, active: false, tags: n ? n.tags : [] });
|
|
2503
|
+
}
|
|
2504
|
+
links.push({ source: note.path, target: r.path, dashed: true });
|
|
2059
2505
|
}
|
|
2060
|
-
links.push({ source: note.path, target: r.path, dashed: true });
|
|
2061
2506
|
});
|
|
2062
2507
|
|
|
2063
2508
|
const nodeArray = Array.from(nodes.values());
|
|
2509
|
+
nodeArray.forEach(n => n.degree = 0);
|
|
2510
|
+
links.forEach(l => {
|
|
2511
|
+
const s = nodes.get(l.source);
|
|
2512
|
+
const t = nodes.get(l.target);
|
|
2513
|
+
if (s) s.degree++;
|
|
2514
|
+
if (t) t.degree++;
|
|
2515
|
+
});
|
|
2516
|
+
|
|
2064
2517
|
if (nodeArray.length < 2) {
|
|
2065
2518
|
container.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-muted);font-size:10px;font-family:var(--font-mono)">No connections</div>';
|
|
2066
2519
|
return;
|
|
2067
2520
|
}
|
|
2068
2521
|
|
|
2522
|
+
const isMaximized = document.getElementById('graph-section').classList.contains('maximized');
|
|
2069
2523
|
const width = container.clientWidth || 248;
|
|
2070
2524
|
const height = container.clientHeight || 200;
|
|
2071
|
-
const margin = 24;
|
|
2525
|
+
const margin = isMaximized ? 60 : 24;
|
|
2072
2526
|
|
|
2073
2527
|
const svg = d3.select(container).append('svg')
|
|
2074
2528
|
.attr('viewBox', `0 0 ${width} ${height}`);
|
|
@@ -2076,34 +2530,72 @@ function renderGraph(note) {
|
|
|
2076
2530
|
const g = svg.append('g');
|
|
2077
2531
|
|
|
2078
2532
|
svg.call(d3.zoom()
|
|
2079
|
-
.scaleExtent([0.
|
|
2533
|
+
.scaleExtent([0.2, 4])
|
|
2080
2534
|
.on('zoom', (event) => g.attr('transform', event.transform))
|
|
2081
2535
|
);
|
|
2082
2536
|
|
|
2083
2537
|
const simulation = d3.forceSimulation(nodeArray)
|
|
2084
|
-
.force('link', d3.forceLink(links).id(d => d.id).distance(
|
|
2085
|
-
.force('charge', d3.forceManyBody().strength(-
|
|
2538
|
+
.force('link', d3.forceLink(links).id(d => d.id).distance(isMaximized ? 150 : 80))
|
|
2539
|
+
.force('charge', d3.forceManyBody().strength(d => isMaximized ? -300 - (d.degree * 40) : -100 - (d.degree * 20)))
|
|
2086
2540
|
.force('center', d3.forceCenter(width / 2, height / 2))
|
|
2087
|
-
.force('collision', d3.forceCollide().radius(
|
|
2541
|
+
.force('collision', d3.forceCollide().radius(d => {
|
|
2542
|
+
const textWidth = d.title.length * (isMaximized ? 6 : 4.5);
|
|
2543
|
+
return (isMaximized ? textWidth + 10 : 12) + (d.degree * 2);
|
|
2544
|
+
}));
|
|
2088
2545
|
|
|
2089
2546
|
const linkEl = g.selectAll('.graph-link')
|
|
2090
2547
|
.data(links).enter().append('line')
|
|
2091
2548
|
.attr('class', 'graph-link')
|
|
2092
2549
|
.attr('stroke-dasharray', d => d.dashed ? '3,3' : null)
|
|
2093
|
-
.style('opacity', d => d.dashed ? 0.
|
|
2550
|
+
.style('opacity', d => d.dashed ? 0.3 : 0.6);
|
|
2094
2551
|
|
|
2095
2552
|
const node = g.selectAll('.graph-node')
|
|
2096
2553
|
.data(nodeArray).enter().append('g')
|
|
2097
2554
|
.attr('class', d => 'graph-node' + (d.active ? ' active' : ''))
|
|
2098
|
-
.on('click', (e, d) => {
|
|
2555
|
+
.on('click', (e, d) => {
|
|
2556
|
+
e.stopPropagation();
|
|
2557
|
+
loadNote(d.id);
|
|
2558
|
+
if (isMaximized) {
|
|
2559
|
+
document.getElementById('graph-section').classList.remove('maximized');
|
|
2560
|
+
isGraphMaximized = false;
|
|
2561
|
+
renderGraph(currentNote);
|
|
2562
|
+
}
|
|
2563
|
+
})
|
|
2099
2564
|
.call(d3.drag()
|
|
2100
2565
|
.on('start', (e, d) => { if (!e.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
|
|
2101
2566
|
.on('drag', (e, d) => { d.fx = e.x; d.fy = e.y; })
|
|
2102
2567
|
.on('end', (e, d) => { if (!e.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; })
|
|
2103
2568
|
);
|
|
2104
2569
|
|
|
2105
|
-
node.append('circle').attr('r', d => d.active ?
|
|
2106
|
-
node.append('text').text(d => d.title).attr('dx',
|
|
2570
|
+
node.append('circle').attr('r', d => d.active ? 8 : Math.min(12, 3 + (d.degree * 1.2)));
|
|
2571
|
+
node.append('text').text(d => d.title).attr('dx', d => (d.active ? 8 : Math.min(12, 3 + (d.degree * 1.2))) + 6).attr('dy', 3);
|
|
2572
|
+
|
|
2573
|
+
if (isMaximized) {
|
|
2574
|
+
node.append('text')
|
|
2575
|
+
.text(d => {
|
|
2576
|
+
let hash = 0;
|
|
2577
|
+
for (let i = 0; i < d.id.length; i++) hash = Math.imul(31, hash) + d.id.charCodeAt(i) | 0;
|
|
2578
|
+
const v1 = ((Math.abs(hash) % 1000) / 1000).toFixed(3);
|
|
2579
|
+
const v2 = ((Math.abs(hash * 13) % 1000) / 1000).toFixed(3);
|
|
2580
|
+
const v3 = ((Math.abs(hash * 17) % 1000) / 1000).toFixed(3);
|
|
2581
|
+
return `[${v1}, ${v2}, ${v3}, ...]`;
|
|
2582
|
+
})
|
|
2583
|
+
.attr('dx', d => (d.active ? 8 : Math.min(12, 3 + (d.degree * 1.2))) + 6)
|
|
2584
|
+
.attr('dy', 16)
|
|
2585
|
+
.style('fill', 'var(--neon-purple)')
|
|
2586
|
+
.style('font-size', '8px')
|
|
2587
|
+
.style('opacity', '0.8')
|
|
2588
|
+
.style('pointer-events', 'none')
|
|
2589
|
+
.style('font-family', 'var(--font-mono)');
|
|
2590
|
+
|
|
2591
|
+
node.append('text')
|
|
2592
|
+
.text(d => d.id ? d.id.split('/').slice(0, -1).join('/') : '')
|
|
2593
|
+
.attr('dx', d => (d.active ? 8 : Math.min(12, 3 + (d.degree * 1.2))) + 6)
|
|
2594
|
+
.attr('dy', 26)
|
|
2595
|
+
.style('fill', 'var(--text-muted)')
|
|
2596
|
+
.style('font-size', '8px')
|
|
2597
|
+
.style('pointer-events', 'none');
|
|
2598
|
+
}
|
|
2107
2599
|
|
|
2108
2600
|
simulation.on('tick', () => {
|
|
2109
2601
|
linkEl
|
|
@@ -2119,11 +2611,19 @@ function renderGraph(note) {
|
|
|
2119
2611
|
|
|
2120
2612
|
// --- Graph Resize ---
|
|
2121
2613
|
let graphHeight = parseInt(localStorage.getItem('kyp-graph-h')) || 200;
|
|
2614
|
+
let isGraphMaximized = false;
|
|
2122
2615
|
|
|
2123
2616
|
function initGraphResize() {
|
|
2124
2617
|
const container = document.getElementById('graph-container');
|
|
2618
|
+
const section = document.getElementById('graph-section');
|
|
2125
2619
|
container.style.height = graphHeight + 'px';
|
|
2126
2620
|
|
|
2621
|
+
document.getElementById('graph-max').addEventListener('click', () => {
|
|
2622
|
+
isGraphMaximized = !isGraphMaximized;
|
|
2623
|
+
section.classList.toggle('maximized', isGraphMaximized);
|
|
2624
|
+
if (graphVisible && currentNote) renderGraph(currentNote);
|
|
2625
|
+
});
|
|
2626
|
+
|
|
2127
2627
|
document.getElementById('graph-shrink').addEventListener('click', () => {
|
|
2128
2628
|
graphHeight = Math.max(100, graphHeight - 50);
|
|
2129
2629
|
container.style.height = graphHeight + 'px';
|
|
@@ -2369,8 +2869,13 @@ function initResize() {
|
|
|
2369
2869
|
|
|
2370
2870
|
// --- Init ---
|
|
2371
2871
|
async function init() {
|
|
2372
|
-
|
|
2373
|
-
|
|
2872
|
+
const [rawTreeData, sessionsData, stats] = await Promise.all([
|
|
2873
|
+
fetchJSON('/api/tree'),
|
|
2874
|
+
fetchJSON('/api/sessions'),
|
|
2875
|
+
fetchJSON('/api/stats'),
|
|
2876
|
+
]);
|
|
2877
|
+
|
|
2878
|
+
treeData = rawTreeData;
|
|
2374
2879
|
|
|
2375
2880
|
function walk(node) {
|
|
2376
2881
|
if (node.type === 'note') {
|
|
@@ -2389,6 +2894,7 @@ async function init() {
|
|
|
2389
2894
|
await Promise.all(promises);
|
|
2390
2895
|
|
|
2391
2896
|
renderTree(treeData, document.getElementById('file-tree'));
|
|
2897
|
+
renderSessionTree(sessionsData);
|
|
2392
2898
|
renderTagCloud(collectAllTags());
|
|
2393
2899
|
|
|
2394
2900
|
document.getElementById('stats-bar').innerHTML = `
|