mirror of
https://github.com/zadam/trilium.git
synced 2025-12-12 18:34:24 +01:00
New layout: Integrate small ribbon categories + collection properties (#8018)
This commit is contained in:
commit
792a10ace5
@ -2031,7 +2031,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Hide weekends",
|
||||
"display-week-numbers": "Display week numbers",
|
||||
"map-style": "Map style:",
|
||||
"map-style": "Map style",
|
||||
"max-nesting-depth": "Max nesting depth:",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector (Light)",
|
||||
@ -2146,6 +2146,12 @@
|
||||
"backlinks_one": "{{count}} backlink",
|
||||
"backlinks_other": "{{count}} backlinks",
|
||||
"backlinks_description_one": "This note is linked from {{count}} other note.\n\nClick to view the list of backlinks.",
|
||||
"backlinks_description_other": "This note is linked from {{count}} other notes.\n\nClick to view the list of backlinks."
|
||||
"backlinks_description_other": "This note is linked from {{count}} other notes.\n\nClick to view the list of backlinks.",
|
||||
"clipped_note": "Web clip",
|
||||
"clipped_note_description": "This note was originally taken from {{url}}.\n\nClick to navigate to the source webpage.",
|
||||
"execute_script": "Run script",
|
||||
"execute_script_description": "This note is a script note. Click to execute the script.",
|
||||
"execute_sql": "Run SQL",
|
||||
"execute_sql_description": "This note is a SQL note. Click to execute the SQL query."
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,9 @@
|
||||
&.temporarily-editable-badge { --color: #4fa52b; }
|
||||
&.read-only-badge { --color: #e33f3b; }
|
||||
&.share-badge { --color: #3b82f6; }
|
||||
&.clipped-note-badge { --color: #57a2a5; }
|
||||
&.backlinks-badge { color: var(--badge-text-color); }
|
||||
&.execute-badge { --color: #f59e0b; }
|
||||
|
||||
a {
|
||||
color: inherit !important;
|
||||
|
||||
@ -8,7 +8,7 @@ import { t } from "../services/i18n";
|
||||
import { formatDateTime } from "../utils/formatters";
|
||||
import { BacklinksList, useBacklinkCount } from "./FloatingButtonsDefinitions";
|
||||
import Dropdown, { DropdownProps } from "./react/Dropdown";
|
||||
import { useIsNoteReadOnly, useNoteContext, useStaticTooltip } from "./react/hooks";
|
||||
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean, useStaticTooltip } from "./react/hooks";
|
||||
import Icon from "./react/Icon";
|
||||
import { NoteSizeWidget, useNoteMetadata } from "./ribbon/NoteInfoTab";
|
||||
import { useShareInfo } from "./shared_info";
|
||||
@ -20,6 +20,8 @@ export default function BreadcrumbBadges() {
|
||||
<ReadOnlyBadge />
|
||||
<ShareBadge />
|
||||
<BacklinksBadge />
|
||||
<ClippedNoteBadge />
|
||||
<ExecuteBadge />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -114,6 +116,40 @@ function BacklinksBadge() {
|
||||
);
|
||||
}
|
||||
|
||||
function ClippedNoteBadge() {
|
||||
const { note } = useNoteContext();
|
||||
const [ pageUrl ] = useNoteLabel(note, "pageUrl");
|
||||
|
||||
return (pageUrl &&
|
||||
<Badge
|
||||
className="clipped-note-badge"
|
||||
icon="bx bx-globe"
|
||||
text={t("breadcrumb_badges.clipped_note")}
|
||||
tooltip={t("breadcrumb_badges.clipped_note_description", { url: pageUrl })}
|
||||
href={pageUrl}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ExecuteBadge() {
|
||||
const { note, parentComponent } = useNoteContext();
|
||||
const isScript = note?.isTriliumScript();
|
||||
const isSql = note?.isTriliumSqlite();
|
||||
const isExecutable = isScript || isSql;
|
||||
const [ executeDescription ] = useNoteLabel(note, "executeDescription");
|
||||
const [ executeButton ] = useNoteLabelBoolean(note, "executeButton");
|
||||
|
||||
return (note && isExecutable && (executeDescription || executeButton) &&
|
||||
<Badge
|
||||
className="execute-badge"
|
||||
icon="bx bx-play"
|
||||
text={isScript ? t("breadcrumb_badges.execute_script") : t("breadcrumb_badges.execute_sql")}
|
||||
tooltip={executeDescription || (isScript ? t("breadcrumb_badges.execute_script_description") : t("breadcrumb_badges.execute_sql_description"))}
|
||||
onClick={() => parentComponent.triggerCommand("runActiveNote")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
interface BadgeProps {
|
||||
text?: string;
|
||||
icon?: string;
|
||||
|
||||
@ -300,8 +300,9 @@ function ExportImageButtons({ note, triggerEvent, isDefaultViewMode }: FloatingB
|
||||
|
||||
function InAppHelpButton({ note }: FloatingButtonContext) {
|
||||
const helpUrl = getHelpUrlForNote(note);
|
||||
const isEnabled = !!helpUrl && (!isNewLayout || (note?.type !== "book"));
|
||||
|
||||
return !!helpUrl && (
|
||||
return isEnabled && (
|
||||
<FloatingButton
|
||||
icon="bx bx-help-circle"
|
||||
text={t("help-button.title")}
|
||||
|
||||
@ -1,46 +1,13 @@
|
||||
import { type ComponentChild } from "preact";
|
||||
|
||||
import { formatDateTime } from "../utils/formatters";
|
||||
import { useNoteContext, useStaticTooltip } from "./react/hooks";
|
||||
import { joinElements } from "./react/react_utils";
|
||||
import { useNoteMetadata } from "./ribbon/NoteInfoTab";
|
||||
import { Trans } from "react-i18next";
|
||||
import { useRef } from "preact/hooks";
|
||||
import CollectionProperties from "./note_bars/CollectionProperties";
|
||||
import { useNoteContext, useNoteProperty } from "./react/hooks";
|
||||
|
||||
export default function NoteTitleDetails() {
|
||||
const { note, noteContext } = useNoteContext();
|
||||
const isHiddenNote = note?.noteId.startsWith("_");
|
||||
const isDefaultView = noteContext?.viewScope?.viewMode === "default";
|
||||
const { note } = useNoteContext();
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
|
||||
const items: ComponentChild[] = [].filter(item => !!item);
|
||||
|
||||
return items.length && (
|
||||
return (
|
||||
<div className="title-details">
|
||||
{joinElements(items, " • ")}
|
||||
{note && noteType === "book" && <CollectionProperties note={note} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function TextWithValue({ i18nKey, value, valueTooltip }: {
|
||||
i18nKey: string;
|
||||
value: string;
|
||||
valueTooltip: string;
|
||||
}) {
|
||||
const listItemRef = useRef<HTMLLIElement>(null);
|
||||
useStaticTooltip(listItemRef, {
|
||||
selector: "span.value",
|
||||
title: valueTooltip,
|
||||
popperConfig: { placement: "bottom" }
|
||||
});
|
||||
|
||||
return (
|
||||
<li ref={listItemRef}>
|
||||
<Trans
|
||||
i18nKey={i18nKey}
|
||||
components={{
|
||||
Value: <span className="value">{value}</span> as React.ReactElement
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
220
apps/client/src/widgets/note_bars/CollectionProperties.tsx
Normal file
220
apps/client/src/widgets/note_bars/CollectionProperties.tsx
Normal file
@ -0,0 +1,220 @@
|
||||
import { t } from "i18next";
|
||||
import { useContext } from "preact/hooks";
|
||||
import { Fragment } from "preact/jsx-runtime";
|
||||
|
||||
import FNote from "../../entities/fnote";
|
||||
import { ViewTypeOptions } from "../collections/interface";
|
||||
import Dropdown from "../react/Dropdown";
|
||||
import { FormDropdownDivider, FormDropdownSubmenu, FormListItem, FormListToggleableItem } from "../react/FormList";
|
||||
import FormTextBox from "../react/FormTextBox";
|
||||
import { useNoteLabel, useNoteLabelBoolean, useNoteLabelWithDefault } from "../react/hooks";
|
||||
import Icon from "../react/Icon";
|
||||
import { ParentComponent } from "../react/react_utils";
|
||||
import { bookPropertiesConfig, BookProperty, ButtonProperty, CheckBoxProperty, ComboBoxItem, ComboBoxProperty, NumberProperty, SplitButtonProperty } from "../ribbon/collection-properties-config";
|
||||
import { useViewType, VIEW_TYPE_MAPPINGS } from "../ribbon/CollectionPropertiesTab";
|
||||
import ActionButton from "../react/ActionButton";
|
||||
import { getHelpUrlForNote } from "../../services/in_app_help";
|
||||
import { openInAppHelpFromUrl } from "../../services/utils";
|
||||
|
||||
const ICON_MAPPINGS: Record<ViewTypeOptions, string> = {
|
||||
grid: "bx bxs-grid",
|
||||
list: "bx bx-list-ul",
|
||||
calendar: "bx bx-calendar",
|
||||
table: "bx bx-table",
|
||||
geoMap: "bx bx-map-alt",
|
||||
board: "bx bx-columns",
|
||||
presentation: "bx bx-rectangle"
|
||||
};
|
||||
|
||||
export default function CollectionProperties({ note }: { note: FNote }) {
|
||||
const [ viewType, setViewType ] = useViewType(note);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewTypeSwitcher viewType={viewType} setViewType={setViewType} />
|
||||
<ViewOptions note={note} viewType={viewType} />
|
||||
<div className="spacer" />
|
||||
<HelpButton note={note} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ViewTypeSwitcher({ viewType, setViewType }: { viewType: ViewTypeOptions, setViewType: (newValue: ViewTypeOptions) => void }) {
|
||||
return (
|
||||
<Dropdown
|
||||
text={<>
|
||||
<Icon icon={ICON_MAPPINGS[viewType]} />
|
||||
{VIEW_TYPE_MAPPINGS[viewType]}
|
||||
</>}
|
||||
>
|
||||
{Object.entries(VIEW_TYPE_MAPPINGS).map(([ key, label ]) => (
|
||||
<FormListItem
|
||||
key={key}
|
||||
onClick={() => setViewType(key as ViewTypeOptions)}
|
||||
selected={viewType === key}
|
||||
disabled={viewType === key}
|
||||
icon={ICON_MAPPINGS[key as ViewTypeOptions]}
|
||||
>{label}</FormListItem>
|
||||
))}
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
function ViewOptions({ note, viewType }: { note: FNote, viewType: ViewTypeOptions }) {
|
||||
const properties = bookPropertiesConfig[viewType].properties;
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
buttonClassName="bx bx-cog icon-action"
|
||||
hideToggleArrow
|
||||
>
|
||||
{properties.map(property => (
|
||||
<ViewProperty key={property.label} note={note} property={property} />
|
||||
))}
|
||||
{properties.length > 0 && <FormDropdownDivider />}
|
||||
|
||||
<ViewProperty note={note} property={{
|
||||
type: "checkbox",
|
||||
icon: "bx bx-archive",
|
||||
label: t("book_properties.include_archived_notes"),
|
||||
bindToLabel: "includeArchived"
|
||||
} as CheckBoxProperty} />
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
function ViewProperty({ note, property }: { note: FNote, property: BookProperty }) {
|
||||
switch (property.type) {
|
||||
case "button":
|
||||
return <ButtonPropertyView note={note} property={property} />;
|
||||
case "split-button":
|
||||
return <SplitButtonPropertyView note={note} property={property} />;
|
||||
case "checkbox":
|
||||
return <CheckBoxPropertyView note={note} property={property} />;
|
||||
case "number":
|
||||
return <NumberPropertyView note={note} property={property} />;
|
||||
case "combobox":
|
||||
return <ComboBoxPropertyView note={note} property={property} />;
|
||||
}
|
||||
}
|
||||
|
||||
function ButtonPropertyView({ note, property }: { note: FNote, property: ButtonProperty }) {
|
||||
const parentComponent = useContext(ParentComponent);
|
||||
|
||||
return (
|
||||
<FormListItem
|
||||
icon={property.icon}
|
||||
title={property.title}
|
||||
onClick={() => {
|
||||
if (!parentComponent) return;
|
||||
property.onClick({
|
||||
note,
|
||||
triggerCommand: parentComponent.triggerCommand.bind(parentComponent)
|
||||
});
|
||||
}}
|
||||
>{property.label}</FormListItem>
|
||||
);
|
||||
}
|
||||
|
||||
function SplitButtonPropertyView({ note, property }: { note: FNote, property: SplitButtonProperty }) {
|
||||
const parentComponent = useContext(ParentComponent);
|
||||
const ItemsComponent = property.items;
|
||||
const clickContext = parentComponent && {
|
||||
note,
|
||||
triggerCommand: parentComponent.triggerCommand.bind(parentComponent)
|
||||
};
|
||||
|
||||
return (parentComponent &&
|
||||
<FormDropdownSubmenu
|
||||
icon={property.icon ?? "bx bx-empty"}
|
||||
title={property.label}
|
||||
onDropdownToggleClicked={() => clickContext && property.onClick(clickContext)}
|
||||
>
|
||||
<ItemsComponent note={note} parentComponent={parentComponent} />
|
||||
</FormDropdownSubmenu>
|
||||
);
|
||||
}
|
||||
|
||||
function NumberPropertyView({ note, property }: { note: FNote, property: NumberProperty }) {
|
||||
//@ts-expect-error Interop with text box which takes in string values even for numbers.
|
||||
const [ value, setValue ] = useNoteLabel(note, property.bindToLabel);
|
||||
const disabled = property.disabled?.(note);
|
||||
|
||||
return (
|
||||
<FormListItem
|
||||
icon={property.icon}
|
||||
disabled={disabled}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{property.label}
|
||||
<FormTextBox
|
||||
type="number"
|
||||
currentValue={value ?? ""} onChange={setValue}
|
||||
style={{ width: (property.width ?? 100) }}
|
||||
min={property.min ?? 0}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</FormListItem>
|
||||
);
|
||||
}
|
||||
|
||||
function ComboBoxPropertyView({ note, property }: { note: FNote, property: ComboBoxProperty }) {
|
||||
const [ value, setValue ] = useNoteLabelWithDefault(note, property.bindToLabel, property.defaultValue ?? "");
|
||||
|
||||
function renderItem(option: ComboBoxItem) {
|
||||
return (
|
||||
<FormListItem
|
||||
key={option.value}
|
||||
checked={value === option.value}
|
||||
onClick={() => setValue(option.value)}
|
||||
>
|
||||
{option.label}
|
||||
</FormListItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<FormDropdownSubmenu
|
||||
title={property.label}
|
||||
icon={property.icon ?? "bx bx-empty"}
|
||||
>
|
||||
{(property.options).map((option, index) => {
|
||||
if ("items" in option) {
|
||||
return (
|
||||
<Fragment key={option.title}>
|
||||
<FormListItem key={option.title} disabled>{option.title}</FormListItem>
|
||||
{option.items.map(renderItem)}
|
||||
{index < property.options.length - 1 && <FormDropdownDivider />}
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
return renderItem(option);
|
||||
}
|
||||
})}
|
||||
</FormDropdownSubmenu>
|
||||
);
|
||||
}
|
||||
|
||||
function CheckBoxPropertyView({ note, property }: { note: FNote, property: CheckBoxProperty }) {
|
||||
const [ value, setValue ] = useNoteLabelBoolean(note, property.bindToLabel);
|
||||
return (
|
||||
<FormListToggleableItem
|
||||
icon={property.icon}
|
||||
title={property.label}
|
||||
currentValue={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function HelpButton({ note }: { note: FNote }) {
|
||||
const helpUrl = getHelpUrlForNote(note);
|
||||
|
||||
return (helpUrl && (
|
||||
<ActionButton
|
||||
icon="bx bx-help-circle"
|
||||
onClick={(() => openInAppHelpFromUrl(helpUrl))}
|
||||
text={t("help-button.title")}
|
||||
/>
|
||||
));
|
||||
}
|
||||
@ -37,6 +37,21 @@ body.experimental-feature-new-layout {
|
||||
padding-inline-start: 24px;
|
||||
}
|
||||
|
||||
.title-details {
|
||||
padding-inline-end: 16px;
|
||||
|
||||
.dropdown-menu {
|
||||
input.form-control {
|
||||
padding: 2px 8px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.title-row {
|
||||
margin-left: 12px;
|
||||
|
||||
@ -75,7 +90,8 @@ body.experimental-feature-new-layout {
|
||||
}
|
||||
}
|
||||
|
||||
.scrolling-container:has(> :is(.note-detail.full-height, .note-list-widget.full-height)) {
|
||||
.scrolling-container:has(> :is(.note-detail.full-height, .note-list-widget.full-height)),
|
||||
.note-split.type-book {
|
||||
.title-row,
|
||||
.title-details {
|
||||
width: 100%;
|
||||
@ -84,12 +100,11 @@ body.experimental-feature-new-layout {
|
||||
}
|
||||
|
||||
.title-row {
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.title-details {
|
||||
margin-bottom: 0.2em;
|
||||
opacity: 0.65;
|
||||
padding-bottom: 0.2em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,10 +206,11 @@ export function FormDropdownDivider() {
|
||||
return <div className="dropdown-divider" />;
|
||||
}
|
||||
|
||||
export function FormDropdownSubmenu({ icon, title, children, dropStart }: {
|
||||
export function FormDropdownSubmenu({ icon, title, children, dropStart, onDropdownToggleClicked }: {
|
||||
icon: string,
|
||||
title: ComponentChildren,
|
||||
children: ComponentChildren,
|
||||
onDropdownToggleClicked?: () => void,
|
||||
dropStart?: boolean
|
||||
}) {
|
||||
const [ openOnMobile, setOpenOnMobile ] = useState(false);
|
||||
@ -224,6 +225,10 @@ export function FormDropdownSubmenu({ icon, title, children, dropStart }: {
|
||||
if (isMobile()) {
|
||||
setOpenOnMobile(!openOnMobile);
|
||||
}
|
||||
|
||||
if (onDropdownToggleClicked) {
|
||||
onDropdownToggleClicked();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon icon={icon} />{" "}
|
||||
|
||||
@ -12,34 +12,41 @@ import FormCheckbox from "../react/FormCheckbox";
|
||||
import FormTextBox from "../react/FormTextBox";
|
||||
import { ComponentChildren } from "preact";
|
||||
import { ViewTypeOptions } from "../collections/interface";
|
||||
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
||||
import { isExperimentalFeatureEnabled } from "../../services/experimental_features";
|
||||
|
||||
const VIEW_TYPE_MAPPINGS: Record<ViewTypeOptions, string> = {
|
||||
grid: t("book_properties.grid"),
|
||||
list: t("book_properties.list"),
|
||||
calendar: t("book_properties.calendar"),
|
||||
table: t("book_properties.table"),
|
||||
geoMap: t("book_properties.geo-map"),
|
||||
board: t("book_properties.board"),
|
||||
presentation: t("book_properties.presentation")
|
||||
export const VIEW_TYPE_MAPPINGS: Record<ViewTypeOptions, string> = {
|
||||
grid: t("book_properties.grid"),
|
||||
list: t("book_properties.list"),
|
||||
calendar: t("book_properties.calendar"),
|
||||
table: t("book_properties.table"),
|
||||
geoMap: t("book_properties.geo-map"),
|
||||
board: t("book_properties.board"),
|
||||
presentation: t("book_properties.presentation")
|
||||
};
|
||||
|
||||
export default function CollectionPropertiesTab({ note }: TabContext) {
|
||||
const [ viewType, setViewType ] = useNoteLabel(note, "viewType");
|
||||
const defaultViewType = (note?.type === "search" ? "list" : "grid");
|
||||
const viewTypeWithDefault = (viewType ?? defaultViewType) as ViewTypeOptions;
|
||||
const properties = bookPropertiesConfig[viewTypeWithDefault].properties;
|
||||
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
||||
|
||||
return (
|
||||
<div className="book-properties-widget">
|
||||
{note && (
|
||||
<>
|
||||
<CollectionTypeSwitcher viewType={viewTypeWithDefault} setViewType={setViewType} />
|
||||
<BookProperties viewType={viewTypeWithDefault} note={note} properties={properties} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
export default function CollectionPropertiesTab({ note }: TabContext) {
|
||||
const [viewType, setViewType] = useViewType(note);
|
||||
const properties = bookPropertiesConfig[viewType].properties;
|
||||
|
||||
return (
|
||||
<div className="book-properties-widget">
|
||||
{note && (
|
||||
<>
|
||||
{!isNewLayout && <CollectionTypeSwitcher viewType={viewType} setViewType={setViewType} />}
|
||||
<BookProperties viewType={viewType} note={note} properties={properties} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function useViewType(note: FNote | null | undefined) {
|
||||
const [ viewType, setViewType ] = useNoteLabel(note, "viewType");
|
||||
const defaultViewType = (note?.type === "search" ? "list" : "grid");
|
||||
const viewTypeWithDefault = (viewType ?? defaultViewType) as ViewTypeOptions;
|
||||
return [ viewTypeWithDefault, setViewType ] as const;
|
||||
}
|
||||
|
||||
function CollectionTypeSwitcher({ viewType, setViewType }: { viewType: string, setViewType: (newValue: string) => void }) {
|
||||
@ -148,7 +155,7 @@ function NumberPropertyView({ note, property }: { note: FNote, property: NumberP
|
||||
<FormTextBox
|
||||
type="number"
|
||||
currentValue={value ?? ""} onChange={setValue}
|
||||
style={{ width: (property.width ?? 100) + "px" }}
|
||||
style={{ width: (property.width ?? 100) }}
|
||||
min={property.min ?? 0}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@ -38,7 +38,7 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [
|
||||
icon: "bx bx-play",
|
||||
content: ScriptTab,
|
||||
activate: true,
|
||||
show: ({ note }) => note &&
|
||||
show: ({ note }) => note && !isNewLayout &&
|
||||
(note.isTriliumScript() || note.isTriliumSqlite()) &&
|
||||
(note.hasLabel("executeDescription") || note.hasLabel("executeButton"))
|
||||
},
|
||||
@ -60,14 +60,14 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [
|
||||
title: t("book_properties.book_properties"),
|
||||
icon: "bx bx-book",
|
||||
content: CollectionPropertiesTab,
|
||||
show: ({ note }) => note?.type === "book" || note?.type === "search",
|
||||
show: ({ note }) => !isNewLayout && note?.type === "book" || note?.type === "search",
|
||||
toggleCommand: "toggleRibbonTabBookProperties"
|
||||
},
|
||||
{
|
||||
title: t("note_properties.info"),
|
||||
icon: "bx bx-info-square",
|
||||
content: NotePropertiesTab,
|
||||
show: ({ note }) => !!note?.getLabelValue("pageUrl"),
|
||||
show: ({ note }) => !isNewLayout && !!note?.getLabelValue("pageUrl"),
|
||||
activate: true
|
||||
},
|
||||
{
|
||||
|
||||
@ -18,7 +18,8 @@ interface BookConfig {
|
||||
export interface CheckBoxProperty {
|
||||
type: "checkbox",
|
||||
label: string;
|
||||
bindToLabel: FilterLabelsByType<boolean>
|
||||
bindToLabel: FilterLabelsByType<boolean>;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface ButtonProperty {
|
||||
@ -40,10 +41,11 @@ export interface NumberProperty {
|
||||
bindToLabel: FilterLabelsByType<number>;
|
||||
width?: number;
|
||||
min?: number;
|
||||
icon?: string;
|
||||
disabled?: (note: FNote) => boolean;
|
||||
}
|
||||
|
||||
interface ComboBoxItem {
|
||||
export interface ComboBoxItem {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
@ -56,6 +58,7 @@ interface ComboBoxGroup {
|
||||
export interface ComboBoxProperty {
|
||||
type: "combobox",
|
||||
label: string;
|
||||
icon?: string;
|
||||
bindToLabel: FilterLabelsByType<string>;
|
||||
/**
|
||||
* The default value is used when the label is not set.
|
||||
@ -107,11 +110,13 @@ export const bookPropertiesConfig: Record<ViewTypeOptions, BookConfig> = {
|
||||
properties: [
|
||||
{
|
||||
label: t("book_properties_config.hide-weekends"),
|
||||
icon: "bx bx-calendar-week",
|
||||
type: "checkbox",
|
||||
bindToLabel: "calendar:hideWeekends"
|
||||
},
|
||||
{
|
||||
label: t("book_properties_config.display-week-numbers"),
|
||||
icon: "bx bx-hash",
|
||||
type: "checkbox",
|
||||
bindToLabel: "calendar:weekNumbers"
|
||||
}
|
||||
@ -121,6 +126,7 @@ export const bookPropertiesConfig: Record<ViewTypeOptions, BookConfig> = {
|
||||
properties: [
|
||||
{
|
||||
label: t("book_properties_config.map-style"),
|
||||
icon: "bx bx-palette",
|
||||
type: "combobox",
|
||||
bindToLabel: "map:style",
|
||||
defaultValue: DEFAULT_MAP_LAYER_NAME,
|
||||
@ -147,6 +153,7 @@ export const bookPropertiesConfig: Record<ViewTypeOptions, BookConfig> = {
|
||||
},
|
||||
{
|
||||
label: t("book_properties_config.show-scale"),
|
||||
icon: "bx bx-ruler",
|
||||
type: "checkbox",
|
||||
bindToLabel: "map:scale"
|
||||
}
|
||||
@ -156,6 +163,7 @@ export const bookPropertiesConfig: Record<ViewTypeOptions, BookConfig> = {
|
||||
properties: [
|
||||
{
|
||||
label: t("book_properties_config.max-nesting-depth"),
|
||||
icon: "bx bx-subdirectory-right",
|
||||
type: "number",
|
||||
bindToLabel: "maxNestingDepth",
|
||||
width: 65,
|
||||
@ -171,6 +179,7 @@ export const bookPropertiesConfig: Record<ViewTypeOptions, BookConfig> = {
|
||||
{
|
||||
label: "Theme",
|
||||
type: "combobox",
|
||||
icon: "bx bx-palette",
|
||||
bindToLabel: "presentation:theme",
|
||||
defaultValue: DEFAULT_THEME,
|
||||
options: getPresentationThemes().map(theme => ({
|
||||
|
||||
@ -5,6 +5,7 @@ type Labels = {
|
||||
color: string;
|
||||
iconClass: string;
|
||||
workspaceIconClass: string;
|
||||
executeButton: boolean;
|
||||
executeDescription: string;
|
||||
executeTitle: string;
|
||||
limit: string; // should be probably be number
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user