diff --git a/__mocks__/obsidian.ts b/__mocks__/obsidian.ts index 4b56776..1e89f45 100644 --- a/__mocks__/obsidian.ts +++ b/__mocks__/obsidian.ts @@ -27,7 +27,32 @@ export const moment = jest.fn((date: string, _formats: string[], _strict?: boole parsedDate.setUTCHours(hour, minute, second); return mockMoment; }), - valueOf: jest.fn(() => parsedDate.getTime()) + valueOf: jest.fn(() => parsedDate.getTime()), + isSame: jest.fn((other, unit) => { + if (unit === 'day') { + const otherDate = new Date(other); + return ( + parsedDate.getUTCFullYear() === otherDate.getUTCFullYear() && + parsedDate.getUTCMonth() === otherDate.getUTCMonth() && + parsedDate.getUTCDate() === otherDate.getUTCDate() + ); + } + return parsedDate.getTime() === new Date(other).getTime(); + }), + isBefore: jest.fn((other, unit) => { + if (unit === 'day') { + const otherDate = new Date(other); + return parsedDate < otherDate && parsedDate.getUTCDate() !== otherDate.getUTCDate(); + } + return parsedDate.getTime() < new Date(other).getTime(); + }), + isAfter: jest.fn((other, unit) => { + if (unit === 'day') { + const otherDate = new Date(other); + return parsedDate > otherDate && parsedDate.getUTCDate() !== otherDate.getUTCDate(); + } + return parsedDate.getTime() > new Date(other).getTime(); + }), }; return mockMoment; }); diff --git a/manifest.json b/manifest.json index 33c7c8b..3d66818 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "vault-explorer", "name": "Vault Explorer", - "version": "1.8.1", + "version": "1.9.0", "minAppVersion": "1.4.13", "description": "Explore your vault in visual format", "author": "DecafDev", diff --git a/package.json b/package.json index 50042ed..afe9836 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-vault-explorer", - "version": "1.8.1", + "version": "1.9.0", "description": "Explore your vault in visual format", "main": "main.js", "scripts": { diff --git a/src/constants.ts b/src/constants.ts index 11bdfce..4c3af32 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,14 +25,14 @@ export const DEFAULT_SETTINGS: VaultExplorerPluginSettings = { onlyFavorites: false, timestamp: "all", sort: "file-name-asc", - properties: { + custom: { selectedGroupId: randomGroupId, groups: [ { id: randomGroupId, name: "Group 1", - filters: [], + rules: [], isEnabled: true } ] diff --git a/src/main.ts b/src/main.ts index b0381bd..cd64f89 100644 --- a/src/main.ts +++ b/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 { PropertyFilter, PropertyFilterGroup, VaultExplorerPluginSettings, ViewType } from './types'; +import { VaultExplorerPluginSettings, ViewType } from './types'; import { DEFAULT_SETTINGS, HOVER_LINK_SOURCE_ID, VAULT_EXPLORER_VIEW } from './constants'; import _ from 'lodash'; import EventManager from './event/event-manager'; @@ -17,10 +17,11 @@ 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'; -import { VaultExplorerPluginSettings_1_5_0 } from './types/types-1.5.0'; +import { PropertyFilterGroup_1_5_0, PropertyFilter_1_5_0, VaultExplorerPluginSettings_1_5_0 } from './types/types-1.5.0'; import { VaultExplorerPluginSettings_1_6_0 } from './types/types-1.6.0'; import { loadDeviceId } from './svelte/shared/services/device-id-utils'; import License from './svelte/shared/services/license'; +import { VaultExplorerPluginSettings_1_8_1 } from './types/types-1.8.1'; export default class VaultExplorerPlugin extends Plugin { settings: VaultExplorerPluginSettings = DEFAULT_SETTINGS; @@ -199,8 +200,8 @@ export default class VaultExplorerPlugin extends Plugin { 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 => { + const updatedGroups: PropertyFilterGroup_1_5_0[] = groups.map(group => { + const updatedFilters: PropertyFilter_1_5_0[] = group.filters.map(filter => { return { ...filter, type: filter.type as any, @@ -243,7 +244,7 @@ export default class VaultExplorerPlugin extends Plugin { if (isVersionLessThan(settingsVersion, "1.6.1")) { console.log("Upgrading settings from version 1.6.0 to 1.6.1"); const typedData = (data as unknown) as VaultExplorerPluginSettings_1_6_0; - const newData: VaultExplorerPluginSettings = { + const newData: VaultExplorerPluginSettings_1_8_1 = { ...typedData, properties: { ...typedData.properties, @@ -253,6 +254,38 @@ export default class VaultExplorerPlugin extends Plugin { } data = newData as unknown as Record; } + + if (isVersionLessThan(settingsVersion, "1.9.0")) { + console.log("Upgrading settings from version 1.8.1 to 1.9.0"); + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_8_1; + const newData: VaultExplorerPluginSettings = { + ...typedData, + filters: { + ...typedData.filters, + custom: { + selectedGroupId: typedData.filters.properties.selectedGroupId, + groups: typedData.filters.properties.groups.map(group => { + const rules = group.filters.map(filter => { + return { + ...filter, + valueData: "", + type: filter.type as any + } + }); + return { + ...group, + rules + } + }) + } + } + } + delete (newData.filters as any).properties; + for (const group of newData.filters.custom.groups as any) { + delete group.filters; + } + data = newData as unknown as Record; + } } } diff --git a/src/svelte/app/components/group-tag-list.svelte b/src/svelte/app/components/group-tag-list.svelte index 7e3d6ce..671e0d4 100644 --- a/src/svelte/app/components/group-tag-list.svelte +++ b/src/svelte/app/components/group-tag-list.svelte @@ -1,9 +1,9 @@
diff --git a/src/svelte/app/index.svelte b/src/svelte/app/index.svelte index 0df06d7..dfa6ed0 100644 --- a/src/svelte/app/index.svelte +++ b/src/svelte/app/index.svelte @@ -8,7 +8,7 @@ import { FrontMatterCache, Menu, TFile, TFolder } from "obsidian"; import PropertiesFilterModal from "src/obsidian/properties-filter-modal"; import { - PropertyFilterGroup, + FilterGroup, SortFilter, TimestampFilter, ViewType, @@ -65,7 +65,7 @@ let onlyFavorites: boolean = false; let viewOrder: ViewType[] = []; let currentView: ViewType = ViewType.GRID; - let propertyFilterGroups: PropertyFilterGroup[] = []; + let propertyFilterGroups: FilterGroup[] = []; let selectedPropertyFilterGroupId: string = ""; let frontmatterCache: Record = {}; @@ -112,16 +112,16 @@ onlyFavorites = plugin.settings.filters.onlyFavorites; currentView = plugin.settings.views.currentView; viewOrder = plugin.settings.views.order; - propertyFilterGroups = plugin.settings.filters.properties.groups; + propertyFilterGroups = plugin.settings.filters.custom.groups; selectedPropertyFilterGroupId = - plugin.settings.filters.properties.selectedGroupId; + plugin.settings.filters.custom.selectedGroupId; }); onMount(() => { function handlePropertiesFilterUpdate() { - propertyFilterGroups = plugin.settings.filters.properties.groups; + propertyFilterGroups = plugin.settings.filters.custom.groups; selectedPropertyFilterGroupId = - plugin.settings.filters.properties.selectedGroupId; + plugin.settings.filters.custom.selectedGroupId; } EventManager.getInstance().on( @@ -387,8 +387,8 @@ plugin.settings.filters.onlyFavorites = onlyFavorites; plugin.settings.views.order = viewOrder; plugin.settings.views.currentView = currentView; - plugin.settings.filters.properties.groups = propertyFilterGroups; - plugin.settings.filters.properties.selectedGroupId = + plugin.settings.filters.custom.groups = propertyFilterGroups; + plugin.settings.filters.custom.selectedGroupId = selectedPropertyFilterGroupId; await plugin.saveSettings(); } diff --git a/src/svelte/app/services/filters/custom/filter-by-groups.ts b/src/svelte/app/services/filters/custom/filter-by-groups.ts index f808aae..78fab81 100644 --- a/src/svelte/app/services/filters/custom/filter-by-groups.ts +++ b/src/svelte/app/services/filters/custom/filter-by-groups.ts @@ -1,23 +1,24 @@ import { FrontMatterCache } from "obsidian"; -import { PropertyFilter, PropertyFilterGroup } from "src/types"; +import { FilterRule, FilterGroup, DatePropertyFilterValue } from "src/types"; import { loadPropertyValue } from "src/svelte/shared/services/load-property-value"; import { matchTextFilter } from "./match-text-filter"; import { matchCheckboxFilter } from "./match-checkbox-filter"; import { matchListFilter } from "./match-list-filter"; import { matchDateFilter } from "./match-date-filter"; import { matchNumberFilter } from "./match-number-filter"; +import { getDateDaysAgo, getDateDaysAhead } from "src/svelte/shared/services/time-utils"; -export const filterByGroups = (frontmatter: FrontMatterCache | undefined, groups: PropertyFilterGroup[]) => { +export const filterByGroups = (frontmatter: FrontMatterCache | undefined, groups: FilterGroup[]) => { return groups.every((group) => { if (!group.isEnabled) return true; return filterByGroup(frontmatter, group); }); } -const filterByGroup = (frontmatter: FrontMatterCache | undefined, group: PropertyFilterGroup) => { +const filterByGroup = (frontmatter: FrontMatterCache | undefined, group: FilterGroup) => { let result: boolean | null = null; - group.filters.forEach((filter, i) => { + group.rules.forEach((filter, i) => { if (!filter.isEnabled) return; const doesMatch = filterByRule(frontmatter, filter); @@ -35,11 +36,11 @@ const filterByGroup = (frontmatter: FrontMatterCache | undefined, group: Propert return result ?? true; } -const filterByRule = (frontmatter: FrontMatterCache | undefined, filter: PropertyFilter) => { - const { propertyName, condition, value, type, matchWhenPropertyDNE } = filter; - if (propertyName === "") return true; +const filterByRule = (frontmatter: FrontMatterCache | undefined, filter: FilterRule) => { + const { condition, value, type, matchWhenPropertyDNE } = filter; if (type === "text") { + const { propertyName } = filter; let propertyValue = loadPropertyValue(frontmatter, propertyName, type); if (propertyValue) { propertyValue = propertyValue.toLowerCase().trim(); @@ -49,12 +50,14 @@ const filterByRule = (frontmatter: FrontMatterCache | undefined, filter: Propert const doesMatch = matchTextFilter(propertyValue, compare, condition, matchWhenPropertyDNE); return doesMatch; } else if (type === "number") { + const { propertyName } = filter; const propertyValue = loadPropertyValue(frontmatter, propertyName, type); const compare = parseFloat(value.trim()); const doesMatch = matchNumberFilter(propertyValue, compare, condition, matchWhenPropertyDNE); return doesMatch; } else if (type === "checkbox") { + const { propertyName } = filter; const propertyValue = loadPropertyValue(frontmatter, propertyName, type); let compare = null; @@ -67,11 +70,30 @@ const filterByRule = (frontmatter: FrontMatterCache | undefined, filter: Propert const doesMatch = matchCheckboxFilter(propertyValue, compare, condition, matchWhenPropertyDNE); return doesMatch; } else if (type === "date" || type === "datetime") { + const { propertyName, valueData } = filter; const propertyValue = loadPropertyValue(frontmatter, propertyName, type); - const doesMatch = matchDateFilter(propertyValue, value, condition, matchWhenPropertyDNE); + let compare = valueData; + if (value === DatePropertyFilterValue.TODAY) { + compare = getDateDaysAgo(0); + } else if (value === DatePropertyFilterValue.YESTERDAY) { + compare = getDateDaysAgo(1); + } else if (value === DatePropertyFilterValue.TOMORROW) { + compare = getDateDaysAhead(1); + } else if (value === DatePropertyFilterValue.ONE_WEEK_AGO) { + compare = getDateDaysAgo(7); + } else if (value === DatePropertyFilterValue.ONE_WEEK_FROM_NOW) { + compare = getDateDaysAhead(7); + } else if (value === DatePropertyFilterValue.ONE_MONTH_AGO) { + compare = getDateDaysAgo(30); + } else if (value === DatePropertyFilterValue.ONE_MONTH_FROM_NOW) { + compare = getDateDaysAhead(30); + } + + const doesMatch = matchDateFilter(propertyValue, compare, condition, matchWhenPropertyDNE); return doesMatch; } else if (type === "list") { + const { propertyName } = filter; let propertyValue = loadPropertyValue(frontmatter, propertyName, type); if (propertyValue) { propertyValue = propertyValue.map((v) => v.toLowerCase().trim()); diff --git a/src/svelte/app/services/filters/custom/match-date-filter.ts b/src/svelte/app/services/filters/custom/match-date-filter.ts index acc597f..a2e67ca 100644 --- a/src/svelte/app/services/filters/custom/match-date-filter.ts +++ b/src/svelte/app/services/filters/custom/match-date-filter.ts @@ -1,4 +1,4 @@ -import { getEndOfDayMillis, getStartOfDayMillis, getTimeMillis, isDateSupported } from "src/svelte/shared/services/time-utils"; +import { getMomentDate, isDateSupported } from "src/svelte/shared/services/time-utils"; import { DateFilterCondition } from "src/types"; export const matchDateFilter = ( @@ -8,40 +8,50 @@ export const matchDateFilter = ( matchIfNull: boolean ) => { if (propertyValue) { - console.assert(isDateSupported(propertyValue), `Date filter propertyValue ${propertyValue} must be supported date format`); + console.assert(isDateSupported(propertyValue), `DateFilter propertyValue "${propertyValue}" must be supported date format`); } + console.assert(isDateSupported(compare), `DateFilter compare "${compare}" must be supported date format`); switch (condition) { case DateFilterCondition.IS: { if (propertyValue === null) return matchIfNull; - if (!isDateSupported(propertyValue)) return true; - const propertyValueTime = getTimeMillis(propertyValue); - const dayStartTime = getStartOfDayMillis(compare); - const dayEndTime = getEndOfDayMillis(compare); - - return ( - propertyValueTime >= dayStartTime && - propertyValueTime <= dayEndTime - ); + const propertyValueDate = getMomentDate(propertyValue); + const compareDate = getMomentDate(compare); + return propertyValueDate.isSame(compareDate, "day"); } case DateFilterCondition.IS_AFTER: { if (propertyValue === null) return matchIfNull; - if (!isDateSupported(propertyValue)) return true; - const propertyValueTime = getTimeMillis(propertyValue); - const dayEndTime = getEndOfDayMillis(compare); - return propertyValueTime > dayEndTime; + const propertyValueDate = getMomentDate(propertyValue); + const compareDate = getMomentDate(compare); + return propertyValueDate.isAfter(compareDate, "day"); } + case DateFilterCondition.IS_ON_OR_AFTER: { + if (propertyValue === null) return matchIfNull; + + const propertyValueDate = getMomentDate(propertyValue); + const compareDate = getMomentDate(compare); + return propertyValueDate.isAfter(compareDate, "day") || propertyValueDate.isSame(compareDate, "day"); + } + + case DateFilterCondition.IS_BEFORE: { if (propertyValue === null) return matchIfNull; - if (!isDateSupported(propertyValue)) return true; - const propertyValueTime = getTimeMillis(propertyValue); - const dayStartTime = getStartOfDayMillis(compare); - return propertyValueTime < dayStartTime; + const propertyValueDate = getMomentDate(propertyValue); + const compareDate = getMomentDate(compare); + return propertyValueDate.isBefore(compareDate, "day"); + } + + case DateFilterCondition.IS_ON_OR_BEFORE: { + if (propertyValue === null) return matchIfNull; + + const propertyValueDate = getMomentDate(propertyValue); + const compareDate = getMomentDate(compare); + return propertyValueDate.isBefore(compareDate, "day") || propertyValueDate.isSame(compareDate, "day"); } case DateFilterCondition.EXISTS: diff --git a/src/svelte/app/services/render-utils.ts b/src/svelte/app/services/render-utils.ts index 690d46d..2646c0e 100644 --- a/src/svelte/app/services/render-utils.ts +++ b/src/svelte/app/services/render-utils.ts @@ -1,12 +1,12 @@ import { FrontMatterCache, TFile } from "obsidian"; -import { PropertyType, VaultExplorerPluginSettings } from "src/types"; +import { FilterRuleType, VaultExplorerPluginSettings } from "src/types"; import { MarkdownFileRenderData } from "../types"; import { getTimeMillis, isDateSupported } from "../../shared/services/time-utils"; import Logger from "js-logger"; import { loadPropertyValue } from "src/svelte/shared/services/load-property-value"; export const formatFileDataForRender = (settings: VaultExplorerPluginSettings, file: TFile, frontmatter: FrontMatterCache | undefined,): MarkdownFileRenderData => { - const tags: string[] | null = loadPropertyValue(frontmatter, "tags", PropertyType.LIST); + const tags: string[] | null = loadPropertyValue(frontmatter, "tags", FilterRuleType.LIST); const { createdDate: createdDateProp, @@ -18,14 +18,14 @@ export const formatFileDataForRender = (settings: VaultExplorerPluginSettings, f custom3: custom3Prop, } = settings.properties; - const url: string | null = loadPropertyValue(frontmatter, urlProp, PropertyType.TEXT); - const favorite: boolean | null = loadPropertyValue(frontmatter, favoriteProp, PropertyType.CHECKBOX); - const creationDate: string | null = loadPropertyValue(frontmatter, createdDateProp, PropertyType.DATE || PropertyType.DATETIME); - const modifiedDate: string | null = loadPropertyValue(frontmatter, modifiedDateProp, PropertyType.DATE || PropertyType.DATETIME); + const url: string | null = loadPropertyValue(frontmatter, urlProp, FilterRuleType.TEXT); + const favorite: boolean | null = loadPropertyValue(frontmatter, favoriteProp, FilterRuleType.CHECKBOX); + const creationDate: string | null = loadPropertyValue(frontmatter, createdDateProp, FilterRuleType.DATE || FilterRuleType.DATETIME); + const modifiedDate: string | null = loadPropertyValue(frontmatter, modifiedDateProp, FilterRuleType.DATE || FilterRuleType.DATETIME); - const custom1: string | null = loadPropertyValue(frontmatter, custom1Prop, PropertyType.TEXT); - const custom2: string | null = loadPropertyValue(frontmatter, custom2Prop, PropertyType.TEXT); - const custom3: string | null = loadPropertyValue(frontmatter, custom3Prop, PropertyType.TEXT); + const custom1: string | null = loadPropertyValue(frontmatter, custom1Prop, FilterRuleType.TEXT); + const custom2: string | null = loadPropertyValue(frontmatter, custom2Prop, FilterRuleType.TEXT); + const custom3: string | null = loadPropertyValue(frontmatter, custom3Prop, FilterRuleType.TEXT); let createdMillis = file.stat.ctime; if (creationDate != null) { diff --git a/src/svelte/properties-filter-app/components/utils.ts b/src/svelte/properties-filter-app/components/display-name-utils.ts similarity index 60% rename from src/svelte/properties-filter-app/components/utils.ts rename to src/svelte/properties-filter-app/components/display-name-utils.ts index 0341939..855f1f2 100644 --- a/src/svelte/properties-filter-app/components/utils.ts +++ b/src/svelte/properties-filter-app/components/display-name-utils.ts @@ -1,4 +1,28 @@ -import { CheckboxFilterCondition, DateFilterCondition, FilterCondition, ListFilterCondition, NumberFilterCondition, TextFilterCondition } from "src/types"; +import { CheckboxFilterCondition, DateFilterCondition, DatePropertyFilterValue, FilterCondition, ListFilterCondition, NumberFilterCondition, TextFilterCondition } from "src/types"; + +export const getDisplayNameForDatePropertyFilterValue = (value: DatePropertyFilterValue) => { + switch (value) { + case DatePropertyFilterValue.TODAY: + return "today"; + case DatePropertyFilterValue.TOMORROW: + return "tomorrow"; + case DatePropertyFilterValue.YESTERDAY: + return "yesterday"; + case DatePropertyFilterValue.ONE_WEEK_AGO: + return "one week ago"; + case DatePropertyFilterValue.ONE_WEEK_FROM_NOW: + return "one week from now"; + case DatePropertyFilterValue.ONE_MONTH_AGO: + return "one month ago"; + case DatePropertyFilterValue.ONE_MONTH_FROM_NOW: + return "one month from now"; + case DatePropertyFilterValue.CUSTOM: + return "custom"; + default: + return ""; + } + +} export const getDisplayNameForFilterCondition = (type: FilterCondition) => { switch (type) { @@ -47,6 +71,10 @@ export const getDisplayNameForFilterCondition = (type: FilterCondition) => { return "is after"; case DateFilterCondition.IS_BEFORE: return "is before"; + case DateFilterCondition.IS_ON_OR_AFTER: + return "is on or after"; + case DateFilterCondition.IS_ON_OR_BEFORE: + return "is on or before"; default: return ""; } diff --git a/src/svelte/properties-filter-app/components/group-edit-view.svelte b/src/svelte/properties-filter-app/components/group-edit-view.svelte index 0cb7f35..b485284 100644 --- a/src/svelte/properties-filter-app/components/group-edit-view.svelte +++ b/src/svelte/properties-filter-app/components/group-edit-view.svelte @@ -3,7 +3,7 @@ import IconButton from "src/svelte/shared/components/icon-button.svelte"; import Stack from "src/svelte/shared/components/stack.svelte"; - import { PropertyFilterGroup } from "src/types"; + import { FilterGroup } from "src/types"; import PropertyFilterList from "./property-filter-list.svelte"; import { createEventDispatcher } from "svelte"; @@ -11,7 +11,7 @@ import Spacer from "src/svelte/shared/components/spacer.svelte"; const dispatch = createEventDispatcher(); - export let selectedGroup: PropertyFilterGroup; + export let selectedGroup: FilterGroup; function handleAddFilterClick() { const newFilter = createPropertyFilter(); @@ -34,14 +34,15 @@
- {#if selectedGroup.filters.length > 0} + {#if selectedGroup.rules.length > 0} import IconButton from "src/svelte/shared/components/icon-button.svelte"; import Stack from "src/svelte/shared/components/stack.svelte"; - import { PropertyFilterGroup } from "src/types"; + import { FilterGroup } from "src/types"; - export let groups: PropertyFilterGroup[]; - export let selectedGroup: PropertyFilterGroup | undefined; + export let groups: FilterGroup[]; + export let selectedGroup: FilterGroup | undefined; let listContainerRef: HTMLDivElement | null; let previousLength = 0; diff --git a/src/svelte/properties-filter-app/components/property-filter-list.svelte b/src/svelte/properties-filter-app/components/property-filter-list.svelte index 4a39594..a2aef4e 100644 --- a/src/svelte/properties-filter-app/components/property-filter-list.svelte +++ b/src/svelte/properties-filter-app/components/property-filter-list.svelte @@ -1,9 +1,9 @@ @@ -11,12 +11,22 @@ {/if} - + {#if propertyName != null} + + {/if} - {#if type == PropertyType.CHECKBOX && condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST} + {#if type === FilterRuleType.CHECKBOX && condition !== CheckboxFilterCondition.EXISTS && condition !== CheckboxFilterCondition.DOES_NOT_EXIST} {/if} - {#if type !== PropertyType.CHECKBOX && condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST} - + {#if (type === FilterRuleType.DATE || type === FilterRuleType.DATETIME) && condition !== DateFilterCondition.EXISTS && condition !== DateFilterCondition.DOES_NOT_EXIST} + + {/if} + {#if type !== FilterRuleType.CHECKBOX && type !== FilterRuleType.DATE && type !== FilterRuleType.DATETIME && condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST} + + {/if} + {#if (type === FilterRuleType.DATE || type === FilterRuleType.DATETIME) && value == DatePropertyFilterValue.CUSTOM && condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST} + {/if} {#if condition !== TextFilterCondition.EXISTS && condition !== TextFilterCondition.DOES_NOT_EXIST} diff --git a/src/svelte/properties-filter-app/index.svelte b/src/svelte/properties-filter-app/index.svelte index 0f203ba..fa88176 100644 --- a/src/svelte/properties-filter-app/index.svelte +++ b/src/svelte/properties-filter-app/index.svelte @@ -6,11 +6,12 @@ import { CheckboxFilterCondition, DateFilterCondition, - FilterCondition, ListFilterCondition, NumberFilterCondition, - PropertyFilterGroup, + FilterGroup, TextFilterCondition, + FilterRuleType, + DatePropertyFilterValue, } from "src/types"; import { generateRandomId } from "../shared/services/random"; import GroupEditView from "./components/group-edit-view.svelte"; @@ -20,7 +21,7 @@ import Divider from "../shared/components/divider.svelte"; let selectedGroupId: string = ""; - let groups: PropertyFilterGroup[] = []; + let groups: FilterGroup[] = []; let plugin: VaultExplorerPlugin; $: selectedGroup = groups.find((group) => group.id === selectedGroupId); @@ -28,16 +29,16 @@ $: groups, selectedGroupId, saveSettings(); async function saveSettings() { - plugin.settings.filters.properties.groups = groups; - plugin.settings.filters.properties.selectedGroupId = selectedGroupId; + plugin.settings.filters.custom.groups = groups; + plugin.settings.filters.custom.selectedGroupId = selectedGroupId; await plugin.saveSettings(); } store.plugin.subscribe((p) => { plugin = p; - groups = plugin.settings.filters.properties.groups; - selectedGroupId = plugin.settings.filters.properties.selectedGroupId; + groups = plugin.settings.filters.custom.groups; + selectedGroupId = plugin.settings.filters.custom.selectedGroupId; }); onMount(() => { @@ -52,10 +53,10 @@ } function handleAddGroupClick() { - const newGroup: PropertyFilterGroup = { + const newGroup: FilterGroup = { id: generateRandomId(), name: `Group ${groups.length + 1}`, - filters: [createPropertyFilter()], + rules: [createPropertyFilter()], isEnabled: groups.length === 0, }; @@ -88,7 +89,7 @@ const newGroups = groups.map((group) => group.id === selectedGroupId - ? { ...group, filters: [...group.filters, filter] } + ? { ...group, rules: [...group.rules, filter] } : group, ); @@ -112,10 +113,8 @@ group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id - ? { ...filter, condition } - : filter, + rules: group.rules.map((rule) => + rule.id === id ? { ...rule, condition } : rule, ), } : group, @@ -167,9 +166,7 @@ group.id === selectedGroupId ? { ...group, - filters: group.filters.filter( - (filter) => filter.id !== id, - ), + rules: group.rules.filter((rule) => rule.id !== id), } : group, ); @@ -184,10 +181,10 @@ group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id - ? { ...filter, propertyName: name } - : filter, + rules: group.rules.map((rule) => + rule.id === id + ? { ...rule, propertyName: name } + : rule, ), } : group, @@ -203,10 +200,10 @@ group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id - ? { ...filter, isEnabled: !filter.isEnabled } - : filter, + rules: group.rules.map((rule) => + rule.id === id + ? { ...rule, isEnabled: !rule.isEnabled } + : rule, ), } : group, @@ -222,8 +219,8 @@ group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id ? { ...filter, operator } : filter, + rules: group.rules.map((rule) => + rule.id === id ? { ...rule, operator } : rule, ), } : group, @@ -235,7 +232,7 @@ function handleFilterTypeChange(e: CustomEvent) { const { id, type } = e.detail; - let newCondition: FilterCondition; + let newCondition: any; let newValue = ""; if (type === "text") { newCondition = TextFilterCondition.IS; @@ -247,25 +244,37 @@ } else if (type === "list") { newCondition = ListFilterCondition.CONTAINS; } else if (type === "date" || type === "datetime") { + newValue = DatePropertyFilterValue.TODAY; newCondition = DateFilterCondition.IS; } else { throw new Error(`Unhandled filter type: ${type}`); } - const newGroups: PropertyFilterGroup[] = groups.map((group) => + const newGroups: FilterGroup[] = groups.map((group) => group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id + rules: group.rules.map((rule) => + rule.id === id ? { - ...filter, + ...rule, type, - name: "", + ...(type === FilterRuleType.TEXT || + type === FilterRuleType.NUMBER || + type === FilterRuleType.LIST || + type === FilterRuleType.CHECKBOX || + type === FilterRuleType.DATE || + type === FilterRuleType.DATETIME + ? { propertyName: "" } + : {}), condition: newCondition, value: newValue, + ...(type === FilterRuleType.DATE || + type === FilterRuleType.DATETIME + ? { valueData: "" } + : {}), } - : filter, + : rule, ), } : group, @@ -277,12 +286,44 @@ function handleFilterValueChange(e: CustomEvent) { const { id, value } = e.detail; + const newGroups: FilterGroup[] = groups.map((group) => { + const { rules } = group; + if (group.id === selectedGroupId) { + const newRules = rules.map((rule) => { + if (rule.id === id) { + return { + ...rule, + value, + ...(rule.type === FilterRuleType.DATE || + rule.type === FilterRuleType.DATETIME + ? { valueData: "" } + : {}), + }; + } + return rule; + }); + return { + ...group, + rules: newRules, + }; + } + return group; + }); + + groups = newGroups; + } + + function handleFilterValueDataChange(e: CustomEvent) { + const { id, value } = e.detail; + const newGroups = groups.map((group) => group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id ? { ...filter, value } : filter, + rules: group.rules.map((rule) => + rule.id === id + ? { ...rule, valueData: value } + : rule, ), } : group, @@ -294,17 +335,17 @@ function handleFilterMatchWhenPropertyDNEChange(e: CustomEvent) { const { id, matchWhenDNE } = e.detail; - const newGroups = groups.map((group) => + const newGroups: FilterGroup[] = groups.map((group) => group.id === selectedGroupId ? { ...group, - filters: group.filters.map((filter) => - filter.id === id + rules: group.rules.map((rule) => + rule.id === id ? { - ...filter, + ...rule, matchWhenPropertyDNE: matchWhenDNE, } - : filter, + : rule, ), } : group, @@ -339,6 +380,7 @@ on:filterToggle={handleFilterToggle} on:filterOperatorChange={handleFilterOperatorChange} on:filterValueChange={handleFilterValueChange} + on:filterValueDataChange={handleFilterValueDataChange} on:filterMatchWhenPropertyDNEChange={handleFilterMatchWhenPropertyDNEChange} /> {/if} diff --git a/src/svelte/properties-filter-app/utils.ts b/src/svelte/properties-filter-app/utils.ts index 01ccc3b..6d81f5f 100644 --- a/src/svelte/properties-filter-app/utils.ts +++ b/src/svelte/properties-filter-app/utils.ts @@ -1,10 +1,10 @@ -import { PropertyType, TextFilterCondition, TextPropertyFilter } from "src/types"; +import { FilterRuleType, TextFilterCondition, TextPropertyFilter } from "src/types"; import { generateRandomId } from "../shared/services/random"; export const createPropertyFilter = (): TextPropertyFilter => { return { id: generateRandomId(), - type: PropertyType.TEXT, + type: FilterRuleType.TEXT, propertyName: "", operator: "and", isEnabled: true, diff --git a/src/svelte/shared/services/load-property-value.ts b/src/svelte/shared/services/load-property-value.ts index 120a224..52c3973 100644 --- a/src/svelte/shared/services/load-property-value.ts +++ b/src/svelte/shared/services/load-property-value.ts @@ -1,6 +1,6 @@ import Logger from "js-logger"; import { FrontMatterCache } from "obsidian"; -import { PropertyType } from "src/types"; +import { FilterRuleType } from "src/types"; import { isDateSupported } from "./time-utils"; /** @@ -10,7 +10,7 @@ import { isDateSupported } from "./time-utils"; * @param expectedType - The expected type of the property * @returns - The property value or null if the property isn't valid */ -export const loadPropertyValue = (frontmatter: FrontMatterCache | undefined, propertyName: string, expectedType: PropertyType): T | null => { +export const loadPropertyValue = (frontmatter: FrontMatterCache | undefined, propertyName: string, expectedType: FilterRuleType): T | null => { //If the file has no frontmatter, return null if (!frontmatter) { return null; @@ -29,32 +29,32 @@ export const loadPropertyValue = (frontmatter: FrontMatterCache | undefined, } //Validate the property value for the expected type - if (expectedType === PropertyType.TEXT) { + if (expectedType === FilterRuleType.TEXT) { if (typeof propertyValue !== "string") { Logger.warn(`Property value of type 'text' is not a string: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.NUMBER) { + } else if (expectedType === FilterRuleType.NUMBER) { if (typeof propertyValue !== "number") { Logger.warn(`Property value of type 'number' is not a number: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.DATE) { + } else if (expectedType === FilterRuleType.DATE) { if (typeof propertyValue !== "string") { Logger.warn(`Property value of type 'date' is not a string: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.DATETIME) { + } else if (expectedType === FilterRuleType.DATETIME) { if (typeof propertyValue !== "string") { Logger.warn(`Property value of type 'datetime' is not a string: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.CHECKBOX) { + } else if (expectedType === FilterRuleType.CHECKBOX) { if (typeof propertyValue !== "boolean") { Logger.warn(`Property value of type 'checkbox' is not a boolean: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.LIST) { + } else if (expectedType === FilterRuleType.LIST) { if (!Array.isArray(propertyValue)) { Logger.warn(`Property value of type 'list' is not an array: ${propertyValue}`); //Don't return null here, because the property value can be converted to an array @@ -63,19 +63,19 @@ export const loadPropertyValue = (frontmatter: FrontMatterCache | undefined, //In older versions of Obsidian, the date can be stored in the frontmatter //in a format other than YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS - if (expectedType === PropertyType.DATE) { + if (expectedType === FilterRuleType.DATE) { if (!isDateSupported(propertyValue)) { Logger.warn(`Property value of type 'date' has unsupported date format: ${propertyValue}`); return null; } - } else if (expectedType === PropertyType.DATETIME) { + } else if (expectedType === FilterRuleType.DATETIME) { if (!isDateSupported(propertyValue)) { Logger.warn(`Property value of type 'datetime' has unsupported date format: ${propertyValue}`); return null; } } - if (expectedType === PropertyType.LIST) { + if (expectedType === FilterRuleType.LIST) { //If the property is not an array, return it as an array //This is a bug in Obsidian? if (!Array.isArray(propertyValue)) { diff --git a/src/svelte/shared/services/time-utils.ts b/src/svelte/shared/services/time-utils.ts index 5cb27f0..03ba976 100644 --- a/src/svelte/shared/services/time-utils.ts +++ b/src/svelte/shared/services/time-utils.ts @@ -27,6 +27,18 @@ export const getStartOfThisWeekMillis = () => { return moment().startOf("week").valueOf(); }; +export const getMomentDate = (date: string) => { + return moment(date, DATE_FORMATS, true); +} + +export const getDateDaysAgo = (daysAgo: number) => { + return moment().subtract(daysAgo, "days").format("YYYY-MM-DD"); +} + +export const getDateDaysAhead = (daysAgo: number) => { + return moment().add(daysAgo, "days").format("YYYY-MM-DD"); +} + /** * Gets 12:00 AM of the previous week in milliseconds. The week starts on Sunday. * @returns - The start of the previous week in milliseconds diff --git a/src/types/index.ts b/src/types/index.ts index b540ce7..4f671c8 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -15,9 +15,9 @@ export interface VaultExplorerPluginSettings { onlyFavorites: boolean; sort: SortFilter; timestamp: TimestampFilter; - properties: { + custom: { selectedGroupId: string; - groups: PropertyFilterGroup[]; + groups: FilterGroup[]; } }, views: { @@ -74,29 +74,20 @@ export enum CheckboxFilterCondition { DOES_NOT_EXIST = "does-not-exist", } -//TODO: add more types +//TODO: add is between export enum DateFilterCondition { IS = "is", IS_BEFORE = "is-before", IS_AFTER = "is-after", + IS_ON_OR_BEFORE = "is-on-or-before", + IS_ON_OR_AFTER = "is-on-or-after", EXISTS = "exists", DOES_NOT_EXIST = "does-not-exist", } export type FilterCondition = TextFilterCondition | NumberFilterCondition | DateFilterCondition | CheckboxFilterCondition | ListFilterCondition; -interface BasePropertyFilter { - id: string; - propertyName: string; - operator: FilterOperator; - type: PropertyType; - isEnabled: boolean; - value: string; - matchWhenPropertyDNE: boolean; -} - -//Matches Obsidian property types -export enum PropertyType { +export enum FilterRuleType { TEXT = "text", NUMBER = "number", LIST = "list", @@ -105,37 +96,63 @@ export enum PropertyType { DATETIME = "datetime", } -export interface TextPropertyFilter extends BasePropertyFilter { - type: PropertyType.TEXT; +export enum DatePropertyFilterValue { + TODAY = "today", + TOMORROW = "tomorrow", + YESTERDAY = "yesterday", + ONE_WEEK_FROM_NOW = "one-week-from-now", + ONE_WEEK_AGO = "one-week-ago", + ONE_MONTH_FROM_NOW = "one-month-from-now", + ONE_MONTH_AGO = "one-month-ago", + CUSTOM = "custom" +} + +interface BaseFilterRule { + id: string; + operator: FilterOperator; + type: FilterRuleType; + isEnabled: boolean; + value: string; + matchWhenPropertyDNE: boolean; +} + +export interface TextPropertyFilter extends BaseFilterRule { + type: FilterRuleType.TEXT; + propertyName: string; condition: TextFilterCondition; } -export interface NumberPropertyFilter extends BasePropertyFilter { - type: PropertyType.NUMBER; +export interface NumberPropertyFilter extends BaseFilterRule { + type: FilterRuleType.NUMBER; + propertyName: string; condition: NumberFilterCondition; } -export interface ListPropertyFilter extends BasePropertyFilter { - type: PropertyType.LIST +export interface ListPropertyFilter extends BaseFilterRule { + type: FilterRuleType.LIST + propertyName: string; condition: ListFilterCondition; } -export interface CheckboxPropertyFilter extends BasePropertyFilter { - type: PropertyType.CHECKBOX +export interface CheckboxPropertyFilter extends BaseFilterRule { + type: FilterRuleType.CHECKBOX; + propertyName: string; condition: CheckboxFilterCondition; } -export interface DatePropertyFilter extends BasePropertyFilter { - type: PropertyType.DATE | PropertyType.DATETIME; +export interface DatePropertyFilter extends BaseFilterRule { + type: FilterRuleType.DATE | FilterRuleType.DATETIME; + propertyName: string; condition: DateFilterCondition; + valueData: string; } -export type PropertyFilter = TextPropertyFilter | NumberPropertyFilter | ListPropertyFilter | CheckboxPropertyFilter | DatePropertyFilter; +export type FilterRule = TextPropertyFilter | NumberPropertyFilter | ListPropertyFilter | CheckboxPropertyFilter | DatePropertyFilter; -export interface PropertyFilterGroup { +export interface FilterGroup { id: string; name: string; - filters: PropertyFilter[]; + rules: FilterRule[]; isEnabled: boolean; } diff --git a/src/types/types-1.5.0.ts b/src/types/types-1.5.0.ts index 7c4f316..2f58b0c 100644 --- a/src/types/types-1.5.0.ts +++ b/src/types/types-1.5.0.ts @@ -27,6 +27,10 @@ export interface VaultExplorerPluginSettings_1_5_0 { pluginVersion: string | null; } +export type PropertyFilterGroup_1_5_0 = PropertyFilterGroup; + +export type PropertyFilter_1_5_0 = PropertyFilter; + type WordBreak = "normal" | "break-word"; enum ViewType { diff --git a/src/types/types-1.8.1.ts b/src/types/types-1.8.1.ts new file mode 100644 index 0000000..b74f2f4 --- /dev/null +++ b/src/types/types-1.8.1.ts @@ -0,0 +1,144 @@ +export interface VaultExplorerPluginSettings_1_8_1 { + logLevel: string; + properties: { + favorite: string; + url: string; + createdDate: string; + modifiedDate: 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", +} + +//TODO: add more types +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: PropertyType; + isEnabled: boolean; + value: string; + matchWhenPropertyDNE: boolean; +} + +//Matches Obsidian property types +enum PropertyType { + TEXT = "text", + NUMBER = "number", + LIST = "list", + CHECKBOX = "checkbox", + DATE = "date", + DATETIME = "datetime", +} + +interface TextPropertyFilter extends BasePropertyFilter { + type: PropertyType.TEXT; + condition: TextFilterCondition; +} + +interface NumberPropertyFilter extends BasePropertyFilter { + type: PropertyType.NUMBER; + condition: NumberFilterCondition; +} + +interface ListPropertyFilter extends BasePropertyFilter { + type: PropertyType.LIST + condition: ListFilterCondition; +} + +interface CheckboxPropertyFilter extends BasePropertyFilter { + type: PropertyType.CHECKBOX + condition: CheckboxFilterCondition; +} + +interface DatePropertyFilter extends BasePropertyFilter { + type: PropertyType.DATE | PropertyType.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"; diff --git a/tests/unit/load-property-value.test.ts b/tests/unit/load-property-value.test.ts index bf131ff..f4bbb3f 100644 --- a/tests/unit/load-property-value.test.ts +++ b/tests/unit/load-property-value.test.ts @@ -1,6 +1,6 @@ import { FrontMatterCache } from "obsidian"; -import { PropertyType } from "src/types"; +import { FilterRuleType } from "src/types"; import { loadPropertyValue } from "src/svelte/shared/services/load-property-value"; describe("loadPropertyValue", () => { @@ -9,7 +9,7 @@ describe("loadPropertyValue", () => { const frontmatter: FrontMatterCache | undefined = undefined; //Act - const result = loadPropertyValue(frontmatter, "test", PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, "test", FilterRuleType.TEXT); //Assert expect(result).toBeNull(); @@ -21,7 +21,7 @@ describe("loadPropertyValue", () => { const propertyName = ""; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.TEXT); //Assert expect(result).toBeNull(); @@ -33,7 +33,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.TEXT); //Assert expect(result).toBeNull(); @@ -45,7 +45,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.TEXT); //Assert expect(result).toBeNull(); @@ -57,7 +57,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.TEXT); //Assert expect(result).toBeNull(); @@ -69,7 +69,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.TEXT); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.TEXT); //Assert expect(result).toBe("test"); @@ -81,7 +81,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.NUMBER); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.NUMBER); //Assert expect(result).toBeNull(); @@ -93,7 +93,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.NUMBER); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.NUMBER); //Assert expect(result).toBe(1); @@ -105,7 +105,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.CHECKBOX); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.CHECKBOX); //Assert expect(result).toBeNull(); @@ -117,7 +117,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.CHECKBOX); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.CHECKBOX); //Assert expect(result).toBe(true); @@ -129,7 +129,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.LIST); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.LIST); //Assert expect(result).toEqual(["test"]); @@ -141,7 +141,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.LIST); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.LIST); //Assert expect(result).toEqual(["test"]); @@ -154,7 +154,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.LIST); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.LIST); //Assert expect(result).toEqual(["test"]); @@ -166,7 +166,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATE); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATE); //Assert expect(result).toBeNull(); @@ -178,7 +178,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATETIME); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATETIME); //Assert expect(result).toBeNull(); @@ -191,7 +191,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATE); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATE); //Assert expect(result).toBe("2021-01-01"); @@ -203,7 +203,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATETIME); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATETIME); //Assert expect(result).toBeNull(); @@ -215,7 +215,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATETIME); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATETIME); //Assert expect(result).toBeNull(); @@ -227,7 +227,7 @@ describe("loadPropertyValue", () => { const propertyName = "test"; //Act - const result = loadPropertyValue(frontmatter, propertyName, PropertyType.DATETIME); + const result = loadPropertyValue(frontmatter, propertyName, FilterRuleType.DATETIME); //Assert expect(result).toBe("2021-01-01T00:00:00"); diff --git a/tests/unit/match-date-filter.test.ts b/tests/unit/match-date-filter.test.ts index 0877fcd..d1fc9dc 100644 --- a/tests/unit/match-date-filter.test.ts +++ b/tests/unit/match-date-filter.test.ts @@ -189,20 +189,6 @@ describe("matchDateFilter", () => { // Assert expect(result).toEqual(false); }); - - it("should return false for matchDateFilter(YYYY-MM-DDTHH:mm:ss, invalid-date, IS, false)", () => { - // Arrange - const propertyValue = "2020-01-01T12:00:00"; - const compare = "invalid-date"; - const condition = DateFilterCondition.IS; - const matchIfNull = false; - - // Act - const result = matchDateFilter(propertyValue, compare, condition, matchIfNull); - - // Assert - expect(result).toEqual(false); - }); }); describe("Error Cases", () => { diff --git a/versions.json b/versions.json index e6e2b7a..532f416 100644 --- a/versions.json +++ b/versions.json @@ -59,5 +59,6 @@ "1.7.2": "1.4.13", "1.7.3": "1.4.13", "1.8.0": "1.4.13", - "1.8.1": "1.4.13" + "1.8.1": "1.4.13", + "1.9.0": "1.4.13" }