mirror of
https://github.com/zadam/trilium.git
synced 2026-02-04 04:44:25 +01:00
chore(collections): add collection toolbar to all collections
This commit is contained in:
parent
88ba4451eb
commit
1c9f8a2540
@ -1,20 +1,23 @@
|
||||
import { Dispatch, StateUpdater, useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import "./index.css";
|
||||
import { ColumnMap, getBoardData } from "./data";
|
||||
|
||||
import { createContext, TargetedKeyboardEvent } from "preact";
|
||||
import { Dispatch, StateUpdater, useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
|
||||
import FNote from "../../../entities/fnote";
|
||||
import { t } from "../../../services/i18n";
|
||||
import toast from "../../../services/toast";
|
||||
import CollectionProperties from "../../note_bars/CollectionProperties";
|
||||
import FormTextArea from "../../react/FormTextArea";
|
||||
import FormTextBox from "../../react/FormTextBox";
|
||||
import { useNoteLabelBoolean, useNoteLabelWithDefault, useTriliumEvent } from "../../react/hooks";
|
||||
import Icon from "../../react/Icon";
|
||||
import { t } from "../../../services/i18n";
|
||||
import Api from "./api";
|
||||
import FormTextBox from "../../react/FormTextBox";
|
||||
import { createContext, TargetedKeyboardEvent } from "preact";
|
||||
import { onWheelHorizontalScroll } from "../../widget_utils";
|
||||
import Column from "./column";
|
||||
import BoardApi from "./api";
|
||||
import FormTextArea from "../../react/FormTextArea";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import NoteAutocomplete from "../../react/NoteAutocomplete";
|
||||
import toast from "../../../services/toast";
|
||||
import { onWheelHorizontalScroll } from "../../widget_utils";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import Api from "./api";
|
||||
import BoardApi from "./api";
|
||||
import Column from "./column";
|
||||
import { ColumnMap, getBoardData } from "./data";
|
||||
|
||||
export interface BoardViewData {
|
||||
columns?: BoardColumnData[];
|
||||
@ -145,7 +148,7 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
|
||||
const insertBefore = mouseX < columnMiddle;
|
||||
|
||||
// Calculate the target position
|
||||
let targetIndex = insertBefore ? index : index + 1;
|
||||
const targetIndex = insertBefore ? index : index + 1;
|
||||
|
||||
setColumnDropPosition(targetIndex);
|
||||
}, [draggedColumn]);
|
||||
@ -163,6 +166,7 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
|
||||
className="board-view"
|
||||
onWheel={onWheelHorizontalScroll}
|
||||
>
|
||||
<CollectionProperties note={parentNote} />
|
||||
<BoardViewContext.Provider value={boardViewContext}>
|
||||
{byColumn && columns && <div
|
||||
className="board-view-container"
|
||||
@ -194,7 +198,7 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
|
||||
</div>}
|
||||
</BoardViewContext.Provider>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function AddNewColumn({ api, isInRelationMode }: { api: BoardApi, isInRelationMode: boolean }) {
|
||||
@ -218,26 +222,26 @@ function AddNewColumn({ api, isInRelationMode }: { api: BoardApi, isInRelationMo
|
||||
tabIndex={300}
|
||||
>
|
||||
{!isCreatingNewColumn
|
||||
? <>
|
||||
<Icon icon="bx bx-plus" />{" "}
|
||||
{t("board_view.add-column")}
|
||||
</>
|
||||
: (
|
||||
<TitleEditor
|
||||
placeholder={t("board_view.add-column-placeholder")}
|
||||
save={async (columnName) => {
|
||||
const created = await api.addNewColumn(columnName);
|
||||
if (!created) {
|
||||
toast.showMessage(t("board_view.column-already-exists"), undefined, "bx bx-duplicate");
|
||||
}
|
||||
}}
|
||||
dismiss={() => setIsCreatingNewColumn(false)}
|
||||
isNewItem
|
||||
mode={isInRelationMode ? "relation" : "normal"}
|
||||
/>
|
||||
)}
|
||||
? <>
|
||||
<Icon icon="bx bx-plus" />{" "}
|
||||
{t("board_view.add-column")}
|
||||
</>
|
||||
: (
|
||||
<TitleEditor
|
||||
placeholder={t("board_view.add-column-placeholder")}
|
||||
save={async (columnName) => {
|
||||
const created = await api.addNewColumn(columnName);
|
||||
if (!created) {
|
||||
toast.showMessage(t("board_view.column-already-exists"), undefined, "bx bx-duplicate");
|
||||
}
|
||||
}}
|
||||
dismiss={() => setIsCreatingNewColumn(false)}
|
||||
isNewItem
|
||||
mode={isInRelationMode ? "relation" : "normal"}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function TitleEditor({ currentValue, placeholder, save, dismiss, mode, isNewItem }: {
|
||||
@ -302,26 +306,26 @@ export function TitleEditor({ currentValue, placeholder, save, dismiss, mode, is
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<NoteAutocomplete
|
||||
inputRef={inputRef}
|
||||
noteId={currentValue ?? ""}
|
||||
opts={{
|
||||
hideAllButtons: true,
|
||||
allowCreatingNotes: true
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Escape") {
|
||||
dismiss();
|
||||
}
|
||||
}}
|
||||
onBlur={() => dismiss()}
|
||||
noteIdChanged={(newValue) => {
|
||||
save(newValue);
|
||||
dismiss();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NoteAutocomplete
|
||||
inputRef={inputRef}
|
||||
noteId={currentValue ?? ""}
|
||||
opts={{
|
||||
hideAllButtons: true,
|
||||
allowCreatingNotes: true
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Escape") {
|
||||
dismiss();
|
||||
}
|
||||
}}
|
||||
onBlur={() => dismiss()}
|
||||
noteIdChanged={(newValue) => {
|
||||
save(newValue);
|
||||
dismiss();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -1,24 +1,27 @@
|
||||
import Map from "./map";
|
||||
import "./index.css";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { useNoteBlob, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useNoteTreeDrag, useSpacedUpdate, useTriliumEvent } from "../../react/hooks";
|
||||
import { DEFAULT_MAP_LAYER_NAME } from "./map_layer";
|
||||
|
||||
import { divIcon, GPXOptions, LatLng, LeafletMouseEvent } from "leaflet";
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
import Marker, { GpxTrack } from "./marker";
|
||||
import froca from "../../../services/froca";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import markerIcon from "leaflet/dist/images/marker-icon.png";
|
||||
import markerIconShadow from "leaflet/dist/images/marker-shadow.png";
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
|
||||
import appContext from "../../../components/app_context";
|
||||
import { createNewNote, moveMarker } from "./api";
|
||||
import openContextMenu, { openMapContextMenu } from "./context_menu";
|
||||
import toast from "../../../services/toast";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import branches from "../../../services/branches";
|
||||
import froca from "../../../services/froca";
|
||||
import { t } from "../../../services/i18n";
|
||||
import server from "../../../services/server";
|
||||
import branches from "../../../services/branches";
|
||||
import TouchBar, { TouchBarButton, TouchBarLabel, TouchBarSlider } from "../../react/TouchBar";
|
||||
import toast from "../../../services/toast";
|
||||
import CollectionProperties from "../../note_bars/CollectionProperties";
|
||||
import { useNoteBlob, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useNoteTreeDrag, useSpacedUpdate, useTriliumEvent } from "../../react/hooks";
|
||||
import { ParentComponent } from "../../react/react_utils";
|
||||
import TouchBar, { TouchBarButton, TouchBarLabel, TouchBarSlider } from "../../react/TouchBar";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { createNewNote, moveMarker } from "./api";
|
||||
import openContextMenu, { openMapContextMenu } from "./context_menu";
|
||||
import Map from "./map";
|
||||
import { DEFAULT_MAP_LAYER_NAME } from "./map_layer";
|
||||
import Marker, { GpxTrack } from "./marker";
|
||||
|
||||
const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
|
||||
const DEFAULT_ZOOM = 2;
|
||||
@ -50,7 +53,7 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
useEffect(() => { froca.getNotes(noteIds).then(setNotes) }, [ noteIds ]);
|
||||
useEffect(() => { froca.getNotes(noteIds).then(setNotes); }, [ noteIds ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!note) return;
|
||||
@ -60,7 +63,7 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
|
||||
// Note creation.
|
||||
useTriliumEvent("geoMapCreateChildNote", () => {
|
||||
toast.showPersistent({
|
||||
toast.showPersistent({
|
||||
icon: "plus",
|
||||
id: "geo-new-note",
|
||||
title: "New note",
|
||||
@ -130,6 +133,7 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
|
||||
return (
|
||||
<div className={`geo-view ${state === State.NewNote ? "placing-note" : ""}`}>
|
||||
<CollectionProperties note={note} />
|
||||
{ coordinates !== undefined && zoom !== undefined && <Map
|
||||
apiRef={apiRef} containerRef={containerRef}
|
||||
coordinates={coordinates}
|
||||
@ -204,7 +208,7 @@ function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean
|
||||
onDragged={editable ? onDragged : undefined}
|
||||
onClick={!editable ? onClick : undefined}
|
||||
onContextMenu={onContextMenu}
|
||||
/>
|
||||
/>;
|
||||
}
|
||||
|
||||
function NoteGpxTrack({ note }: { note: FNote }) {
|
||||
@ -238,7 +242,7 @@ function NoteGpxTrack({ note }: { note: FNote }) {
|
||||
color: note.getLabelValue("color") ?? "blue"
|
||||
}
|
||||
}), [ color, iconClass ]);
|
||||
return xmlString && <GpxTrack gpxXmlString={xmlString} options={options} />
|
||||
return xmlString && <GpxTrack gpxXmlString={xmlString} options={options} />;
|
||||
}
|
||||
|
||||
function buildIcon(bxIconClass: string, colorClass?: string, title?: string, noteIdLink?: string, archived?: boolean) {
|
||||
@ -292,5 +296,5 @@ function GeoMapTouchBar({ state, map }: { state: State, map: L.Map | null | unde
|
||||
enabled={state === State.Normal}
|
||||
/>
|
||||
</TouchBar>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import attribute_renderer from "../../../services/attribute_renderer";
|
||||
import content_renderer from "../../../services/content_renderer";
|
||||
import { t } from "../../../services/i18n";
|
||||
import link from "../../../services/link";
|
||||
import CollectionProperties from "../../note_bars/CollectionProperties";
|
||||
import { useImperativeSearchHighlighlighting, useNoteLabel, useNoteLabelBoolean } from "../../react/hooks";
|
||||
import Icon from "../../react/Icon";
|
||||
import NoteLink from "../../react/NoteLink";
|
||||
@ -22,6 +23,8 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
|
||||
return (
|
||||
<div class="note-list list-view">
|
||||
<CollectionProperties note={note} />
|
||||
|
||||
{ noteIds.length > 0 && <div class="note-list-wrapper">
|
||||
<Pager {...pagination} />
|
||||
|
||||
@ -48,6 +51,8 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
|
||||
return (
|
||||
<div class="note-list grid-view">
|
||||
<CollectionProperties note={note} />
|
||||
|
||||
<div class="note-list-wrapper">
|
||||
<Pager {...pagination} />
|
||||
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
import { ViewModeMedia, ViewModeProps } from "../interface";
|
||||
import "./index.css";
|
||||
|
||||
import { RefObject } from "preact";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||
import Reveal from "reveal.js";
|
||||
import slideBaseStylesheet from "reveal.js/dist/reveal.css?raw";
|
||||
import slideCustomStylesheet from "./slidejs.css?raw";
|
||||
import { buildPresentationModel, PresentationModel, PresentationSlideBaseModel } from "./model";
|
||||
import ShadowDom from "../../react/ShadowDom";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import "./index.css";
|
||||
import { RefObject } from "preact";
|
||||
|
||||
import { openInCurrentNoteContext } from "../../../components/note_context";
|
||||
import { useNoteLabelWithDefault, useTriliumEvent } from "../../react/hooks";
|
||||
import { t } from "../../../services/i18n";
|
||||
import { DEFAULT_THEME, loadPresentationTheme } from "./themes";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import { t } from "../../../services/i18n";
|
||||
import CollectionProperties from "../../note_bars/CollectionProperties";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import { useNoteLabelWithDefault, useTriliumEvent } from "../../react/hooks";
|
||||
import ShadowDom from "../../react/ShadowDom";
|
||||
import { ViewModeMedia, ViewModeProps } from "../interface";
|
||||
import { buildPresentationModel, PresentationModel, PresentationSlideBaseModel } from "./model";
|
||||
import slideCustomStylesheet from "./slidejs.css?raw";
|
||||
import { DEFAULT_THEME, loadPresentationTheme } from "./themes";
|
||||
|
||||
export default function PresentationView({ note, noteIds, media, onReady, onProgressChanged }: ViewModeProps<{}>) {
|
||||
const [ presentation, setPresentation ] = useState<PresentationModel>();
|
||||
@ -52,13 +55,14 @@ export default function PresentationView({ note, noteIds, media, onReady, onProg
|
||||
if (media === "screen") {
|
||||
return (
|
||||
<>
|
||||
<CollectionProperties note={note} />
|
||||
<ShadowDom
|
||||
className="presentation-container"
|
||||
containerRef={containerRef}
|
||||
>{content}</ShadowDom>
|
||||
<ButtonOverlay containerRef={containerRef} api={api} />
|
||||
</>
|
||||
)
|
||||
);
|
||||
} else if (media === "print") {
|
||||
// Printing needs a query parameter that is read by Reveal.js.
|
||||
const url = new URL(window.location.href);
|
||||
@ -143,7 +147,7 @@ function ButtonOverlay({ containerRef, api }: { containerRef: RefObject<HTMLDivE
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function Presentation({ presentation, setApi } : { presentation: PresentationModel, setApi: (api: Reveal.Api | undefined) => void }) {
|
||||
@ -179,7 +183,7 @@ function Presentation({ presentation, setApi } : { presentation: PresentationMod
|
||||
api.destroy();
|
||||
setRevealApi(undefined);
|
||||
setApi(undefined);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@ -191,19 +195,19 @@ function Presentation({ presentation, setApi } : { presentation: PresentationMod
|
||||
<div className="slides">
|
||||
{presentation.slides?.map(slide => {
|
||||
if (!slide.verticalSlides) {
|
||||
return <Slide key={slide.noteId} slide={slide} />
|
||||
} else {
|
||||
return (
|
||||
<section>
|
||||
<Slide key={slide.noteId} slide={slide} />
|
||||
{slide.verticalSlides.map(slide => <Slide key={slide.noteId} slide={slide} /> )}
|
||||
</section>
|
||||
);
|
||||
return <Slide key={slide.noteId} slide={slide} />;
|
||||
}
|
||||
return (
|
||||
<section>
|
||||
<Slide key={slide.noteId} slide={slide} />
|
||||
{slide.verticalSlides.map(slide => <Slide key={slide.noteId} slide={slide} /> )}
|
||||
</section>
|
||||
);
|
||||
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
import "./index.css";
|
||||
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { TableData } from "./rows";
|
||||
import { useLegacyWidget } from "../../react/hooks";
|
||||
import Tabulator from "./tabulator";
|
||||
import { Tabulator as VanillaTabulator, SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, DataTreeModule, Options, RowComponent} from 'tabulator-tables';
|
||||
import { useContextMenu } from "./context_menu";
|
||||
import { ParentComponent } from "../../react/react_utils";
|
||||
import { DataTreeModule, EditModule, FormatModule, FrozenColumnsModule, InteractionModule, MoveColumnsModule, MoveRowsModule, Options, PersistenceModule, ResizeColumnsModule, RowComponent,SortModule, Tabulator as VanillaTabulator} from 'tabulator-tables';
|
||||
|
||||
import FNote from "../../../entities/fnote";
|
||||
import { t } from "../../../services/i18n";
|
||||
import Button from "../../react/Button";
|
||||
import "./index.css";
|
||||
import useRowTableEditing from "./row_editing";
|
||||
import useColTableEditing from "./col_editing";
|
||||
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
||||
import SpacedUpdate from "../../../services/spaced_update";
|
||||
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
||||
import CollectionProperties from "../../note_bars/CollectionProperties";
|
||||
import Button from "../../react/Button";
|
||||
import { useLegacyWidget } from "../../react/hooks";
|
||||
import { ParentComponent } from "../../react/react_utils";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import useColTableEditing from "./col_editing";
|
||||
import { useContextMenu } from "./context_menu";
|
||||
import useData, { TableConfig } from "./data";
|
||||
import useRowTableEditing from "./row_editing";
|
||||
import { TableData } from "./rows";
|
||||
import Tabulator from "./tabulator";
|
||||
|
||||
export default function TableView({ note, noteIds, notePath, viewConfig, saveConfig }: ViewModeProps<TableConfig>) {
|
||||
const tabulatorRef = useRef<VanillaTabulator>(null);
|
||||
@ -36,7 +39,7 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
|
||||
dataTreeChildIndent: 20,
|
||||
dataTreeExpandElement: `<button class="tree-expand"><span class="bx bx-chevron-right"></span></button>`,
|
||||
dataTreeCollapseElement: `<button class="tree-collapse"><span class="bx bx-chevron-down"></span></button>`
|
||||
}
|
||||
};
|
||||
}, [ hasChildren ]);
|
||||
|
||||
const rowFormatter = useCallback((row: RowComponent) => {
|
||||
@ -46,6 +49,8 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
|
||||
|
||||
return (
|
||||
<div className="table-view">
|
||||
<CollectionProperties note={note} />
|
||||
|
||||
{rowData !== undefined && persistenceProps && (
|
||||
<>
|
||||
<Tabulator
|
||||
@ -72,7 +77,7 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
|
||||
)}
|
||||
{attributeDetailWidgetEl}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function TableFooter({ note }: { note: FNote }) {
|
||||
@ -84,7 +89,7 @@ function TableFooter({ note }: { note: FNote }) {
|
||||
<Button triggerCommand="addNewTableColumn" icon="bx bx-carousel" text={t("table_view.new-column")} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function usePersistence(viewConfig: TableConfig | null | undefined, saveConfig: (newConfig: TableConfig) => void) {
|
||||
|
||||
@ -30,12 +30,10 @@
|
||||
|
||||
@media (max-width: 991px) {
|
||||
flex-wrap: wrap;
|
||||
padding: 0.55em 1em;
|
||||
margin: 0;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
>div {
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user