mirror of
https://github.com/decaf-dev/obsidian-vault-explorer.git
synced 2026-07-22 10:10:31 +00:00
Match when property doesn't exist (#50)
* feat: add matchNotesWithoutProperty setting * feat: add match without property checkbox * feat: add business logic for handling property DNE checkbox * refactor: rename to property type
This commit is contained in:
parent
29c4af256b
commit
06d8aa63c5
12 changed files with 282 additions and 59 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "vault-explorer",
|
||||
"name": "Vault Explorer",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.0",
|
||||
"minAppVersion": "1.4.13",
|
||||
"description": "Explore your vault in visual format",
|
||||
"author": "DecafDev",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "obsidian-vault-explorer",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.0",
|
||||
"description": "Explore your vault in visual format",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
37
src/main.ts
37
src/main.ts
|
|
@ -3,7 +3,7 @@ import { Plugin, TAbstractFile, TFile, TFolder } from 'obsidian';
|
|||
import VaultExplorerView from './obsidian/vault-explorer-view';
|
||||
import VaultExplorerSettingsTab from './obsidian/vault-explorer-settings-tab';
|
||||
|
||||
import { VaultExplorerPluginSettings, ViewType } from './types';
|
||||
import { PropertyFilter, PropertyFilterGroup, PropertyType, VaultExplorerPluginSettings, ViewType } from './types';
|
||||
import { DEFAULT_SETTINGS, VAULT_EXPLORER_VIEW } from './constants';
|
||||
import _ from 'lodash';
|
||||
import EventManager from './event/event-manager';
|
||||
|
|
@ -16,6 +16,7 @@ import { LOG_LEVEL_WARN } from './logger/constants';
|
|||
import { VaultExplorerPluginSettings_1_0_1 } from './types/types-1.0.1';
|
||||
import { moveFocus } from './focus-utils';
|
||||
import { VaultExplorerPluginSettings_1_2_0 } from './types/types-1.2.0';
|
||||
import { VaultExplorerPluginSettings_1_2_1 } from './types/types-1.2.1';
|
||||
|
||||
export default class VaultExplorerPlugin extends Plugin {
|
||||
settings: VaultExplorerPluginSettings = DEFAULT_SETTINGS;
|
||||
|
|
@ -189,7 +190,7 @@ export default class VaultExplorerPlugin extends Plugin {
|
|||
if (isVersionLessThan(settingsVersion, "1.2.1")) {
|
||||
console.log("Upgrading settings from version 1.2.0 to 1.2.1");
|
||||
const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_0;
|
||||
const newData: VaultExplorerPluginSettings = {
|
||||
const newData: VaultExplorerPluginSettings_1_2_1 = {
|
||||
...typedData,
|
||||
views: {
|
||||
...typedData.views,
|
||||
|
|
@ -198,6 +199,38 @@ export default class VaultExplorerPlugin extends Plugin {
|
|||
}
|
||||
data = newData as unknown as Record<string, unknown>;
|
||||
}
|
||||
|
||||
if (isVersionLessThan(settingsVersion, "1.3.0")) {
|
||||
console.log("Upgrading settings from version 1.2.1 to 1.3.0");
|
||||
const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_1;
|
||||
const groups = typedData.filters.properties.groups;
|
||||
|
||||
const updatedGroups: PropertyFilterGroup[] = groups.map(group => {
|
||||
const updatedFilters: PropertyFilter[] = group.filters.map(filter => {
|
||||
return {
|
||||
...filter,
|
||||
type: filter.type as any,
|
||||
matchWhenPropertyDNE: false
|
||||
}
|
||||
});
|
||||
return {
|
||||
...group,
|
||||
filters: updatedFilters
|
||||
}
|
||||
});
|
||||
|
||||
const newData: VaultExplorerPluginSettings = {
|
||||
...typedData,
|
||||
filters: {
|
||||
...typedData.filters,
|
||||
properties: {
|
||||
...typedData.filters.properties,
|
||||
groups: updatedGroups,
|
||||
}
|
||||
}
|
||||
}
|
||||
data = newData as unknown as Record<string, unknown>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
return group.filters.every((filter) => {
|
||||
if (!filter.isEnabled) return true;
|
||||
|
||||
const { propertyName, condition, value, type } = filter;
|
||||
const { propertyName, condition, value, type, matchWhenPropertyDNE } = filter;
|
||||
if (propertyName === "") return true;
|
||||
|
||||
let propertyValue: (string | string[] | boolean | number | null) = frontmatter?.[propertyName] ?? null;
|
||||
|
|
@ -34,7 +34,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
Logger.warn(`Property value is not a string: ${propertyValue}`);
|
||||
return true;
|
||||
}
|
||||
const doesMatch = doesTextMatchFilter(condition, propertyValue, value);
|
||||
const doesMatch = doesTextMatchFilter(condition, propertyValue, value, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "list") {
|
||||
if (propertyValue !== null && !Array.isArray(propertyValue)) {
|
||||
|
|
@ -42,7 +42,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
return true;
|
||||
}
|
||||
const compare = value.split(",").map((v) => v.trim());
|
||||
const doesMatch = doesListMatchFilter(condition, propertyValue, compare);
|
||||
const doesMatch = doesListMatchFilter(condition, propertyValue, compare, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "number") {
|
||||
if (propertyValue !== null && typeof propertyValue !== "number") {
|
||||
|
|
@ -50,7 +50,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
return true;
|
||||
}
|
||||
const compare = parseFloat(value);
|
||||
const doesMatch = doesNumberMatchFilter(condition, propertyValue, compare);
|
||||
const doesMatch = doesNumberMatchFilter(condition, propertyValue, compare, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
} else if (type === "checkbox") {
|
||||
if (propertyValue !== null && typeof propertyValue !== "boolean") {
|
||||
|
|
@ -59,7 +59,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
}
|
||||
|
||||
const compare = value === "true";
|
||||
const doesMatch = doesCheckboxMatchFilter(condition, propertyValue, compare);
|
||||
const doesMatch = doesCheckboxMatchFilter(condition, propertyValue, compare, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
|
||||
} else if (type === "date" || type === "datetime") {
|
||||
|
|
@ -68,7 +68,7 @@ export const filterByProperty = (frontmatter: FrontMatterCache | undefined, grou
|
|||
return true;
|
||||
}
|
||||
|
||||
const doesMatch = doesDateMatchFilter(condition, propertyValue, value);
|
||||
const doesMatch = doesDateMatchFilter(condition, propertyValue, value, matchWhenPropertyDNE);
|
||||
return doesMatch;
|
||||
|
||||
} else {
|
||||
|
|
@ -82,6 +82,7 @@ const doesTextMatchFilter = (
|
|||
condition: FilterCondition,
|
||||
propertyValue: string | null,
|
||||
compare: string,
|
||||
matchIfNull: boolean
|
||||
): boolean => {
|
||||
if (propertyValue)
|
||||
propertyValue = propertyValue.toLowerCase().trim();
|
||||
|
|
@ -90,22 +91,22 @@ const doesTextMatchFilter = (
|
|||
|
||||
switch (condition) {
|
||||
case TextFilterCondition.IS:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue === compare;
|
||||
case TextFilterCondition.IS_NOT:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue !== compare;
|
||||
case TextFilterCondition.CONTAINS:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue.includes(compare);
|
||||
case TextFilterCondition.DOES_NOT_CONTAIN:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return !propertyValue.includes(compare);
|
||||
case TextFilterCondition.STARTS_WITH:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue.startsWith(compare);
|
||||
case TextFilterCondition.ENDS_WITH:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue.endsWith(compare);
|
||||
case TextFilterCondition.EXISTS:
|
||||
return propertyValue !== null;
|
||||
|
|
@ -116,16 +117,16 @@ const doesTextMatchFilter = (
|
|||
}
|
||||
};
|
||||
|
||||
const doesListMatchFilter = (condition: ListFilterCondition, propertyValue: string[] | null, compare: string[]) => {
|
||||
const doesListMatchFilter = (condition: ListFilterCondition, propertyValue: string[] | null, compare: string[], matchIfNull: boolean) => {
|
||||
switch (condition) {
|
||||
case ListFilterCondition.CONTAINS:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
|
||||
return propertyValue.some((value) => //Union
|
||||
compare.some((c) => c === value)
|
||||
);
|
||||
case ListFilterCondition.DOES_NOT_CONTAIN:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
|
||||
return propertyValue.every((value) => //Complement
|
||||
compare.every((c) => c !== value)
|
||||
|
|
@ -141,11 +142,11 @@ const doesListMatchFilter = (condition: ListFilterCondition, propertyValue: stri
|
|||
|
||||
const doesDateMatchFilter = (condition: DateFilterCondition,
|
||||
propertyValue: string | null,
|
||||
compare: string | null) => {
|
||||
compare: string | null, matchIfNull: boolean) => {
|
||||
|
||||
switch (condition) {
|
||||
case DateFilterCondition.IS: {
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
if (compare === null) return false;
|
||||
|
||||
const propertyValueTime = getMillis(propertyValue);
|
||||
|
|
@ -158,7 +159,7 @@ const doesDateMatchFilter = (condition: DateFilterCondition,
|
|||
);
|
||||
}
|
||||
case DateFilterCondition.IS_AFTER: {
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
if (compare === null) return false;
|
||||
|
||||
const propertyValueTime = getMillis(propertyValue);
|
||||
|
|
@ -166,7 +167,7 @@ const doesDateMatchFilter = (condition: DateFilterCondition,
|
|||
return propertyValueTime > dayEndTime;
|
||||
}
|
||||
case DateFilterCondition.IS_BEFORE: {
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
if (compare === null) return false;
|
||||
|
||||
const propertyValueTime = getMillis(propertyValue);
|
||||
|
|
@ -186,25 +187,26 @@ export const doesNumberMatchFilter = (
|
|||
condition: NumberFilterCondition,
|
||||
propertyValue: number | null,
|
||||
compare: number,
|
||||
matchIfNull: boolean
|
||||
) => {
|
||||
switch (condition) {
|
||||
case NumberFilterCondition.IS_EQUAL:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue === compare;
|
||||
case NumberFilterCondition.IS_GREATER:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue > compare;
|
||||
case NumberFilterCondition.IS_GREATER_OR_EQUAL:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue >= compare;
|
||||
case NumberFilterCondition.IS_LESS:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue < compare;
|
||||
case NumberFilterCondition.IS_LESS_OR_EQUAL:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue <= compare;
|
||||
case NumberFilterCondition.IS_NOT_EQUAL:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue !== compare;
|
||||
case NumberFilterCondition.EXISTS:
|
||||
return propertyValue !== null;
|
||||
|
|
@ -219,13 +221,14 @@ export const doesCheckboxMatchFilter = (
|
|||
condition: CheckboxFilterCondition,
|
||||
propertyValue: boolean | null,
|
||||
compare: boolean,
|
||||
matchIfNull: boolean
|
||||
) => {
|
||||
switch (condition) {
|
||||
case CheckboxFilterCondition.IS:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue === compare;
|
||||
case CheckboxFilterCondition.IS_NOT:
|
||||
if (propertyValue === null) return false;
|
||||
if (propertyValue === null) return matchIfNull;
|
||||
return propertyValue !== compare;
|
||||
case CheckboxFilterCondition.EXISTS:
|
||||
return propertyValue !== null;
|
||||
|
|
|
|||
|
|
@ -39,10 +39,11 @@
|
|||
filters={selectedGroup.filters}
|
||||
on:filterConditionChange
|
||||
on:filterTypeChange
|
||||
on:filterNameChange
|
||||
on:filterPropertyNameChange
|
||||
on:filterValueChange
|
||||
on:filterToggle
|
||||
on:filterDeleteClick
|
||||
on:filterMatchWhenPropertyDNEChange
|
||||
/>
|
||||
<Spacer direction="vertical" size="sm" />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -12,16 +12,18 @@
|
|||
id={filter.id}
|
||||
value={filter.value}
|
||||
condition={filter.condition}
|
||||
matchWhenPropertyDNE={filter.matchWhenPropertyDNE}
|
||||
type={filter.type}
|
||||
name={filter.propertyName}
|
||||
propertyName={filter.propertyName}
|
||||
isEnabled={filter.isEnabled}
|
||||
on:groupChange
|
||||
on:filterConditionChange
|
||||
on:filterTypeChange
|
||||
on:filterNameChange
|
||||
on:filterPropertyNameChange
|
||||
on:filterValueChange
|
||||
on:filterToggle
|
||||
on:filterDeleteClick
|
||||
on:filterMatchWhenPropertyDNEChange
|
||||
/>
|
||||
{/each}
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -8,18 +8,19 @@
|
|||
FilterCondition,
|
||||
ListFilterCondition,
|
||||
NumberFilterCondition,
|
||||
PropertyFilterType,
|
||||
PropertyType,
|
||||
TextFilterCondition,
|
||||
} from "src/types";
|
||||
import { getDisplayNameForFilterCondition } from "./utils";
|
||||
import { getAllObsidianProperties } from "src/obsidian/utils";
|
||||
|
||||
export let id: string;
|
||||
export let name: string;
|
||||
export let type: PropertyFilterType;
|
||||
export let propertyName: string;
|
||||
export let type: PropertyType;
|
||||
export let value: string;
|
||||
export let condition: FilterCondition;
|
||||
export let isEnabled: boolean;
|
||||
export let matchWhenPropertyDNE: boolean;
|
||||
|
||||
let plugin: VaultExplorerPlugin;
|
||||
let obsidianProperties: ObsidianProperty[] = [];
|
||||
|
|
@ -43,10 +44,10 @@
|
|||
|
||||
function handlePropertyNameChange(e: Event) {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
dispatch("filterNameChange", { id, name: value });
|
||||
dispatch("filterPropertyNameChange", { id, name: value });
|
||||
}
|
||||
|
||||
function handlePropertyTypeChange(e: Event) {
|
||||
function handleTypeChange(e: Event) {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
dispatch("filterTypeChange", { id, type: value });
|
||||
}
|
||||
|
|
@ -61,6 +62,14 @@
|
|||
dispatch("filterValueChange", { id, value });
|
||||
}
|
||||
|
||||
function handleMatchWhenDNEChange(e: Event) {
|
||||
const value = (e.target as HTMLInputElement).checked;
|
||||
dispatch("filterMatchWhenPropertyDNEChange", {
|
||||
id,
|
||||
matchWhenDNE: value,
|
||||
});
|
||||
}
|
||||
|
||||
function handleToggle() {
|
||||
dispatch("filterToggle", { id });
|
||||
}
|
||||
|
|
@ -78,7 +87,7 @@
|
|||
return prop.type === type;
|
||||
});
|
||||
|
||||
function findFilterConditions(type: PropertyFilterType): FilterCondition[] {
|
||||
function findFilterConditions(type: PropertyType): FilterCondition[] {
|
||||
if (type === "text") {
|
||||
return Object.values(TextFilterCondition);
|
||||
} else if (type === "number") {
|
||||
|
|
@ -96,13 +105,13 @@
|
|||
</script>
|
||||
|
||||
<div class="vault-explorer-property-filter">
|
||||
<Wrap spacingX="sm" spacingY="sm">
|
||||
<select value={type} on:change={handlePropertyTypeChange}>
|
||||
{#each Object.values(PropertyFilterType) as type}
|
||||
<Wrap spacingX="sm" spacingY="sm" align="center">
|
||||
<select value={type} on:change={handleTypeChange}>
|
||||
{#each Object.values(PropertyType) as type}
|
||||
<option value={type}>{type}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<select value={name} on:change={handlePropertyNameChange}>
|
||||
<select value={propertyName} on:change={handlePropertyNameChange}>
|
||||
<option value="">Select a property</option>
|
||||
{#each filteredObsidianProperties as prop (prop.name)}
|
||||
<option value={prop.name}>{prop.name}</option>
|
||||
|
|
@ -118,6 +127,14 @@
|
|||
{#if condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST}
|
||||
<input type="text" {value} on:change={handleValueChange} />
|
||||
{/if}
|
||||
{#if condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST}
|
||||
<input
|
||||
aria-label="Match when property doesn't exist"
|
||||
type="checkbox"
|
||||
checked={matchWhenPropertyDNE}
|
||||
on:change={handleMatchWhenDNEChange}
|
||||
/>
|
||||
{/if}
|
||||
<Stack spacing="sm" align="center">
|
||||
<Switch value={isEnabled} on:change={() => handleToggle()} />
|
||||
<IconButton
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
import GroupList from "./components/group-list.svelte";
|
||||
import Flex from "../shared/components/flex.svelte";
|
||||
import Divider from "../shared/components/divider.svelte";
|
||||
import { match } from "assert";
|
||||
|
||||
let selectedGroupId: string = "";
|
||||
let groups: PropertyFilterGroup[] = [];
|
||||
|
|
@ -187,7 +188,7 @@
|
|||
groups = newGroups;
|
||||
}
|
||||
|
||||
function handleFilterNameChange(e: CustomEvent) {
|
||||
function handleFilterPropertyNameChange(e: CustomEvent) {
|
||||
const { id, name } = e.detail;
|
||||
|
||||
const newGroups = groups.map((group) =>
|
||||
|
|
@ -243,7 +244,7 @@
|
|||
throw new Error(`Unhandled filter type: ${type}`);
|
||||
}
|
||||
|
||||
const newGroups = groups.map((group) =>
|
||||
const newGroups: PropertyFilterGroup[] = groups.map((group) =>
|
||||
group.id === selectedGroupId
|
||||
? {
|
||||
...group,
|
||||
|
|
@ -252,7 +253,7 @@
|
|||
? {
|
||||
...filter,
|
||||
type,
|
||||
propertyName: "",
|
||||
name: "",
|
||||
condition,
|
||||
value: "",
|
||||
}
|
||||
|
|
@ -281,6 +282,28 @@
|
|||
|
||||
groups = newGroups;
|
||||
}
|
||||
|
||||
function handleFilterMatchWhenPropertyDNEChange(e: CustomEvent) {
|
||||
const { id, matchWhenDNE } = e.detail;
|
||||
|
||||
const newGroups = groups.map((group) =>
|
||||
group.id === selectedGroupId
|
||||
? {
|
||||
...group,
|
||||
filters: group.filters.map((filter) =>
|
||||
filter.id === id
|
||||
? {
|
||||
...filter,
|
||||
matchWhenPropertyDNE: matchWhenDNE,
|
||||
}
|
||||
: filter,
|
||||
),
|
||||
}
|
||||
: group,
|
||||
);
|
||||
|
||||
groups = newGroups;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="vault-explorer-property-filter-app">
|
||||
|
|
@ -304,9 +327,10 @@
|
|||
on:filterTypeChange={handleFilterTypeChange}
|
||||
on:filterConditionChange={handleFilterConditionChange}
|
||||
on:filterDeleteClick={handleFilterDeleteClick}
|
||||
on:filterNameChange={handleFilterNameChange}
|
||||
on:filterPropertyNameChange={handleFilterPropertyNameChange}
|
||||
on:filterToggle={handleFilterToggle}
|
||||
on:filterValueChange={handleFilterValueChange}
|
||||
on:filterMatchWhenPropertyDNEChange={handleFilterMatchWhenPropertyDNEChange}
|
||||
/>
|
||||
{/if}
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
import { PropertyFilterType, TextFilterCondition, TextPropertyFilter } from "src/types";
|
||||
import { PropertyType, TextFilterCondition, TextPropertyFilter } from "src/types";
|
||||
import { generateUUID } from "../shared/services/uuid";
|
||||
|
||||
export const createPropertyFilter = (): TextPropertyFilter => {
|
||||
return {
|
||||
id: generateUUID(),
|
||||
type: PropertyFilterType.TEXT,
|
||||
type: PropertyType.TEXT,
|
||||
propertyName: "",
|
||||
operator: "and",
|
||||
isEnabled: true,
|
||||
condition: TextFilterCondition.IS,
|
||||
value: "",
|
||||
matchWhenPropertyDNE: false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,12 +87,14 @@ interface BasePropertyFilter {
|
|||
id: string;
|
||||
propertyName: string;
|
||||
operator: FilterOperator;
|
||||
type: PropertyFilterType;
|
||||
type: PropertyType;
|
||||
isEnabled: boolean;
|
||||
value: string;
|
||||
matchWhenPropertyDNE: boolean;
|
||||
}
|
||||
|
||||
export enum PropertyFilterType {
|
||||
//Matches Obsidian property types
|
||||
export enum PropertyType {
|
||||
TEXT = "text",
|
||||
NUMBER = "number",
|
||||
LIST = "list",
|
||||
|
|
@ -102,27 +104,27 @@ export enum PropertyFilterType {
|
|||
}
|
||||
|
||||
export interface TextPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.TEXT;
|
||||
type: PropertyType.TEXT;
|
||||
condition: TextFilterCondition;
|
||||
}
|
||||
|
||||
export interface NumberPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.NUMBER;
|
||||
type: PropertyType.NUMBER;
|
||||
condition: NumberFilterCondition;
|
||||
}
|
||||
|
||||
export interface ListPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.LIST
|
||||
type: PropertyType.LIST
|
||||
condition: ListFilterCondition;
|
||||
}
|
||||
|
||||
export interface CheckboxPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.CHECKBOX
|
||||
type: PropertyType.CHECKBOX
|
||||
condition: CheckboxFilterCondition;
|
||||
}
|
||||
|
||||
export interface DatePropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.DATE | PropertyFilterType.DATETIME;
|
||||
type: PropertyType.DATE | PropertyType.DATETIME;
|
||||
condition: DateFilterCondition;
|
||||
}
|
||||
|
||||
|
|
|
|||
139
src/types/types-1.2.1.ts
Normal file
139
src/types/types-1.2.1.ts
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
export interface VaultExplorerPluginSettings_1_2_1 {
|
||||
logLevel: string;
|
||||
properties: {
|
||||
favorite: string;
|
||||
url: string;
|
||||
custom1: string;
|
||||
custom2: string;
|
||||
custom3: string;
|
||||
},
|
||||
filters: {
|
||||
folder: string;
|
||||
search: string;
|
||||
onlyFavorites: boolean;
|
||||
sort: SortFilter;
|
||||
timestamp: TimestampFilter;
|
||||
properties: {
|
||||
selectedGroupId: string;
|
||||
groups: PropertyFilterGroup[];
|
||||
}
|
||||
},
|
||||
views: {
|
||||
currentView: ViewType;
|
||||
order: ViewType[];
|
||||
titleWrapping: WordBreak;
|
||||
}
|
||||
pageSize: number;
|
||||
pluginVersion: string | null;
|
||||
}
|
||||
|
||||
type WordBreak = "normal" | "break-word";
|
||||
|
||||
enum ViewType {
|
||||
GRID = "grid",
|
||||
LIST = "list",
|
||||
}
|
||||
|
||||
type FilterOperator = "and" | "or";
|
||||
|
||||
enum TextFilterCondition {
|
||||
IS = "is",
|
||||
IS_NOT = "is-not",
|
||||
CONTAINS = "contains",
|
||||
DOES_NOT_CONTAIN = "does-not-contain",
|
||||
STARTS_WITH = "starts-with",
|
||||
ENDS_WITH = "ends-with",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
enum ListFilterCondition {
|
||||
CONTAINS = "contains",
|
||||
DOES_NOT_CONTAIN = "does-not-contain",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
enum NumberFilterCondition {
|
||||
IS_EQUAL = "is-equal",
|
||||
IS_NOT_EQUAL = "is-not-equal",
|
||||
IS_GREATER = "is-greater",
|
||||
IS_LESS = "is-less",
|
||||
IS_GREATER_OR_EQUAL = "is-greater-or-equal",
|
||||
IS_LESS_OR_EQUAL = "is-less-or-equal",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
enum CheckboxFilterCondition {
|
||||
IS = "is",
|
||||
IS_NOT = "is-not",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
enum DateFilterCondition {
|
||||
IS = "is",
|
||||
IS_BEFORE = "is-before",
|
||||
IS_AFTER = "is-after",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
type FilterCondition = TextFilterCondition | NumberFilterCondition | DateFilterCondition | CheckboxFilterCondition | ListFilterCondition;
|
||||
|
||||
interface BasePropertyFilter {
|
||||
id: string;
|
||||
propertyName: string;
|
||||
operator: FilterOperator;
|
||||
type: PropertyFilterType;
|
||||
isEnabled: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
enum PropertyFilterType {
|
||||
TEXT = "text",
|
||||
NUMBER = "number",
|
||||
LIST = "list",
|
||||
CHECKBOX = "checkbox",
|
||||
DATE = "date",
|
||||
DATETIME = "datetime",
|
||||
}
|
||||
|
||||
interface TextPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.TEXT;
|
||||
condition: TextFilterCondition;
|
||||
}
|
||||
|
||||
interface NumberPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.NUMBER;
|
||||
condition: NumberFilterCondition;
|
||||
}
|
||||
|
||||
interface ListPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.LIST
|
||||
condition: ListFilterCondition;
|
||||
}
|
||||
|
||||
interface CheckboxPropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.CHECKBOX
|
||||
condition: CheckboxFilterCondition;
|
||||
}
|
||||
|
||||
interface DatePropertyFilter extends BasePropertyFilter {
|
||||
type: PropertyFilterType.DATE | PropertyFilterType.DATETIME;
|
||||
condition: DateFilterCondition;
|
||||
}
|
||||
|
||||
type PropertyFilter = TextPropertyFilter | NumberPropertyFilter | ListPropertyFilter | CheckboxPropertyFilter | DatePropertyFilter;
|
||||
|
||||
interface PropertyFilterGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
filters: PropertyFilter[];
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
type SortFilter = "file-name-asc" | "file-name-desc" | "modified-asc" | "modified-desc";
|
||||
|
||||
type TimestampFilter = "created-today" | "modified-today" | "created-this-week" | "modified-this-week" | "created-2-weeks" | "modified-2-weeks" | "all";
|
||||
|
|
@ -47,5 +47,6 @@
|
|||
"1.0.1": "1.4.13",
|
||||
"1.1.0": "1.4.13",
|
||||
"1.2.0": "1.4.13",
|
||||
"1.2.1": "1.4.13"
|
||||
|
||||
"1.2.1": "1.4.13",
|
||||
"1.3.0": "1.4.13"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue