mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 07:45:51 +01:00
chore(react/type_widget): port empty search
This commit is contained in:
@@ -4,6 +4,8 @@ import FNote from "../entities/fnote";
|
|||||||
import protected_session_holder from "../services/protected_session_holder";
|
import protected_session_holder from "../services/protected_session_holder";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import NoteContext from "../components/note_context";
|
import NoteContext from "../components/note_context";
|
||||||
|
import Empty from "./type_widgets/Empty";
|
||||||
|
import { VNode } from "preact";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one,
|
* A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one,
|
||||||
@@ -16,8 +18,15 @@ type ExtendedNoteType = Exclude<NoteType, "launcher" | "text" | "code"> | "empty
|
|||||||
*/
|
*/
|
||||||
export default function NoteDetail() {
|
export default function NoteDetail() {
|
||||||
const { note, type } = useNoteInfo();
|
const { note, type } = useNoteInfo();
|
||||||
|
const [ correspondingWidget, setCorrespondingWidget ] = useState<VNode>();
|
||||||
|
|
||||||
return <p>Note detail goes here! {note?.title} of {type}</p>
|
useEffect(() => setCorrespondingWidget(getCorrespondingWidget(type)), [ type ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{correspondingWidget || <p>Note detail goes here! {note?.title} of {type}</p>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Manages both note changes and changes to the widget type, which are asynchronous. */
|
/** Manages both note changes and changes to the widget type, which are asynchronous. */
|
||||||
@@ -36,6 +45,15 @@ function useNoteInfo() {
|
|||||||
return { note, type };
|
return { note, type };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCorrespondingWidget(noteType: ExtendedNoteType | undefined) {
|
||||||
|
switch (noteType) {
|
||||||
|
case "empty":
|
||||||
|
return <Empty />
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function getWidgetType(note: FNote | null | undefined, noteContext: NoteContext | undefined): Promise<ExtendedNoteType> {
|
async function getWidgetType(note: FNote | null | undefined, noteContext: NoteContext | undefined): Promise<ExtendedNoteType> {
|
||||||
if (!note) {
|
if (!note) {
|
||||||
return "empty";
|
return "empty";
|
||||||
|
|||||||
38
apps/client/src/widgets/type_widgets/Empty.css
Normal file
38
apps/client/src/widgets/type_widgets/Empty.css
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.workspace-notes {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-notes .workspace-note {
|
||||||
|
width: 130px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px;
|
||||||
|
border: 1px transparent solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-notes .workspace-note:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid var(--main-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-empty-results .aa-dropdown-menu {
|
||||||
|
max-height: 50vh;
|
||||||
|
overflow: scroll;
|
||||||
|
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-tab-search .note-autocomplete-input {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-tab-search .input-clearer-button {
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-icon {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 500%;
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { useEffect, useRef } from "preact/hooks";
|
||||||
|
import { t } from "../../services/i18n";
|
||||||
|
import FormGroup from "../react/FormGroup";
|
||||||
|
import NoteAutocomplete from "../react/NoteAutocomplete";
|
||||||
|
import "./Empty.css";
|
||||||
|
import { refToJQuerySelector } from "../react/react_utils";
|
||||||
|
import note_autocomplete from "../../services/note_autocomplete";
|
||||||
|
import appContext from "../../components/app_context";
|
||||||
|
|
||||||
|
export default function Empty() {
|
||||||
|
return (
|
||||||
|
<div class="note-detail-empty note-detail-printable">
|
||||||
|
<div class="workspace-notes"></div>
|
||||||
|
|
||||||
|
<NoteSearch />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NoteSearch() {
|
||||||
|
const resultsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const autocompleteRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
// Show recent notes.
|
||||||
|
useEffect(() => {
|
||||||
|
const $autoComplete = refToJQuerySelector(autocompleteRef);
|
||||||
|
note_autocomplete.showRecentNotes($autoComplete);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormGroup name="empty-tab-search" label={t("empty.open_note_instruction")} className="empty-tab-search">
|
||||||
|
<NoteAutocomplete
|
||||||
|
placeholder={t("empty.search_placeholder")}
|
||||||
|
container={resultsContainerRef}
|
||||||
|
inputRef={autocompleteRef}
|
||||||
|
opts={{
|
||||||
|
hideGoToSelectedNoteButton: true,
|
||||||
|
allowCreatingNotes: true,
|
||||||
|
allowJumpToSearchNotes: true,
|
||||||
|
}}
|
||||||
|
onChange={suggestion => {
|
||||||
|
if (!suggestion?.notePath) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeContext = appContext.tabManager.getActiveContext();
|
||||||
|
if (activeContext) {
|
||||||
|
activeContext.setNote(suggestion.notePath);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<div ref={resultsContainerRef} className="note-detail-empty-results" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,57 +5,7 @@ import searchService from "../../services/search.js";
|
|||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
const TPL = /*html*/`
|
||||||
<div class="note-detail-empty note-detail-printable">
|
`;
|
||||||
<style>
|
|
||||||
.workspace-notes {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-notes .workspace-note {
|
|
||||||
width: 130px;
|
|
||||||
text-align: center;
|
|
||||||
margin: 10px;
|
|
||||||
border: 1px transparent solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-notes .workspace-note:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--main-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-detail-empty-results .aa-dropdown-menu {
|
|
||||||
max-height: 50vh;
|
|
||||||
overflow: scroll;
|
|
||||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
|
||||||
border-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-tab-search .note-autocomplete-input {
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-tab-search .input-clearer-button {
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-icon {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 500%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="workspace-notes"></div>
|
|
||||||
<div class="form-group empty-tab-search">
|
|
||||||
<label>${t("empty.open_note_instruction")}</label>
|
|
||||||
<div class="input-group mt-1">
|
|
||||||
<input class="form-control note-autocomplete" placeholder="${t("empty.search_placeholder")}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="note-detail-empty-results"></div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
export default class EmptyTypeWidget extends TypeWidget {
|
export default class EmptyTypeWidget extends TypeWidget {
|
||||||
|
|
||||||
@@ -73,28 +23,8 @@ export default class EmptyTypeWidget extends TypeWidget {
|
|||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$autoComplete = this.$widget.find(".note-autocomplete");
|
this.$autoComplete = this.$widget.find(".note-autocomplete");
|
||||||
this.$results = this.$widget.find(".note-detail-empty-results");
|
this.$results = this.$widget.find(".note-detail-empty-results");
|
||||||
|
|
||||||
noteAutocompleteService
|
|
||||||
.initNoteAutocomplete(this.$autoComplete, {
|
|
||||||
hideGoToSelectedNoteButton: true,
|
|
||||||
allowCreatingNotes: true,
|
|
||||||
allowJumpToSearchNotes: true,
|
|
||||||
container: this.$results[0]
|
|
||||||
})
|
|
||||||
.on("autocomplete:noteselected", function (event, suggestion, dataset) {
|
|
||||||
if (!suggestion.notePath) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeContext = appContext.tabManager.getActiveContext();
|
|
||||||
if (activeContext) {
|
|
||||||
activeContext.setNote(suggestion.notePath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$workspaceNotes = this.$widget.find(".workspace-notes");
|
this.$workspaceNotes = this.$widget.find(".workspace-notes");
|
||||||
|
|
||||||
noteAutocompleteService.showRecentNotes(this.$autoComplete);
|
|
||||||
super.doRender();
|
super.doRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user