diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts index e58958f3c..67e4025b0 100644 --- a/apps/client/src/services/utils.ts +++ b/apps/client/src/services/utils.ts @@ -808,6 +808,14 @@ export function numberObjectsInPlace(items: T[]): Indexed[] return items as Indexed[]; } +export function mapToKeyValueArray(map: Record) { + const values: { key: K, value: V }[] = []; + for (const [ key, value ] of Object.entries(map)) { + values.push({ key: key as K, value: value as V }); + } + return values; +} + export default { reloadFrontendApp, restartDesktopApp, diff --git a/apps/client/src/widgets/ribbon/CollectionPropertiesTab.tsx b/apps/client/src/widgets/ribbon/CollectionPropertiesTab.tsx new file mode 100644 index 000000000..027dafd30 --- /dev/null +++ b/apps/client/src/widgets/ribbon/CollectionPropertiesTab.tsx @@ -0,0 +1,45 @@ +import { useMemo } from "preact/hooks"; +import { t } from "../../services/i18n"; +import { ViewTypeOptions } from "../../services/note_list_renderer"; +import FormSelect from "../react/FormSelect"; +import { TabContext } from "./ribbon-interface"; +import { mapToKeyValueArray } from "../../services/utils"; +import { useNoteLabel } from "../react/hooks"; +import FNote from "../../entities/fnote"; +import FormGroup from "../react/FormGroup"; + +const VIEW_TYPE_MAPPINGS: Record = { + 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") +}; + +export default function CollectionPropertiesTab({ note }: TabContext) { + return (note && +
+ + +
+
+
+ ); +} + +function CollectionTypeSwitcher({ note }: { note: FNote }) { + const collectionTypes = useMemo(() => mapToKeyValueArray(VIEW_TYPE_MAPPINGS), []); + const [ viewType, setViewType ] = useNoteLabel(note, "viewType"); + + return ( +
+ {t("book_properties.view_type")}:    + +
+ ) +} \ No newline at end of file diff --git a/apps/client/src/widgets/ribbon/Ribbon.tsx b/apps/client/src/widgets/ribbon/Ribbon.tsx index 52887938a..6473ab278 100644 --- a/apps/client/src/widgets/ribbon/Ribbon.tsx +++ b/apps/client/src/widgets/ribbon/Ribbon.tsx @@ -21,6 +21,7 @@ import NotePathsTab from "./NotePathsTab"; import NoteMapTab from "./NoteMapTab"; import OwnedAttributesTab from "./OwnedAttributesTab"; import InheritedAttributesTab from "./InheritedAttributesTab"; +import CollectionPropertiesTab from "./CollectionPropertiesTab"; interface TitleContext { note: FNote | null | undefined; @@ -71,9 +72,11 @@ const TAB_CONFIGURATION = numberObjectsInPlace([ activate: ({ note }) => (note?.getPromotedDefinitionAttributes().length === 0 || !options.is("promotedAttributesOpenInRibbon")) && options.is("editedNotesOpenInRibbon") }, { - // BookPropertiesWidget title: t("book_properties.book_properties"), - icon: "bx bx-book" + icon: "bx bx-book", + content: CollectionPropertiesTab, + show: ({ note }) => note?.type === "book", + toggleCommand: "toggleRibbonTabBookProperties" }, { title: t("note_properties.info"), @@ -157,7 +160,7 @@ export default function Ribbon() { const filteredTabs = useMemo(() => TAB_CONFIGURATION.filter(tab => typeof tab.show === "boolean" ? tab.show : tab.show?.(titleContext)), [ titleContext, note ]); return ( -
+
{filteredTabs.map(({ title, icon, index }) => ( diff --git a/apps/client/src/widgets/ribbon/style.css b/apps/client/src/widgets/ribbon/style.css index cc9bc5380..ef568a514 100644 --- a/apps/client/src/widgets/ribbon/style.css +++ b/apps/client/src/widgets/ribbon/style.css @@ -350,4 +350,41 @@ overflow: auto; padding: 14px 12px 13px 12px; } +/* #endregion */ + +/* #region Book properties */ +.book-properties-widget { + padding: 12px 12px 6px 12px; + display: flex; +} + +.book-properties-widget > * { + margin-right: 15px; +} + +.book-properties-container { + display: flex; + align-items: center; +} + +.book-properties-container > div { + margin-right: 15px; +} + +.book-properties-container > .type-number > label { + display: flex; + align-items: baseline; +} + +.book-properties-container input[type="checkbox"] { + margin-right: 5px; +} + +.book-properties-container label { + display: flex; + justify-content: center; + align-items: center; + text-overflow: clip; + white-space: nowrap; +} /* #endregion */ \ No newline at end of file diff --git a/apps/client/src/widgets/ribbon_widgets/book_properties.ts b/apps/client/src/widgets/ribbon_widgets/book_properties.ts index 04fb61c02..31ca63a2d 100644 --- a/apps/client/src/widgets/ribbon_widgets/book_properties.ts +++ b/apps/client/src/widgets/ribbon_widgets/book_properties.ts @@ -5,72 +5,6 @@ import type FNote from "../../entities/fnote.js"; import type { EventData } from "../../components/app_context.js"; import { bookPropertiesConfig, BookProperty } from "./book_properties_config.js"; import attributes from "../../services/attributes.js"; -import type { ViewTypeOptions } from "../../services/note_list_renderer.js"; - -const VIEW_TYPE_MAPPINGS: Record = { - 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") -}; - -const TPL = /*html*/` -
- - -
- ${t("book_properties.view_type")}:    - - -
- -
-
-
-`; export default class BookPropertiesWidget extends NoteContextAwareWidget { @@ -78,28 +12,7 @@ export default class BookPropertiesWidget extends NoteContextAwareWidget { private $propertiesContainer!: JQuery; private labelsToWatch: string[] = []; - get name() { - return "bookProperties"; - } - - get toggleCommand() { - return "toggleRibbonTabBookProperties"; - } - - isEnabled() { - return this.note && this.note.type === "book"; - } - - getTitle() { - return { - show: this.isEnabled(), - - }; - } - doRender() { - this.$widget = $(TPL); - this.contentSized(); this.$viewTypeSelect = this.$widget.find(".view-type-select"); this.$viewTypeSelect.on("change", () => this.toggleViewType(String(this.$viewTypeSelect.val())));