mirror of
https://github.com/decaf-dev/obsidian-vault-explorer.git
synced 2026-07-22 10:10:31 +00:00
Add table view (#293)
* chore: bump version * feat: add basic table view * feat: format time data as a time string * feat: add basePath * refactor: remove unused handlers * feat: add context menu to table * feat: add title support * feat: remove slash from path * feat: handle custom rendering of elements * feat: handle row click * feat: add min width to columns * feat: add hover over * feat: add file icons * feat: enable table setting
This commit is contained in:
parent
fca7f1c5cd
commit
aae9d6c394
18 changed files with 671 additions and 46 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "vault-explorer",
|
||||
"name": "Vault Explorer",
|
||||
"version": "1.38.0",
|
||||
"version": "1.39.0",
|
||||
"minAppVersion": "1.4.13",
|
||||
"description": "Explore your vault in visual format",
|
||||
"author": "DecafDev",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "obsidian-vault-explorer",
|
||||
"version": "1.38.0",
|
||||
"version": "1.39.0",
|
||||
"description": "Explore your vault in visual format",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,12 @@ export const DEFAULT_SETTINGS: VaultExplorerPluginSettings = {
|
|||
filterGroupsWidth: "300px",
|
||||
shouldWrapFilterGroups: false,
|
||||
pageSize: 25,
|
||||
viewOrder: [TExplorerView.GRID, TExplorerView.LIST, TExplorerView.FEED],
|
||||
viewOrder: [
|
||||
TExplorerView.GRID,
|
||||
TExplorerView.LIST,
|
||||
TExplorerView.TABLE,
|
||||
TExplorerView.FEED,
|
||||
],
|
||||
configDir: ".vaultexplorer",
|
||||
pluginVersion: null,
|
||||
logLevel: LOG_LEVEL_WARN,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import Migrate_1_31_0 from "./migrate_1_31_0";
|
|||
import Migrate_1_33_0 from "./migrate_1_33_0";
|
||||
import Migrate_1_37_0 from "./migrate_1_37_0";
|
||||
import Migrate_1_38_0 from "./migrate_1_38_0";
|
||||
import Migrate_1_39_0 from "./migrate_1_39_0";
|
||||
|
||||
const migrations: TMigration[] = [
|
||||
{
|
||||
|
|
@ -165,6 +166,11 @@ const migrations: TMigration[] = [
|
|||
to: "1.38.0",
|
||||
migrate: Migrate_1_38_0,
|
||||
},
|
||||
{
|
||||
from: "1.38.0",
|
||||
to: "1.39.0",
|
||||
migrate: Migrate_1_39_0,
|
||||
},
|
||||
];
|
||||
|
||||
export const preformMigrations = (
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { VaultExplorerPluginSettings_1_37_2 } from "src/types/types-1-37-0";
|
||||
import MigrationInterface from "./migration_interface";
|
||||
import { VaultExplorerPluginSettings } from "src/types";
|
||||
import { VaultExplorerPluginSettings_1_38_0 } from "src/types/types-1.38.0";
|
||||
|
||||
export default class Migrate_1_38_0 implements MigrationInterface {
|
||||
migrate(data: Record<string, unknown>) {
|
||||
const typedData = data as unknown as VaultExplorerPluginSettings_1_37_2;
|
||||
const typedData = data as unknown as VaultExplorerPluginSettings_1_38_0;
|
||||
const newData: VaultExplorerPluginSettings = {
|
||||
...typedData,
|
||||
loadBodyTags: true,
|
||||
|
|
|
|||
26
src/migrations/migrate_1_39_0.ts
Normal file
26
src/migrations/migrate_1_39_0.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import MigrationInterface from "./migration_interface";
|
||||
import { TExplorerView, VaultExplorerPluginSettings } from "src/types";
|
||||
import { VaultExplorerPluginSettings_1_38_0 } from "src/types/types-1.38.0";
|
||||
|
||||
export default class Migrate_1_39_0 implements MigrationInterface {
|
||||
migrate(data: Record<string, unknown>) {
|
||||
const typedData = data as unknown as VaultExplorerPluginSettings_1_38_0;
|
||||
const newData: VaultExplorerPluginSettings = {
|
||||
...typedData,
|
||||
viewOrder: [
|
||||
TExplorerView.GRID,
|
||||
TExplorerView.LIST,
|
||||
TExplorerView.TABLE,
|
||||
TExplorerView.FEED,
|
||||
],
|
||||
views: {
|
||||
...typedData.views,
|
||||
table: {
|
||||
isEnabled: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return newData as unknown as Record<string, unknown>;
|
||||
}
|
||||
}
|
||||
|
|
@ -247,8 +247,6 @@ export default class VaultExplorerSettingsTab extends PluginSettingTab {
|
|||
|
||||
new Setting(containerEl).setName("Table view").addToggle((toggle) =>
|
||||
toggle
|
||||
.setDisabled(true) //TODO implement
|
||||
.setTooltip("This view is not yet implemented.")
|
||||
.setValue(this.plugin.settings.views.table.isEnabled)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.views.table.isEnabled = value;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export default class VaultExplorerView extends ItemView {
|
|||
const containerEl = this.containerEl.children[1];
|
||||
|
||||
store.plugin.set(this.plugin);
|
||||
|
||||
this.component = new VaultExplorerApp({
|
||||
target: containerEl,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@
|
|||
const dispatch = createEventDispatcher();
|
||||
|
||||
let plugin: VaultExplorerPlugin;
|
||||
store.plugin.subscribe((value) => {
|
||||
plugin = value;
|
||||
store.plugin.subscribe((p) => {
|
||||
plugin = p;
|
||||
enableFileIcons = plugin.settings.enableFileIcons;
|
||||
removeH1 = plugin.settings.views.feed.removeH1;
|
||||
collapseStyle = plugin.settings.views.feed.collapseStyle;
|
||||
|
|
@ -158,10 +158,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
function handleTitleContextMenu(e: Event) {
|
||||
handleCardContextMenu(e);
|
||||
}
|
||||
|
||||
function handleCardMouseOver(e: MouseEvent) {
|
||||
const targetEl = e.currentTarget as HTMLElement;
|
||||
plugin.app.workspace.trigger("hover-link", {
|
||||
|
|
@ -233,14 +229,6 @@
|
|||
role="link"
|
||||
class="vault-explorer-feed-card__title"
|
||||
on:focus={() => {}}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
handleTitleClick();
|
||||
}}
|
||||
on:contextmenu={(e) => {
|
||||
e.preventDefault();
|
||||
handleTitleContextMenu(e);
|
||||
}}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
|
|
@ -285,7 +273,7 @@
|
|||
}
|
||||
|
||||
.vault-explorer-feed-card:focus-visible {
|
||||
box-shadow: 0 0 0 3px var(--background-modifier-border-focus);
|
||||
box-shadow: 0 0 0 3px var(--background-modifier-focus);
|
||||
}
|
||||
|
||||
.vault-explorer-feed-card__title {
|
||||
|
|
|
|||
|
|
@ -159,10 +159,6 @@
|
|||
handleCardClick();
|
||||
}
|
||||
|
||||
function handleTitleContextMenu(e: Event) {
|
||||
handleCardContextMenu(e);
|
||||
}
|
||||
|
||||
$: hasFooterContent =
|
||||
tags != null || custom1 != null || custom2 != null || custom3 != null;
|
||||
|
||||
|
|
@ -249,10 +245,6 @@
|
|||
e.preventDefault();
|
||||
handleTitleClick();
|
||||
}}
|
||||
on:contextmenu={(e) => {
|
||||
e.preventDefault();
|
||||
handleTitleContextMenu(e);
|
||||
}}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
|
|
@ -106,10 +106,6 @@
|
|||
openInCurrentTab(plugin, path);
|
||||
}
|
||||
|
||||
function handleTitleContextMenu(e: Event) {
|
||||
handleItemContextMenu(e);
|
||||
}
|
||||
|
||||
function handleFavoriteChange(filePath: string, value: boolean) {
|
||||
dispatch("favoritePropertyChange", { filePath, value });
|
||||
}
|
||||
|
|
@ -166,14 +162,6 @@
|
|||
role="link"
|
||||
class={titleClassName}
|
||||
on:focus={() => {}}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
handleTitleClick();
|
||||
}}
|
||||
on:contextmenu={(e) => {
|
||||
e.preventDefault();
|
||||
handleTitleContextMenu(e);
|
||||
}}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
278
src/svelte/app/components/table-view.svelte
Normal file
278
src/svelte/app/components/table-view.svelte
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { openContextMenu } from "../services/context-menu";
|
||||
import { formatAsBearTimeString } from "../services/time-string";
|
||||
import { FileRenderData } from "../types";
|
||||
import store from "src/svelte/shared/services/store";
|
||||
import VaultExplorerPlugin from "src/main";
|
||||
import Tag from "src/svelte/shared/components/tag.svelte";
|
||||
import Wrap from "src/svelte/shared/components/wrap.svelte";
|
||||
import { openInCurrentTab } from "../services/open-file";
|
||||
import { HOVER_LINK_SOURCE_ID } from "src/constants";
|
||||
import Stack from "src/svelte/shared/components/stack.svelte";
|
||||
import { getIconIdForFile } from "../services/file-icon";
|
||||
import Icon from "src/svelte/shared/components/icon.svelte";
|
||||
import EventManager from "src/event/event-manager";
|
||||
import { PluginEvent } from "src/event/types";
|
||||
|
||||
interface TColumn {
|
||||
key: string;
|
||||
label: string;
|
||||
classNames?: string;
|
||||
format?: (value: unknown) => string;
|
||||
}
|
||||
|
||||
export let data: FileRenderData[];
|
||||
export let startIndex: number;
|
||||
export let pageLength: number;
|
||||
|
||||
let filteredItems: FileRenderData[] = [];
|
||||
let plugin: VaultExplorerPlugin | null = null;
|
||||
let enableFileIcons: boolean = true;
|
||||
|
||||
let columns: TColumn[] = [
|
||||
{
|
||||
key: "baseName",
|
||||
label: "Name",
|
||||
classNames: "vault-explorer-table-view__title-text",
|
||||
},
|
||||
{ key: "extension", label: "Extension" },
|
||||
{ key: "basePath", label: "Folder" },
|
||||
{
|
||||
key: "tags",
|
||||
label: "Tags",
|
||||
},
|
||||
{
|
||||
key: "isFavorite",
|
||||
label: "Favorite",
|
||||
format: (value: unknown) => (value === true ? "Yes" : "No"),
|
||||
},
|
||||
{
|
||||
key: "createdMillis",
|
||||
label: "Created",
|
||||
format: (value: unknown) => formatAsBearTimeString(value as number),
|
||||
},
|
||||
{
|
||||
key: "modifiedMillis",
|
||||
label: "Modified",
|
||||
format: (value: unknown) => formatAsBearTimeString(value as number),
|
||||
},
|
||||
];
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
store.plugin.subscribe((p) => {
|
||||
plugin = p;
|
||||
enableFileIcons = plugin.settings.enableFileIcons;
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
function handleFileIconsChange() {
|
||||
if (plugin === null) return;
|
||||
|
||||
enableFileIcons = plugin.settings.enableFileIcons;
|
||||
}
|
||||
|
||||
EventManager.getInstance().on(
|
||||
PluginEvent.FILE_ICONS_SETTING_CHANGE,
|
||||
handleFileIconsChange,
|
||||
);
|
||||
return () => {
|
||||
EventManager.getInstance().off(
|
||||
PluginEvent.FILE_ICONS_SETTING_CHANGE,
|
||||
handleFileIconsChange,
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
function handleFavoriteChange(filePath: string, value: boolean) {
|
||||
dispatch("favoritePropertyChange", { filePath, value });
|
||||
}
|
||||
|
||||
function handleRowClick(path: string) {
|
||||
if (plugin === null) return;
|
||||
|
||||
openInCurrentTab(plugin, path);
|
||||
}
|
||||
|
||||
function handleRowMouseOver(e: MouseEvent, path: string) {
|
||||
if (plugin === null) return;
|
||||
|
||||
const targetEl = e.currentTarget as HTMLElement;
|
||||
plugin.app.workspace.trigger("hover-link", {
|
||||
event: e,
|
||||
linktext: path,
|
||||
source: HOVER_LINK_SOURCE_ID,
|
||||
targetEl,
|
||||
hoverParent: targetEl.parentElement,
|
||||
});
|
||||
}
|
||||
|
||||
function handleRowContextMenu(
|
||||
e: Event,
|
||||
path: string,
|
||||
isFavorite: boolean | null,
|
||||
) {
|
||||
if (plugin === null) return;
|
||||
|
||||
const nativeEvent = e as MouseEvent;
|
||||
openContextMenu(plugin, path, nativeEvent, {
|
||||
isFavorite,
|
||||
onFavoriteChange: handleFavoriteChange,
|
||||
});
|
||||
}
|
||||
|
||||
function getValue(item: FileRenderData, column: TColumn): unknown {
|
||||
const { key, format } = column;
|
||||
const itemValue = item[key as keyof FileRenderData] ?? "";
|
||||
|
||||
if (format !== undefined) {
|
||||
return format(itemValue);
|
||||
}
|
||||
return itemValue;
|
||||
}
|
||||
|
||||
function asStringArray(value: unknown): string[] {
|
||||
return value as string[];
|
||||
}
|
||||
|
||||
$: {
|
||||
if (startIndex < data.length) {
|
||||
filteredItems = Array.from({ length: pageLength }, (_, i) => {
|
||||
const index = startIndex + i;
|
||||
return data[index];
|
||||
});
|
||||
} else {
|
||||
filteredItems = [];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="vault-explorer-table-view">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{#each columns as column (column.key)}
|
||||
<th>{column.label}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each filteredItems as filteredItem}
|
||||
<tr
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="vault-explorer-list-item"
|
||||
on:click={() => handleRowClick(filteredItem.path)}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
handleRowClick(filteredItem.path);
|
||||
}
|
||||
}}
|
||||
on:focus={() => {}}
|
||||
on:contextmenu={(e) =>
|
||||
handleRowContextMenu(
|
||||
e,
|
||||
filteredItem.path,
|
||||
filteredItem.isFavorite,
|
||||
)}
|
||||
on:mouseover={(e) =>
|
||||
handleRowMouseOver(e, filteredItem.path)}
|
||||
>
|
||||
{#each columns as column (column.key)}
|
||||
{@const value = getValue(filteredItem, column)}
|
||||
<td>
|
||||
{#if column.key == "tags"}
|
||||
<Wrap spacingX="sm" spacingY="sm">
|
||||
{#each asStringArray(value) as tag}
|
||||
<Tag name={tag} variant="unstyled" />
|
||||
{/each}
|
||||
</Wrap>
|
||||
{:else if column.key == "baseName"}
|
||||
<div class="vault-explorer-table-view__title">
|
||||
<Stack spacing="xs">
|
||||
{#if enableFileIcons}
|
||||
<Icon
|
||||
iconId={getIconIdForFile(
|
||||
filteredItem.baseName,
|
||||
filteredItem.extension,
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
<div
|
||||
class="vault-explorer-table-view__title-text"
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
{:else}
|
||||
<div>{value}</div>
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.vault-explorer-table-view {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th:first-child,
|
||||
.vault-explorer-table-view td:first-child {
|
||||
width: 300px;
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view__title {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view__title-text {
|
||||
color: var(--text-accent);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th,
|
||||
.vault-explorer-table-view td {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th:nth-child(4) {
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th:nth-child(6) {
|
||||
min-width: 175px;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view th:nth-child(7) {
|
||||
min-width: 175px;
|
||||
}
|
||||
|
||||
.vault-explorer-table-view tr:hover:not(:has(th)) {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.vault-explorer-table-view tr:focus-visible:not(:has(th)) {
|
||||
box-shadow: 0 0 0 3px var(--background-modifier-border-focus);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
favoritesStore,
|
||||
TFavoritesCache,
|
||||
} from "./services/favorites-store";
|
||||
import TableView from "./components/table-view.svelte";
|
||||
|
||||
// ============================================
|
||||
// Variables
|
||||
|
|
@ -965,6 +966,13 @@
|
|||
{pageLength}
|
||||
on:favoritePropertyChange={handleFavoritePropertyChange}
|
||||
/>
|
||||
{:else if currentView === "table"}
|
||||
<TableView
|
||||
data={renderData}
|
||||
{startIndex}
|
||||
{pageLength}
|
||||
on:favoritePropertyChange={handleFavoritePropertyChange}
|
||||
/>
|
||||
{:else if currentView === "feed"}
|
||||
<FeedView
|
||||
data={renderData}
|
||||
|
|
|
|||
|
|
@ -221,12 +221,16 @@ export const formatFileDataForRender = ({
|
|||
}
|
||||
|
||||
const displayName = extension === "md" ? basename : name;
|
||||
const basePath = path.includes("/")
|
||||
? path.substring(0, path.lastIndexOf("/"))
|
||||
: "/";
|
||||
|
||||
return {
|
||||
id: fileId,
|
||||
displayName,
|
||||
baseName: basename,
|
||||
path,
|
||||
baseName: basename,
|
||||
basePath,
|
||||
extension,
|
||||
url,
|
||||
content: fileContent,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ export interface FileRenderData {
|
|||
id: string;
|
||||
displayName: string;
|
||||
path: string;
|
||||
basePath: string;
|
||||
extension: string;
|
||||
baseName: string;
|
||||
content: string | null;
|
||||
|
|
|
|||
327
src/types/types-1.38.0.ts
Normal file
327
src/types/types-1.38.0.ts
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
export interface VaultExplorerPluginSettings_1_38_0 {
|
||||
properties: {
|
||||
favorite: string;
|
||||
url: string;
|
||||
image: string;
|
||||
createdDate: string;
|
||||
modifiedDate: string;
|
||||
custom1: string;
|
||||
custom2: string;
|
||||
custom3: string;
|
||||
};
|
||||
filters: {
|
||||
search: TSearchFilter;
|
||||
favorites: TFavoritesFilter;
|
||||
sort: TSortFilter;
|
||||
timestamp: TTimestampFilter;
|
||||
custom: TCustomFilter;
|
||||
};
|
||||
views: {
|
||||
dashboard: TDashboardView;
|
||||
grid: TGridView;
|
||||
list: TListView;
|
||||
table: TTableView;
|
||||
feed: TFeedView;
|
||||
recommended: TRecommendedView;
|
||||
related: TRelatedView;
|
||||
};
|
||||
titleWrapping: WordBreak;
|
||||
enableClockUpdates: boolean;
|
||||
enableFileIcons: boolean;
|
||||
loadBodyTags: boolean;
|
||||
currentView: TExplorerView | null;
|
||||
pageSize: number;
|
||||
filterGroupsWidth: string;
|
||||
shouldWrapFilterGroups: boolean;
|
||||
viewOrder: TExplorerView[];
|
||||
configDir: string;
|
||||
pluginVersion: string | null;
|
||||
logLevel: string;
|
||||
}
|
||||
|
||||
type FileInteractionStyle = "title" | "content";
|
||||
|
||||
interface BaseView {
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
interface TTableView extends BaseView {}
|
||||
|
||||
interface TListView extends BaseView {
|
||||
showTags: boolean;
|
||||
}
|
||||
|
||||
interface TGridView extends BaseView {
|
||||
coverImageSources: CoverImageSource[];
|
||||
loadSocialMediaImage: boolean;
|
||||
}
|
||||
|
||||
interface CoverImageSource {
|
||||
type: CoverImageSourceType;
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
type CoverImageSourceType =
|
||||
| "image-property"
|
||||
| "url-property"
|
||||
| "frontmatter"
|
||||
| "body";
|
||||
|
||||
interface TDashboardView extends BaseView {}
|
||||
|
||||
type CollapseStyle = "no-new-lines" | "no-extra-new-lines";
|
||||
|
||||
interface TFeedView extends BaseView {
|
||||
collapseStyle: CollapseStyle;
|
||||
removeH1: boolean;
|
||||
lineClampSmall: number;
|
||||
lineClampMedium: number;
|
||||
lineClampLarge: number;
|
||||
}
|
||||
|
||||
interface TRecommendedView extends BaseView {}
|
||||
|
||||
interface TRelatedView extends BaseView {}
|
||||
|
||||
interface BaseFilter {
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
interface TSearchFilter extends BaseFilter {
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface TFavoritesFilter extends BaseFilter {
|
||||
value: boolean;
|
||||
}
|
||||
|
||||
interface TSortFilter extends BaseFilter {
|
||||
value: SortFilterOption;
|
||||
}
|
||||
|
||||
interface TTimestampFilter extends BaseFilter {
|
||||
value: TimestampFilterOption;
|
||||
}
|
||||
|
||||
interface TCustomFilter extends BaseFilter {
|
||||
selectedGroupId: string;
|
||||
groups: TFilterGroup[];
|
||||
}
|
||||
|
||||
type TimestampFilterOption =
|
||||
| "created-today"
|
||||
| "modified-today"
|
||||
| "created-this-week"
|
||||
| "modified-this-week"
|
||||
| "created-2-weeks"
|
||||
| "modified-2-weeks"
|
||||
| "all";
|
||||
|
||||
type SortFilterOption =
|
||||
| "file-name-asc"
|
||||
| "file-name-desc"
|
||||
| "modified-asc"
|
||||
| "modified-desc"
|
||||
| "random";
|
||||
|
||||
type WordBreak = "normal" | "break-word";
|
||||
|
||||
enum TExplorerView {
|
||||
DASHBOARD = "dashboard",
|
||||
GRID = "grid",
|
||||
LIST = "list",
|
||||
FEED = "feed",
|
||||
TABLE = "table",
|
||||
RECOMMENDED = "recommended",
|
||||
RELATED = "related",
|
||||
}
|
||||
|
||||
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",
|
||||
IS_ON_OR_BEFORE = "is-on-or-before",
|
||||
IS_ON_OR_AFTER = "is-on-or-after",
|
||||
EXISTS = "exists",
|
||||
DOES_NOT_EXIST = "does-not-exist",
|
||||
}
|
||||
|
||||
enum ContentFilterCondition {
|
||||
CONTAINS = "contains",
|
||||
DOES_NOT_CONTAIN = "does-not-contain",
|
||||
IS_EMPTY = "is-empty",
|
||||
IS_NOT_EMPTY = "is-not-empty",
|
||||
}
|
||||
|
||||
enum FolderFilterCondition {
|
||||
IS = "is",
|
||||
IS_NOT = "is-not",
|
||||
}
|
||||
|
||||
enum FileNameFilterCondition {
|
||||
IS = "is",
|
||||
IS_NOT = "is-not",
|
||||
CONTAINS = "contains",
|
||||
DOES_NOT_CONTAIN = "does-not-contain",
|
||||
STARTS_WITH = "starts-with",
|
||||
ENDS_WITH = "ends-with",
|
||||
}
|
||||
|
||||
type FilterCondition =
|
||||
| TextFilterCondition
|
||||
| NumberFilterCondition
|
||||
| DateFilterCondition
|
||||
| CheckboxFilterCondition
|
||||
| ListFilterCondition
|
||||
| ContentFilterCondition
|
||||
| FolderFilterCondition
|
||||
| FileNameFilterCondition;
|
||||
|
||||
//This matches the Obsidian property types
|
||||
enum PropertyType {
|
||||
TEXT = "text",
|
||||
NUMBER = "number",
|
||||
LIST = "list",
|
||||
CHECKBOX = "checkbox",
|
||||
DATE = "date",
|
||||
DATETIME = "datetime",
|
||||
}
|
||||
|
||||
enum FilterRuleType {
|
||||
PROPERTY = "property",
|
||||
FOLDER = "folder",
|
||||
FILE_NAME = "file-name",
|
||||
CONTENT = "content",
|
||||
}
|
||||
|
||||
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;
|
||||
condition: FilterCondition;
|
||||
isEnabled: boolean;
|
||||
value: string;
|
||||
matchWhenPropertyDNE: boolean;
|
||||
}
|
||||
|
||||
interface TextPropertyFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.PROPERTY;
|
||||
propertyType: PropertyType.TEXT;
|
||||
propertyName: string;
|
||||
condition: TextFilterCondition;
|
||||
}
|
||||
|
||||
interface NumberPropertyFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.PROPERTY;
|
||||
propertyType: PropertyType.NUMBER;
|
||||
propertyName: string;
|
||||
condition: NumberFilterCondition;
|
||||
}
|
||||
|
||||
interface ListPropertyFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.PROPERTY;
|
||||
propertyType: PropertyType.LIST;
|
||||
propertyName: string;
|
||||
condition: ListFilterCondition;
|
||||
}
|
||||
|
||||
interface CheckboxPropertyFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.PROPERTY;
|
||||
propertyType: PropertyType.CHECKBOX;
|
||||
propertyName: string;
|
||||
condition: CheckboxFilterCondition;
|
||||
}
|
||||
|
||||
interface DatePropertyFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.PROPERTY;
|
||||
propertyType: PropertyType.DATE | PropertyType.DATETIME;
|
||||
propertyName: string;
|
||||
condition: DateFilterCondition;
|
||||
valueData: string;
|
||||
}
|
||||
|
||||
interface FolderFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.FOLDER;
|
||||
condition: FolderFilterCondition;
|
||||
includeSubfolders: boolean;
|
||||
}
|
||||
|
||||
interface FileNameFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.FILE_NAME;
|
||||
condition: FileNameFilterCondition;
|
||||
}
|
||||
|
||||
interface ContentFilterRule extends BaseFilterRule {
|
||||
type: FilterRuleType.CONTENT;
|
||||
condition: ContentFilterCondition;
|
||||
}
|
||||
|
||||
type TFilterRule =
|
||||
| PropertyFilterRule
|
||||
| FolderFilterRule
|
||||
| FileNameFilterRule
|
||||
| ContentFilterRule;
|
||||
|
||||
type PropertyFilterRule =
|
||||
| TextPropertyFilterRule
|
||||
| NumberPropertyFilterRule
|
||||
| ListPropertyFilterRule
|
||||
| CheckboxPropertyFilterRule
|
||||
| DatePropertyFilterRule;
|
||||
|
||||
interface TFilterGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
rules: TFilterRule[];
|
||||
isEnabled: boolean;
|
||||
isSticky: boolean;
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
"showTags": true
|
||||
},
|
||||
"table": {
|
||||
"isEnabled": false
|
||||
"isEnabled": true
|
||||
},
|
||||
"feed": {
|
||||
"isEnabled": true,
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
"isEnabled": false
|
||||
}
|
||||
},
|
||||
"currentView": "grid",
|
||||
"currentView": "table",
|
||||
"titleWrapping": "normal",
|
||||
"enableClockUpdates": true,
|
||||
"enableFileIcons": true,
|
||||
|
|
@ -106,9 +106,10 @@
|
|||
"viewOrder": [
|
||||
"grid",
|
||||
"list",
|
||||
"table",
|
||||
"feed"
|
||||
],
|
||||
"configDir": ".vaultexplorer",
|
||||
"pluginVersion": "1.38.0",
|
||||
"pluginVersion": "1.39.0",
|
||||
"logLevel": "trace"
|
||||
}
|
||||
|
|
@ -130,5 +130,6 @@
|
|||
"1.37.0": "1.4.13",
|
||||
"1.37.1": "1.4.13",
|
||||
"1.37.2": "1.4.13",
|
||||
"1.38.0": "1.4.13"
|
||||
"1.38.0": "1.4.13",
|
||||
"1.39.0": "1.4.13"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue