Skip to content

Commit

Permalink
Merge branch 'footer-menu'
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelGB committed Dec 7, 2022
2 parents 80d0435 + 6276930 commit 29f55a0
Show file tree
Hide file tree
Showing 26 changed files with 586 additions and 242 deletions.
13 changes: 13 additions & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 3.0.1
### Shiny new things
- (experimental) new options for the footer including a menu to select those options:
- Percentage of empty cells
- Percentage of cells with a value
- Count of empty cells
- Count of cells with a value
- Count of unique values
- Formula
- Sum of number columns
### No longer broken
- message when dv is not loaded not spammed anymore [ISSUE#642](https://github.com/RafaelGB/obsidian-db-folder/issues/642)
- Correct tooltrip for export button [ISSUE#641](https://github.com/RafaelGB/obsidian-db-folder/issues/641)
## 3.0.0
### Shiny new things
- A new design for the plugin [ISSUE#577](https://github.com/RafaelGB/obsidian-db-folder/issues/577)
Expand Down
2 changes: 1 addition & 1 deletion manifest-beta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "dbfolder",
"name": "DB Folder",
"version": "3.0.0",
"version": "3.0.1",
"minAppVersion": "0.16.3",
"description": "Folder with the capability to store and retrieve data from a folder like database",
"author": "RafaelGB",
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "dbfolder",
"name": "DB Folder",
"version": "3.0.0",
"version": "3.0.1",
"minAppVersion": "0.16.3",
"description": "Folder with the capability to store and retrieve data from a folder like database",
"author": "RafaelGB",
Expand Down
342 changes: 171 additions & 171 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-dbfolder",
"version": "3.0.0",
"version": "3.0.1",
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
"main": "main.js",
"scripts": {
Expand All @@ -23,25 +23,25 @@
"@rollup/plugin-json": "5.0.2",
"@rollup/plugin-node-resolve": "15.0.1",
"@rollup/plugin-replace": "5.0.1",
"@rollup/plugin-typescript": "10.0.0",
"@rollup/plugin-typescript": "10.0.1",
"@rollup/plugin-terser": "0.1.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "13.4.0",
"@types/jest": "29.2.3",
"@types/jest": "29.2.4",
"@types/luxon": "3.1.0",
"@types/node": "18.11.9",
"@types/react": "18.0.25",
"@types/node": "18.11.11",
"@types/react": "18.0.26",
"@types/react-csv": "1.1.3",
"@types/react-datepicker": "4.8.0",
"@types/react-dom": "18.0.9",
"@types/react-window": "1.8.5",
"@typescript-eslint/eslint-plugin": "5.45.0",
"@typescript-eslint/parser": "5.45.0",
"eslint": "8.28.0",
"@typescript-eslint/eslint-plugin": "5.45.1",
"@typescript-eslint/parser": "5.45.1",
"eslint": "8.29.0",
"jest": "29.3.1",
"jest-mock-extended": "3.0.1",
"obsidian": "0.16.3",
"rollup": "3.5.0",
"rollup": "3.6.0",
"rollup-plugin-typescript2": "0.34.1",
"ts-jest": "29.0.3",
"tslib": "2.4.1",
Expand All @@ -50,7 +50,7 @@
"dependencies": {
"@emotion/styled": "11.10.5",
"@mui/icons-material": "5.10.16",
"@mui/material": "5.10.16",
"@mui/material": "5.10.17",
"@popperjs/core": "2.11.6",
"@tanstack/match-sorter-utils": "8.7.0",
"@tanstack/react-table": "8.7.0",
Expand All @@ -64,8 +64,8 @@
"react-csv": "2.2.2",
"react-datepicker": "4.8.0",
"react-dom": "18.2.0",
"react-select": "5.6.1",
"react-select": "5.7.0",
"react-window": "1.8.8",
"zustand": "4.1.4"
"zustand": "4.1.5"
}
}
14 changes: 14 additions & 0 deletions src/DatabaseView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ import {
WorkspaceLeaf,
TFile,
Menu,
Notice,
} from "obsidian";
import { createRoot, Root } from "react-dom/client";
import DatabaseInfo from "services/DatabaseInfo";
import { DataviewService } from "services/DataviewService";
import { LOGGER } from "services/Logger";
import { SettingsModal } from "Settings";
import StateManager from "StateManager";
Expand Down Expand Up @@ -145,6 +147,7 @@ export class DatabaseView extends TextFileView implements HoverParent {
async initDatabase(): Promise<void> {
try {
LOGGER.info(`=>initDatabase ${this.file.path}`);
this.checkRequiredLibraries();
// Load the database file
this.diskConfig = new DatabaseInfo(this.file);
await this.diskConfig.initDatabaseconfigYaml(
Expand Down Expand Up @@ -347,4 +350,15 @@ export class DatabaseView extends TextFileView implements HoverParent {
openFilters() {
this.emitter.emit(EMITTERS_GROUPS.SHORTCUT, EMITTERS_SHORTCUT.OPEN_FILTERS);
}
/****************************************************************
* VIEW VALIDATIONS
* **************************************************************/
private checkRequiredLibraries(): void {
if (!DataviewService.indexIsLoaded) {
new Notice(
`Dataview plugin is not loaded yet. Please wait a few seconds and refresh the page.`,
1000
);
}
}
}
83 changes: 82 additions & 1 deletion src/automations/Footer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,92 @@
import { Row } from "@tanstack/react-table";
import { RowDataType } from "cdm/FolderModel";
import { FooterType } from "helpers/Constants";

export default class Footer {
constructor(public readonly rows: Row<RowDataType>[]) { }

public dispatch(footerType: string, key: string): string {
let footerInfo: string;
try {
switch (footerType) {
case FooterType.COUNT_UNIQUE:
footerInfo = this.countUnique(key);
break;
case FooterType.COUNT_EMPTY:
footerInfo = this.countEmpty(key);
break;
case FooterType.PERCENT_EMPTY:
footerInfo = this.percentEmpty(key);
break;
case FooterType.COUNT_FILLED:
footerInfo = this.countFilled(key);
break;
case FooterType.PERCENT_FILLED:
footerInfo = this.percentFilled(key);
break;
case FooterType.SUM:
footerInfo = this.sum(key);
break;
case FooterType.MIN:
footerInfo = this.min(key);
break;
case FooterType.MAX:
footerInfo = this.max(key);
break;
case FooterType.NONE:
default:
footerInfo = "";
}
} catch (e) {
footerInfo = `Error: ${e.message}`;
} finally {
return footerInfo;
}
}

public sum(key: string): string {
const total = this.rows.reduce((acc, row) => acc + row.getValue<number>(key), 0);
const total = this.rows.reduce((acc, row) => acc + Number(row.getValue<number>(key)), 0);
return `Total: ${total}`;
}

public min(key: string): string {
const min = this.rows.reduce((acc, row) => Math.min(acc, row.getValue<number>(key)), Number.MAX_SAFE_INTEGER);
return `Min: ${min}`;
}

public max(key: string): string {
const max = this.rows.reduce((acc, row) => Math.max(acc, row.getValue<number>(key)), Number.MIN_SAFE_INTEGER);
return `Max: ${max}`;
}

public countUnique(key: string): string {
const uniqueValues = new Set();
this.rows
.filter((row) => row.getValue(key) !== undefined)
.forEach((row) => {
uniqueValues.add(row.getValue(key));
});
return `Unique: ${uniqueValues.size}`;
}

public countEmpty(key: string): string {
const empty = this.rows.filter((row) => !row.getValue(key)).length;
return `Empty: ${empty}`;
}

public percentEmpty(key: string): string {
const empty = this.rows.filter((row) => !row.getValue(key)).length;
return `Empty: ${(empty / this.rows.length * 100).toFixed(2)}%`;
}

public countFilled(key: string): string {
const filled = this.rows.filter((row) => row.getValue(key)).length;
return `Filled: ${filled}`;
}

public percentFilled(key: string): string {
const filled = this.rows.filter((row) => row.getValue(key)).length;
return `Filled: ${(filled / this.rows.length * 100).toFixed(2)}%`;
}

}
3 changes: 3 additions & 0 deletions src/cdm/FolderModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export interface ConfigColumn {
rollup_action?: string;
rollup_key?: string;
persist_rollup?: boolean;
// Footer
footer_type: string;
footer_formula?: string;
/** Extras from yaml */
[key: string]: Literal;
}
Expand Down
6 changes: 4 additions & 2 deletions src/cdm/TableStateInterface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SortingState } from "@tanstack/react-table";
import { Row, SortingState } from "@tanstack/react-table";
import { ConfigColumn, RowDataType, TableColumn } from "cdm/FolderModel";
import { FilterSettings, GlobalSettings, LocalSettings } from "cdm/SettingsModel";
import { DatabaseView } from "DatabaseView";
Expand Down Expand Up @@ -74,6 +74,7 @@ export interface ColumnsState {
alterColumnLabel: (column: TableColumn, label: string) => Promise<void>;
alterColumnSize: (id: string, width: number) => void;
alterIsHidden: (column: TableColumn, isHidden: boolean) => void;
alterColumnConfig: (column: TableColumn, config: Partial<ConfigColumn>) => void;
}
info: {
getAllColumns: () => TableColumn[];
Expand All @@ -100,7 +101,8 @@ export interface AutomationState {
info: {
getFormula: (name: string) => unknown;
runFormula: (input: string, row: RowDataType, dbbConfig: LocalSettings) => Literal;
dispatchRollup: (configColumn: ConfigColumn, relation: Literal, dbbConfig: LocalSettings) => Literal;
dispatchFooter: (column: TableColumn, rows: Row<RowDataType>[]) => Literal;
dispatchRollup: (configColumn: ConfigColumn, relation: Literal, ddbbConfig: LocalSettings) => Literal;
},
actions: {
loadFormulas: (ddbbConfig: LocalSettings) => Promise<void>;
Expand Down
60 changes: 41 additions & 19 deletions src/components/DefaultFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
import Footer from "automations/Footer";
import { DatabaseHeaderProps, TableColumn } from "cdm/FolderModel";
import { InputType } from "helpers/Constants";
import { c, getAlignmentClassname } from "helpers/StylesHelper";
import React from "react";
import { COLUMN_ALIGNMENT_OPTIONS, FooterType } from "helpers/Constants";
import { c } from "helpers/StylesHelper";
import React, { MouseEventHandler, useState } from "react";
import { showFooterMenu } from "components/obsidianArq/commands";
import { Literal } from "obsidian-dataview";

export default function DefaultFooter(headerProps: DatabaseHeaderProps) {
/** Properties of footer */
const { header, table } = headerProps;
const { tableState } = table.options.meta;
const configInfo = tableState.configState((state) => state.info);
const columnActions = tableState.columns((state) => state.actions);

/** Column values */
const { input, config } = header.column.columnDef as TableColumn;
let footerInfo: string;
switch (input) {
case InputType.NUMBER:
footerInfo = new Footer(table.getRowModel().rows).sum(header.id);
break;
default:
return null;
// Do nothing
const tableColumn = header.column.columnDef as TableColumn;
const formulaInfo = tableState.automations((state) => state.info);
const [footerType, setFooterValue] = useState(tableColumn.config.footer_type);
const { config } = tableColumn;
let footerInfo: Literal = "";
if (config.footer_type === FooterType.FORMULA) {
footerInfo = formulaInfo.dispatchFooter(
tableColumn,
table.getRowModel().rows
);
} else {
footerInfo = new Footer(table.getRowModel().rows).dispatch(
footerType,
header.id
);
}
const handlerFooterOptions: MouseEventHandler<HTMLDivElement> = async (
event: React.MouseEvent
) => {
await showFooterMenu(
event.nativeEvent,
tableColumn,
columnActions,
footerType,
setFooterValue
);
};

return (
<span
key={`foot-th-cell-${header.id}`}
className={c(
getAlignmentClassname(config, configInfo.getLocalSettings())
)}
<div
key={`default-footer-${header.id}`}
onClick={handlerFooterOptions}
style={{
minHeight: "20px",
}}
>
{footerInfo}
</span>
{footerInfo?.toString()}
</div>
);
}
4 changes: 2 additions & 2 deletions src/components/TableFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { c } from "helpers/StylesHelper";
import React from "react";

export default function TableFooter(tableFooterProps: TableFooterProps) {
const { table, header, headerIndex } = tableFooterProps;
const { header, headerIndex } = tableFooterProps;
return (
<div key={`foot-th-${headerIndex}`} className={c("th footer")}>
<div key={`table-footer-${headerIndex}`} className={c("th footer")}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.footer, header.getContext())}
Expand Down
2 changes: 1 addition & 1 deletion src/components/index/Database.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function Database(tableProps: TableDataType) {
return (
<StrictMode>
{/** TRY CATCH REACT ERROR */}
<DbErrorBoundary>
<DbErrorBoundary key={"db-error-boundary"}>
<Table {...tableProps} tableStore={tableStore} />
</DbErrorBoundary>
</StrictMode>
Expand Down
5 changes: 3 additions & 2 deletions src/components/modals/PromptModal.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { c } from "helpers/StylesHelper";
import {
Modal,
TextComponent,
Expand Down Expand Up @@ -30,11 +31,11 @@ export class PromptModal extends Modal {

createForm(): void {
const div = this.contentEl.createDiv();
div.addClass("templater-prompt-div");
div.addClass(c("prompt-modal"));
let textInput;
textInput = new TextComponent(div);
this.value = this.default_value ?? "";
textInput.inputEl.addClass("templater-prompt-input");
textInput.inputEl.addClass(c("prompt-input"));
textInput.setPlaceholder("Type text here");
textInput.setValue(this.value);
textInput.onChange((value) => (this.value = value));
Expand Down
Loading

0 comments on commit 29f55a0

Please sign in to comment.