mirror of
https://github.com/zadam/trilium.git
synced 2025-10-20 15:19:01 +02:00
refactor(react): add type safety for note labels
This commit is contained in:
parent
8a66ee7565
commit
b8e4947adb
@ -2,7 +2,7 @@ import { ComponentChildren } from "preact";
|
|||||||
import { Dispatch, StateUpdater, useEffect, useState } from "preact/hooks";
|
import { Dispatch, StateUpdater, useEffect, useState } from "preact/hooks";
|
||||||
import FNote from "../../entities/fnote";
|
import FNote from "../../entities/fnote";
|
||||||
import froca from "../../services/froca";
|
import froca from "../../services/froca";
|
||||||
import { useNoteLabel } from "../react/hooks";
|
import { useNoteLabelInt } from "../react/hooks";
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
|
|
||||||
interface PaginationContext {
|
interface PaginationContext {
|
||||||
@ -62,9 +62,8 @@ export function usePagination(note: FNote, noteIds: string[]): PaginationContext
|
|||||||
const [ pageNotes, setPageNotes ] = useState<FNote[]>();
|
const [ pageNotes, setPageNotes ] = useState<FNote[]>();
|
||||||
|
|
||||||
// Parse page size.
|
// Parse page size.
|
||||||
const [ pageSize ] = useNoteLabel(note, "pageSize");
|
const [ pageSize ] = useNoteLabelInt(note, "pageSize");
|
||||||
const pageSizeNum = parseInt(pageSize ?? "", 10);
|
const normalizedPageSize = (pageSize && pageSize > 0 ? pageSize : 20);
|
||||||
const normalizedPageSize = (pageSizeNum && pageSizeNum > 0 ? pageSizeNum : 20);
|
|
||||||
|
|
||||||
// Calculate start/end index.
|
// Calculate start/end index.
|
||||||
const startIdx = (page - 1) * normalizedPageSize;
|
const startIdx = (page - 1) * normalizedPageSize;
|
||||||
|
@ -129,7 +129,7 @@ function NoteIconList({ note }: { note: FNote }) {
|
|||||||
class="icon-list"
|
class="icon-list"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
const clickedTarget = e.target as HTMLElement;
|
const clickedTarget = e.target as HTMLElement;
|
||||||
|
|
||||||
if (!clickedTarget.classList.contains("bx")) {
|
if (!clickedTarget.classList.contains("bx")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,9 +152,9 @@ function NoteIconList({ note }: { note: FNote }) {
|
|||||||
for (const label of getIconLabels(note)) {
|
for (const label of getIconLabels(note)) {
|
||||||
attributes.removeAttributeById(note.noteId, label.attributeId);
|
attributes.removeAttributeById(note.noteId, label.attributeId);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(iconData?.icons ?? []).map(({className, name}) => (
|
{(iconData?.icons ?? []).map(({className, name}) => (
|
||||||
@ -181,4 +181,4 @@ function getIconLabels(note: FNote) {
|
|||||||
return note.getOwnedLabels()
|
return note.getOwnedLabels()
|
||||||
.filter((label) => ["workspaceIconClass", "iconClass"]
|
.filter((label) => ["workspaceIconClass", "iconClass"]
|
||||||
.includes(label.name));
|
.includes(label.name));
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { Inputs, MutableRef, useCallback, useContext, useDebugValue, useEffect,
|
|||||||
import { CommandListenerData, EventData, EventNames } from "../../components/app_context";
|
import { CommandListenerData, EventData, EventNames } from "../../components/app_context";
|
||||||
import { ParentComponent } from "./react_utils";
|
import { ParentComponent } from "./react_utils";
|
||||||
import SpacedUpdate from "../../services/spaced_update";
|
import SpacedUpdate from "../../services/spaced_update";
|
||||||
import { KeyboardActionNames, OptionNames } from "@triliumnext/commons";
|
import { FilterLabelsByType, KeyboardActionNames, OptionNames } from "@triliumnext/commons";
|
||||||
import options, { type OptionValue } from "../../services/options";
|
import options, { type OptionValue } from "../../services/options";
|
||||||
import utils, { escapeRegExp, reloadFrontendApp } from "../../services/utils";
|
import utils, { escapeRegExp, reloadFrontendApp } from "../../services/utils";
|
||||||
import NoteContext from "../../components/note_context";
|
import NoteContext from "../../components/note_context";
|
||||||
@ -13,7 +13,7 @@ import FBlob from "../../entities/fblob";
|
|||||||
import NoteContextAwareWidget from "../note_context_aware_widget";
|
import NoteContextAwareWidget from "../note_context_aware_widget";
|
||||||
import { RefObject, VNode } from "preact";
|
import { RefObject, VNode } from "preact";
|
||||||
import { Tooltip } from "bootstrap";
|
import { Tooltip } from "bootstrap";
|
||||||
import { CSSProperties, DragEventHandler } from "preact/compat";
|
import { CSSProperties } from "preact/compat";
|
||||||
import keyboard_actions from "../../services/keyboard_actions";
|
import keyboard_actions from "../../services/keyboard_actions";
|
||||||
import Mark from "mark.js";
|
import Mark from "mark.js";
|
||||||
import { DragData } from "../note_tree";
|
import { DragData } from "../note_tree";
|
||||||
@ -291,7 +291,7 @@ export function useNoteRelation(note: FNote | undefined | null, relationName: st
|
|||||||
* @param labelName the name of the label to read/write.
|
* @param labelName the name of the label to read/write.
|
||||||
* @returns an array where the first element is the getter and the second element is the setter. The setter has a special behaviour for convenience: if the value is undefined, the label is created without a value (e.g. a tag), if the value is null then the label is removed.
|
* @returns an array where the first element is the getter and the second element is the setter. The setter has a special behaviour for convenience: if the value is undefined, the label is created without a value (e.g. a tag), if the value is null then the label is removed.
|
||||||
*/
|
*/
|
||||||
export function useNoteLabel(note: FNote | undefined | null, labelName: string): [string | null | undefined, (newValue: string | null | undefined) => void] {
|
export function useNoteLabel(note: FNote | undefined | null, labelName: FilterLabelsByType<string>): [string | null | undefined, (newValue: string | null | undefined) => void] {
|
||||||
const [ , setLabelValue ] = useState<string | null | undefined>();
|
const [ , setLabelValue ] = useState<string | null | undefined>();
|
||||||
|
|
||||||
useEffect(() => setLabelValue(note?.getLabelValue(labelName) ?? null), [ note ]);
|
useEffect(() => setLabelValue(note?.getLabelValue(labelName) ?? null), [ note ]);
|
||||||
@ -325,12 +325,12 @@ export function useNoteLabel(note: FNote | undefined | null, labelName: string):
|
|||||||
] as const;
|
] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useNoteLabelWithDefault(note: FNote | undefined | null, labelName: string, defaultValue: string): [string, (newValue: string | null | undefined) => void] {
|
export function useNoteLabelWithDefault(note: FNote | undefined | null, labelName: FilterLabelsByType<string>, defaultValue: string): [string, (newValue: string | null | undefined) => void] {
|
||||||
const [ labelValue, setLabelValue ] = useNoteLabel(note, labelName);
|
const [ labelValue, setLabelValue ] = useNoteLabel(note, labelName);
|
||||||
return [ labelValue ?? defaultValue, setLabelValue];
|
return [ labelValue ?? defaultValue, setLabelValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: string): [ boolean, (newValue: boolean) => void] {
|
export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: FilterLabelsByType<boolean>): [ boolean, (newValue: boolean) => void] {
|
||||||
const [ labelValue, setLabelValue ] = useState<boolean>(!!note?.hasLabel(labelName));
|
const [ labelValue, setLabelValue ] = useState<boolean>(!!note?.hasLabel(labelName));
|
||||||
|
|
||||||
useEffect(() => setLabelValue(!!note?.hasLabel(labelName)), [ note ]);
|
useEffect(() => setLabelValue(!!note?.hasLabel(labelName)), [ note ]);
|
||||||
@ -358,7 +358,8 @@ export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: s
|
|||||||
return [ labelValue, setter ] as const;
|
return [ labelValue, setter ] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useNoteLabelInt(note: FNote | undefined | null, labelName: string): [ number | undefined, (newValue: number) => void] {
|
export function useNoteLabelInt(note: FNote | undefined | null, labelName: FilterLabelsByType<number>): [ number | undefined, (newValue: number) => void] {
|
||||||
|
//@ts-expect-error `useNoteLabel` only accepts string properties but we need to be able to read number ones.
|
||||||
const [ value, setValue ] = useNoteLabel(note, labelName);
|
const [ value, setValue ] = useNoteLabel(note, labelName);
|
||||||
useDebugValue(labelName);
|
useDebugValue(labelName);
|
||||||
return [
|
return [
|
||||||
|
@ -23,7 +23,7 @@ import { ContentLanguagesList } from "../type_widgets/options/i18n";
|
|||||||
|
|
||||||
export default function BasicPropertiesTab({ note }: TabContext) {
|
export default function BasicPropertiesTab({ note }: TabContext) {
|
||||||
return (
|
return (
|
||||||
<div className="basic-properties-widget">
|
<div className="basic-properties-widget">
|
||||||
<NoteTypeWidget note={note} />
|
<NoteTypeWidget note={note} />
|
||||||
<ProtectedNoteSwitch note={note} />
|
<ProtectedNoteSwitch note={note} />
|
||||||
<EditabilitySelect note={note} />
|
<EditabilitySelect note={note} />
|
||||||
@ -43,7 +43,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
|||||||
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled)
|
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled)
|
||||||
}, [ codeNotesMimeTypes ]);
|
}, [ codeNotesMimeTypes ]);
|
||||||
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
||||||
|
|
||||||
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
||||||
const currentNoteMime = useNoteProperty(note, "mime");
|
const currentNoteMime = useNoteProperty(note, "mime");
|
||||||
const [ modalShown, setModalShown ] = useState(false);
|
const [ modalShown, setModalShown ] = useState(false);
|
||||||
@ -95,7 +95,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
|||||||
checked={checked}
|
checked={checked}
|
||||||
badges={badges}
|
badges={badges}
|
||||||
onClick={() => changeNoteType(type, mime)}
|
onClick={() => changeNoteType(type, mime)}
|
||||||
>{title}</FormListItem>
|
>{title}</FormListItem>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
@ -103,7 +103,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
|||||||
<FormDropdownDivider />
|
<FormDropdownDivider />
|
||||||
<FormListItem
|
<FormListItem
|
||||||
checked={checked}
|
checked={checked}
|
||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<strong>{title}</strong>
|
<strong>{title}</strong>
|
||||||
</FormListItem>
|
</FormListItem>
|
||||||
@ -131,7 +131,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
|||||||
<CodeMimeTypesList />
|
<CodeMimeTypesList />
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProtectedNoteSwitch({ note }: { note?: FNote | null }) {
|
function ProtectedNoteSwitch({ note }: { note?: FNote | null }) {
|
||||||
@ -151,7 +151,7 @@ function ProtectedNoteSwitch({ note }: { note?: FNote | null }) {
|
|||||||
|
|
||||||
function EditabilitySelect({ note }: { note?: FNote | null }) {
|
function EditabilitySelect({ note }: { note?: FNote | null }) {
|
||||||
const [ readOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
const [ readOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||||
const [ autoReadOnlyDisabled, setAutoReadOnlyDisabled ] = useNoteLabelBoolean(note, "autoReadOnlyDisabled");
|
const [ autoReadOnlyDisabled, setAutoReadOnlyDisabled ] = useNoteLabelBoolean(note, "autoReadOnlyDisabled");
|
||||||
|
|
||||||
const options = useMemo(() => ([
|
const options = useMemo(() => ([
|
||||||
{
|
{
|
||||||
@ -208,7 +208,7 @@ function BookmarkSwitch({ note }: { note?: FNote | null }) {
|
|||||||
<FormToggle
|
<FormToggle
|
||||||
switchOnName={t("bookmark_switch.bookmark")} switchOnTooltip={t("bookmark_switch.bookmark_this_note")}
|
switchOnName={t("bookmark_switch.bookmark")} switchOnTooltip={t("bookmark_switch.bookmark_this_note")}
|
||||||
switchOffName={t("bookmark_switch.bookmark")} switchOffTooltip={t("bookmark_switch.remove_bookmark")}
|
switchOffName={t("bookmark_switch.bookmark")} switchOffTooltip={t("bookmark_switch.remove_bookmark")}
|
||||||
currentValue={isBookmarked}
|
currentValue={isBookmarked}
|
||||||
onChange={async (shouldBookmark) => {
|
onChange={async (shouldBookmark) => {
|
||||||
if (!note) return;
|
if (!note) return;
|
||||||
const resp = await server.put<ToggleInParentResponse>(`notes/${note.noteId}/toggle-in-parent/_lbBookmarks/${shouldBookmark}`);
|
const resp = await server.put<ToggleInParentResponse>(`notes/${note.noteId}/toggle-in-parent/_lbBookmarks/${shouldBookmark}`);
|
||||||
@ -260,11 +260,11 @@ function SharedSwitch({ note }: { note?: FNote | null }) {
|
|||||||
} else {
|
} else {
|
||||||
if (note?.getParentBranches().length === 1 && !(await dialog.confirm(t("shared_switch.shared-branch")))) {
|
if (note?.getParentBranches().length === 1 && !(await dialog.confirm(t("shared_switch.shared-branch")))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shareBranch = note?.getParentBranches().find((b) => b.parentNoteId === "_share");
|
const shareBranch = note?.getParentBranches().find((b) => b.parentNoteId === "_share");
|
||||||
if (!shareBranch?.branchId) return;
|
if (!shareBranch?.branchId) return;
|
||||||
await server.remove(`branches/${shareBranch.branchId}?taskId=no-progress-reporting`);
|
await server.remove(`branches/${shareBranch.branchId}?taskId=no-progress-reporting`);
|
||||||
}
|
}
|
||||||
|
|
||||||
sync.syncNow(true);
|
sync.syncNow(true);
|
||||||
@ -330,7 +330,7 @@ function NoteLanguageSwitch({ note }: { note?: FNote | null }) {
|
|||||||
return locales.find(locale => typeof locale === "object" && locale.id === currentNoteLanguage) as Locale | undefined;
|
return locales.find(locale => typeof locale === "object" && locale.id === currentNoteLanguage) as Locale | undefined;
|
||||||
}, [ currentNoteLanguage ]);
|
}, [ currentNoteLanguage ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="note-language-container">
|
<div className="note-language-container">
|
||||||
<span>{t("basic_properties.language")}:</span>
|
<span>{t("basic_properties.language")}:</span>
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ function NoteLanguageSwitch({ note }: { note?: FNote | null }) {
|
|||||||
|
|
||||||
<FormListItem
|
<FormListItem
|
||||||
onClick={() => setModalShown(true)}
|
onClick={() => setModalShown(true)}
|
||||||
>{t("note_language.configure-languages")}</FormListItem>
|
>{t("note_language.configure-languages")}</FormListItem>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
||||||
<HelpButton helpPage="B0lcI9xz1r8K" style={{ marginLeft: "4px" }} />
|
<HelpButton helpPage="B0lcI9xz1r8K" style={{ marginLeft: "4px" }} />
|
||||||
@ -378,4 +378,4 @@ function findTypeTitle(type?: NoteType, mime?: string | null) {
|
|||||||
|
|
||||||
return noteType ? noteType.title : type;
|
return noteType ? noteType.title : type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ function CheckboxPropertyView({ note, property }: { note: FNote, property: Check
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NumberPropertyView({ note, property }: { note: FNote, property: NumberProperty }) {
|
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 [ value, setValue ] = useNoteLabel(note, property.bindToLabel);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -17,4 +17,4 @@ export default function NotePropertiesTab({ note }: TabContext) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,4 @@ export default function ScriptTab({ note }: TabContext) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ export const SEARCH_OPTIONS: SearchOption[] = [
|
|||||||
defaultValue: "root",
|
defaultValue: "root",
|
||||||
icon: "bx bx-filter-alt",
|
icon: "bx bx-filter-alt",
|
||||||
label: t("search_definition.ancestor"),
|
label: t("search_definition.ancestor"),
|
||||||
component: AncestorOption,
|
component: AncestorOption,
|
||||||
additionalAttributesToDelete: [ { type: "label", name: "ancestorDepth" } ]
|
additionalAttributesToDelete: [ { type: "label", name: "ancestorDepth" } ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -173,7 +173,7 @@ function SearchStringOption({ note, refreshResults, error, ...restProps }: Searc
|
|||||||
}
|
}
|
||||||
}, [ error ]);
|
}, [ error ]);
|
||||||
|
|
||||||
return <SearchOption
|
return <SearchOption
|
||||||
title={t("search_string.title_column")}
|
title={t("search_string.title_column")}
|
||||||
help={<>
|
help={<>
|
||||||
<strong>{t("search_string.search_syntax")}</strong> - {t("search_string.also_see")} <a href="#" data-help-page="search.html">{t("search_string.complete_help")}</a>
|
<strong>{t("search_string.search_syntax")}</strong> - {t("search_string.also_see")} <a href="#" data-help-page="search.html">{t("search_string.complete_help")}</a>
|
||||||
@ -243,7 +243,7 @@ function AncestorOption({ note, ...restProps}: SearchOptionProps) {
|
|||||||
const options: { value: string | undefined; label: string }[] = [
|
const options: { value: string | undefined; label: string }[] = [
|
||||||
{ value: "", label: t("ancestor.depth_doesnt_matter") },
|
{ value: "", label: t("ancestor.depth_doesnt_matter") },
|
||||||
{ value: "eq1", label: `${t("ancestor.depth_eq", { count: 1 })} (${t("ancestor.direct_children")})` }
|
{ value: "eq1", label: `${t("ancestor.depth_eq", { count: 1 })} (${t("ancestor.direct_children")})` }
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i=2; i<=9; i++) options.push({ value: "eq" + i, label: t("ancestor.depth_eq", { count: i }) });
|
for (let i=2; i<=9; i++) options.push({ value: "eq" + i, label: t("ancestor.depth_eq", { count: i }) });
|
||||||
for (let i=0; i<=9; i++) options.push({ value: "gt" + i, label: t("ancestor.depth_gt", { count: i }) });
|
for (let i=0; i<=9; i++) options.push({ value: "gt" + i, label: t("ancestor.depth_gt", { count: i }) });
|
||||||
@ -253,7 +253,7 @@ function AncestorOption({ note, ...restProps}: SearchOptionProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <SearchOption
|
return <SearchOption
|
||||||
title={t("ancestor.label")}
|
title={t("ancestor.label")}
|
||||||
note={note} {...restProps}
|
note={note} {...restProps}
|
||||||
>
|
>
|
||||||
<div style={{display: "flex", alignItems: "center"}}>
|
<div style={{display: "flex", alignItems: "center"}}>
|
||||||
@ -357,4 +357,4 @@ function LimitOption({ note, defaultValue, ...restProps }: SearchOptionProps) {
|
|||||||
currentValue={limit ?? defaultValue} onChange={setLimit}
|
currentValue={limit ?? defaultValue} onChange={setLimit}
|
||||||
/>
|
/>
|
||||||
</SearchOption>
|
</SearchOption>
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import attributes from "../../services/attributes";
|
|||||||
import NoteContextAwareWidget from "../note_context_aware_widget";
|
import NoteContextAwareWidget from "../note_context_aware_widget";
|
||||||
import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, type MapLayer } from "../collections/geomap/map_layer";
|
import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, type MapLayer } from "../collections/geomap/map_layer";
|
||||||
import { ViewTypeOptions } from "../collections/interface";
|
import { ViewTypeOptions } from "../collections/interface";
|
||||||
|
import { FilterLabelsByType } from "@triliumnext/commons";
|
||||||
|
|
||||||
interface BookConfig {
|
interface BookConfig {
|
||||||
properties: BookProperty[];
|
properties: BookProperty[];
|
||||||
@ -12,7 +13,7 @@ interface BookConfig {
|
|||||||
export interface CheckBoxProperty {
|
export interface CheckBoxProperty {
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
label: string;
|
label: string;
|
||||||
bindToLabel: string
|
bindToLabel: FilterLabelsByType<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonProperty {
|
export interface ButtonProperty {
|
||||||
@ -26,7 +27,7 @@ export interface ButtonProperty {
|
|||||||
export interface NumberProperty {
|
export interface NumberProperty {
|
||||||
type: "number",
|
type: "number",
|
||||||
label: string;
|
label: string;
|
||||||
bindToLabel: string;
|
bindToLabel: FilterLabelsByType<number>;
|
||||||
width?: number;
|
width?: number;
|
||||||
min?: number;
|
min?: number;
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ interface ComboBoxGroup {
|
|||||||
export interface ComboBoxProperty {
|
export interface ComboBoxProperty {
|
||||||
type: "combobox",
|
type: "combobox",
|
||||||
label: string;
|
label: string;
|
||||||
bindToLabel: string;
|
bindToLabel: FilterLabelsByType<string>;
|
||||||
/**
|
/**
|
||||||
* The default value is used when the label is not set.
|
* The default value is used when the label is not set.
|
||||||
*/
|
*/
|
||||||
|
@ -9,3 +9,4 @@ export * from "./lib/bulk_actions.js";
|
|||||||
export * from "./lib/server_api.js";
|
export * from "./lib/server_api.js";
|
||||||
export * from "./lib/shared_constants.js";
|
export * from "./lib/shared_constants.js";
|
||||||
export * from "./lib/ws_api.js";
|
export * from "./lib/ws_api.js";
|
||||||
|
export * from "./lib/attribute_names.js";
|
||||||
|
45
packages/commons/src/lib/attribute_names.ts
Normal file
45
packages/commons/src/lib/attribute_names.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
type Labels = {
|
||||||
|
color: string;
|
||||||
|
iconClass: string;
|
||||||
|
workspaceIconClass: string;
|
||||||
|
executeDescription: string;
|
||||||
|
executeTitle: string;
|
||||||
|
limit: string; // should be probably be number
|
||||||
|
calendarRoot: boolean;
|
||||||
|
workspaceCalendarRoot: boolean;
|
||||||
|
archived: boolean;
|
||||||
|
sorted: boolean;
|
||||||
|
template: boolean;
|
||||||
|
autoReadOnlyDisabled: boolean;
|
||||||
|
language: string;
|
||||||
|
originalFileName: string;
|
||||||
|
pageUrl: string;
|
||||||
|
|
||||||
|
// Search
|
||||||
|
searchString: string;
|
||||||
|
ancestorDepth: string;
|
||||||
|
orderBy: string;
|
||||||
|
orderDirection: string;
|
||||||
|
|
||||||
|
// Collection-specific
|
||||||
|
viewType: string;
|
||||||
|
status: string;
|
||||||
|
pageSize: number;
|
||||||
|
geolocation: string;
|
||||||
|
readOnly: boolean;
|
||||||
|
expanded: boolean;
|
||||||
|
"calendar:hideWeekends": boolean;
|
||||||
|
"calendar:weekNumbers": boolean;
|
||||||
|
"calendar:view": string;
|
||||||
|
"map:style": string;
|
||||||
|
"map:scale": boolean;
|
||||||
|
"board:groupBy": string;
|
||||||
|
maxNestingDepth: number;
|
||||||
|
includeArchived: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LabelNames = keyof Labels;
|
||||||
|
|
||||||
|
export type FilterLabelsByType<U> = {
|
||||||
|
[K in keyof Labels]: Labels[K] extends U ? K : never;
|
||||||
|
}[keyof Labels];
|
Loading…
x
Reference in New Issue
Block a user