Skip to content

Commit

Permalink
Merge branch '442-fr-edit-nested-metadata'
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelGB committed Oct 6, 2022
2 parents e6af88f + 14e9228 commit a08f251
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 195 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@
"dependencies": {
"@emotion/styled": "11.10.4",
"@mui/icons-material": "5.10.6",
"@mui/material": "5.10.6",
"@mui/material": "5.10.8",
"@popperjs/core": "2.11.6",
"@tanstack/match-sorter-utils": "8.1.1",
"@tanstack/react-table": "8.5.13",
"@tanstack/match-sorter-utils": "8.5.14",
"@tanstack/react-table": "8.5.15",
"eventemitter3": "4.0.7",
"fuse.js": "6.6.2",
"luxon": "3.0.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { resolve_tfolder } from "helpers/FileManagement";
import { generateDataviewTableQuery } from "helpers/QueryHelper";
import { Modal, Notice, Setting } from "obsidian";
import { DataviewService } from "services/DataviewService";
import { ParseService } from "services/ParseService";
import { add_dropdown, add_setting_header } from "settings/SettingsComponents";
import { FileSuggest } from "settings/suggesters/FileSuggester";
import { FolderSuggest } from "settings/suggesters/FolderSuggester";
Expand Down Expand Up @@ -246,7 +247,7 @@ export class DatabaseHelperCreationModalManager {
}

parseValueToThuthyYaml(value: string): string {
return DataviewService.parseLiteral(
return ParseService.parseLiteral(
value,
InputType.MARKDOWN,
this.databaseHelperCreationModal.local_settings
Expand Down
33 changes: 30 additions & 3 deletions src/components/cellTypes/TextCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { renderMarkdown } from "components/obsidianArq/MarkdownRenderer";
import React, { MouseEventHandler, useEffect, useRef } from "react";
import { useState } from "react";
import EditorCell from "components/cellTypes/EditorCell";
import { TableColumn } from "cdm/FolderModel";
import { RowDataType, TableColumn } from "cdm/FolderModel";
import { c, getAlignmentClassname } from "helpers/StylesHelper";
import { Literal } from "obsidian-dataview";

const TextCell = (props: CellComponentProps) => {
const { defaultCell } = props;
Expand All @@ -25,7 +26,7 @@ const TextCell = (props: CellComponentProps) => {
(state) => state.actions
);

const textCell = textRow[column.id]?.toString();
const textCell = parseTextRowToString(textRow, column.id);
/** Ref to cell container */
const containerCellRef = useRef<HTMLDivElement>();
const [dirtyCell, setDirtyCell] = useState(false);
Expand All @@ -51,10 +52,11 @@ const TextCell = (props: CellComponentProps) => {

const persistChange = (changedValue: string) => {
if (changedValue !== undefined && changedValue !== textCell) {
const newCell = parseStringToTextRow(textRow, column.id, changedValue);
dataActions.updateCell(
row.index,
tableColumn,
changedValue.trim(),
newCell,
columnsInfo.getAllColumns(),
configInfo.getLocalSettings()
);
Expand All @@ -80,4 +82,29 @@ const TextCell = (props: CellComponentProps) => {
);
};

function parseTextRowToString(row: RowDataType, columnId: string) {
const cellRoot = row[columnId];
let textCell = "";
if (typeof cellRoot === "object") {
textCell = JSON.stringify(cellRoot);
} else {
textCell = cellRoot?.toString();
}
return textCell;
}

function parseStringToTextRow(
row: RowDataType,
columnId: string,
newValue: string
): Literal {
const cellRoot = row[columnId];
if (typeof cellRoot === "object") {
// TODO control anidated values in function of columnId spliting by "."
return JSON.parse(newValue);
} else {
return newValue.trim();
}
}

export default TextCell;
6 changes: 3 additions & 3 deletions src/components/reducers/CustomSortingFn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RowDataType } from "cdm/FolderModel";
import { LocalSettings } from "cdm/SettingsModel";
import { InputType } from "helpers/Constants";
import { Literal } from "obsidian-dataview";
import { DataviewService } from "services/DataviewService";
import { ParseService } from "services/ParseService";

const dbfolderColumnSortingFn: (
ddbbConfig: LocalSettings
Expand All @@ -14,15 +14,15 @@ const dbfolderColumnSortingFn: (
rowB: Row<RowDataType>,
columnId: string
): number => {
const a = DataviewService.parseLiteral(
const a = ParseService.parseLiteral(
rowA.getValue<Literal>(columnId),
InputType.MARKDOWN,
ddbbConfig,
true
)
.toString()
.toLowerCase();
const b = DataviewService.parseLiteral(
const b = ParseService.parseLiteral(
rowB.getValue<Literal>(columnId),
InputType.MARKDOWN,
ddbbConfig,
Expand Down
4 changes: 2 additions & 2 deletions src/components/reducers/TableFilterFlavours.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RowDataType } from "cdm/FolderModel"
import { LocalSettings } from "cdm/SettingsModel";
import { InputType } from "helpers/Constants";
import { Literal } from "obsidian-dataview";
import { DataviewService } from "services/DataviewService";
import { ParseService } from "services/ParseService";

export const globalDatabaseFilterFn: (ddbbConfig: LocalSettings) => FilterFn<RowDataType> = (ddbbConfig: LocalSettings) => (
row: Row<RowDataType>,
Expand All @@ -14,7 +14,7 @@ export const globalDatabaseFilterFn: (ddbbConfig: LocalSettings) => FilterFn<Row
if (value === undefined) {
return false;
}
const sanitized = DataviewService.parseLiteral(value, InputType.MARKDOWN, ddbbConfig, true).toString().toLowerCase();
const sanitized = ParseService.parseLiteral(value, InputType.MARKDOWN, ddbbConfig, true).toString().toLowerCase();
filterValue = filterValue.toLowerCase();
return sanitized.includes(filterValue) || searchRegex(sanitized, filterValue);
}
Expand Down
4 changes: 2 additions & 2 deletions src/helpers/TableFiltersHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AtomicFilter, FilterGroup, FilterGroupCondition, LocalSettings } from "cdm/SettingsModel";
import { Literal } from "obsidian-dataview";
import { ConditionFiltersOptions, getOperatorFilterValue, InputType, OperatorFilter } from "helpers/Constants";
import { DataviewService } from "services/DataviewService";
import { ParseService } from "services/ParseService";

export default function tableFilter(dbFilters: FilterGroup[], p: Record<string, Literal>, ddbbConfig: LocalSettings): boolean {
if (!dbFilters || dbFilters.length === 0) return true;
Expand Down Expand Up @@ -34,7 +34,7 @@ function validateFilter(p: Record<string, Literal>, filter: FilterGroup, ddbbCon
}
return groupResult;
}
const filterableValue = DataviewService.parseLiteral(p[(filter as AtomicFilter).field], InputType.MARKDOWN, ddbbConfig);
const filterableValue = ParseService.parseLiteral(p[(filter as AtomicFilter).field], InputType.MARKDOWN, ddbbConfig);
// Atomic filter
const operator = (filter as AtomicFilter).operator;
const value = (filter as AtomicFilter).value;
Expand Down
9 changes: 5 additions & 4 deletions src/parsers/RowDatabaseFieldsToFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InputType } from "helpers/Constants";
import { Literal } from "obsidian-dataview";
import { DateTime } from "luxon";
import { DataviewService } from "services/DataviewService";
import { ParseService } from "services/ParseService";
export const parseFrontmatterFieldsToString = (databaseFields: RowDatabaseFields, localSettings: LocalSettings, deletedColumn?: string): string => {
const frontmatterFields = databaseFields.frontmatter;
let array: string[] = [];
Expand All @@ -27,7 +28,7 @@ export const parseInlineFieldsToString = (inlineFields: RowDatabaseFields): stri
}

export function parseValuetoSanitizeYamlValue(value: string, localSettings: LocalSettings): string {
return DataviewService.parseLiteral(value, InputType.MARKDOWN, localSettings).toString();
return ParseService.parseLiteral(value, InputType.MARKDOWN, localSettings).toString();
}

function stringifyDbYaml(literal: Literal, level: number, localSettings: LocalSettings, key?: string): string[] {
Expand All @@ -42,7 +43,7 @@ function stringifyDbYaml(literal: Literal, level: number, localSettings: LocalSe
}
// Manage Dates
else if (DateTime.isDateTime(literal)) {
literalBlock.push(`${" ".repeat(level)}${key}: ${DataviewService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
literalBlock.push(`${" ".repeat(level)}${key}: ${ParseService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
}
// Manage Objects
else if (DataviewService.getDataviewAPI().value.isObject(literal)) {
Expand All @@ -55,9 +56,9 @@ function stringifyDbYaml(literal: Literal, level: number, localSettings: LocalSe
}
// Manage atomic values
else if (key) {
literalBlock.push(`${" ".repeat(level)}${key}: ${DataviewService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
literalBlock.push(`${" ".repeat(level)}${key}: ${ParseService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
} else {
literalBlock.push(`${" ".repeat(level)}- ${DataviewService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
literalBlock.push(`${" ".repeat(level)}- ${ParseService.parseLiteral(literal, InputType.MARKDOWN, localSettings)}`);
}
return literalBlock;
}
168 changes: 0 additions & 168 deletions src/services/DataviewService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { InputType, MarkdownBreakerRules } from "helpers/Constants";
import { Notice } from "obsidian";
import { DataviewApi, getAPI, isPluginEnabled } from "obsidian-dataview";
import { Literal, WrappedLiteral } from "obsidian-dataview/lib/data-model/value";
import { DateTime } from "luxon";
import { LOGGER } from "services/Logger";
import { LocalSettings } from "cdm/SettingsModel";
class DataviewProxy {

private static instance: DataviewProxy;
Expand All @@ -30,52 +26,6 @@ class DataviewProxy {
return this.getDataviewAPI().value.isTruthy(literal?.toString());
}

parseLiteral(literal: Literal, dataTypeDst: string, localSettings: LocalSettings, isInline?: boolean): Literal {
let parsedLiteral: Literal = literal;
if (!this.isTruthy(literal?.toString())) {
return "";
}
literal = this.parseDataArray(literal);
const wrapped = this.wrapLiteral(literal);
LOGGER.debug(`=>parseLiteral: type ${wrapped
.type} to ${dataTypeDst}`);
// Check empty or undefined literals
switch (dataTypeDst) {
case InputType.TEXT:
parsedLiteral = this.parseToString(wrapped);
break;
case InputType.MARKDOWN:
parsedLiteral = this.parseToMarkdown(wrapped, localSettings, isInline);
break;
case InputType.TAGS:
parsedLiteral = this.parseToOptionsArray(wrapped);
break;
case InputType.CALENDAR:
parsedLiteral = this.parseToCalendar(wrapped, localSettings.date_format);
break;
case InputType.CALENDAR_TIME:
parsedLiteral = this.parseToCalendar(wrapped, localSettings.datetime_format);
break;
case InputType.METATADA_TIME:
parsedLiteral = this.parseToCalendar(wrapped);
break;
case InputType.NUMBER:
parsedLiteral = this.parseToNumber(wrapped);
break;
case InputType.CHECKBOX:
parsedLiteral = this.parseToBoolean(wrapped);
break;
case InputType.TASK:
case InputType.FORMULA:
// Do nothing
break;
default:
parsedLiteral = parsedLiteral = this.parseToString(wrapped);

}
LOGGER.debug(`<=parseLiteral`);
return parsedLiteral;
}
/**
* Check if literal is Proxy DataArray, if so, parse it. If not, return same literal
* @param literal
Expand All @@ -97,124 +47,6 @@ class DataviewProxy {
}
return this.instance;
}

private parseToCalendar(wrapped: WrappedLiteral, format?: string): DateTime {
if (wrapped.type === 'string') {
let calendarCandidate;
if (format) {
calendarCandidate = DateTime.fromFormat(wrapped.value, format);
} else {
calendarCandidate = DateTime.fromISO(wrapped.value);
}

if (calendarCandidate.isValid) {
return calendarCandidate;
}
return null;
}

if (DateTime.isDateTime(wrapped.value)) {
return wrapped.value;
} else {
return null;
}
}

private parseToString(wrapped: WrappedLiteral): string {
if (DateTime.isDateTime(wrapped.value)) {
LOGGER.debug("adapting DateTime to string...");
// Values of dataview parse to md friendly strings
return wrapped.value.toFormat("yyyy-MM-dd");
} else {
return this.getDataviewAPI().value.toString(wrapped.value);
}
}

private parseToNumber(wrapped: WrappedLiteral): number {
if (wrapped.type === 'number') {
return wrapped.value;
} else {
const adjustedValue = this.getDataviewAPI().value.toString(wrapped.value);
return Number(adjustedValue);
}
}

private parseToBoolean(wrapped: WrappedLiteral): string {
if (wrapped.type === 'boolean') {
return wrapped.value ? 'true' : 'false';
} else {
const adjustedValue = this.getDataviewAPI().value.toString(wrapped.value);
return adjustedValue === 'true' ? "true" : "false";
}
}

private parseToMarkdown(wrapped: WrappedLiteral, localSettings: LocalSettings, isInline: boolean): string {
let auxMarkdown = '';
switch (wrapped.type) {
case 'boolean':
case 'number':
// Do nothing
auxMarkdown = wrapped.value.toString();
break;
case 'array':
auxMarkdown = wrapped.value
.map(v => this.parseToMarkdown(this.getDataviewAPI().value.wrapValue(v), localSettings, isInline))
.join(', ');
break;

case 'date':
if (wrapped.value.hour === 0 && wrapped.value.minute === 0 && wrapped.value.second === 0) {
// Parse date
auxMarkdown = wrapped.value.toFormat(localSettings.date_format);
} else {
// Parse datetime
auxMarkdown = wrapped.value.toFormat(localSettings.datetime_format);
auxMarkdown = this.handleMarkdownBreaker(auxMarkdown, localSettings, isInline);
}
break;
case 'object':
if (DateTime.isDateTime(wrapped.value)) {
return this.parseToMarkdown({ type: 'date', value: wrapped.value }, localSettings, isInline);
}
// Else go to default
default:
auxMarkdown = this.parseToString(wrapped) as string;
// Check possible markdown breakers
auxMarkdown = this.handleMarkdownBreaker(auxMarkdown, localSettings, isInline);
}
return auxMarkdown;
}

private parseToOptionsArray(wrapped: WrappedLiteral): Literal {
if (wrapped.type !== 'array') {
return wrapped.value.toString().split(",").map(s => s.trim());
}
return wrapped.value;
}

private handleMarkdownBreaker(value: string, localSettings: LocalSettings, isInline?: boolean): string {
// Do nothing if is inline
if (isInline) {
return value;
}

// Remove a possible already existing quote wrapper
if (value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1);
}

// Check possible markdown breakers of the yaml
if (MarkdownBreakerRules.INIT_CHARS.some(c => value.startsWith(c)) ||
MarkdownBreakerRules.BETWEEN_CHARS.some(rule => value.includes(rule)) ||
MarkdownBreakerRules.UNIQUE_CHARS.some(c => value === c) ||
localSettings.frontmatter_quote_wrap) {
value = value.replaceAll(`\\`, ``);
value = value.replaceAll(`"`, `\\"`);
return `"${value}"`;
}

return value;
}
}

export const DataviewService = DataviewProxy.getInstance();
Loading

0 comments on commit a08f251

Please sign in to comment.