Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 284c76d

Browse files
committed
Merge branch '400-bug-filters-on-mobile-does-not-open-correctly'
2 parents 8dbf129 + 23b604e commit 284c76d

File tree

13 files changed

+296
-203
lines changed

13 files changed

+296
-203
lines changed

src/cdm/ModalsModel.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { TableColumn } from "cdm/FolderModel";
1+
import { RowDataType, TableColumn } from "cdm/FolderModel";
22
import { ColumnsState, ConfigState, DataState } from "cdm/TableStateInterface";
33
import { ColumnSettingsManager } from "components/modals/columnSettings/ColumnSettingsModal";
44
import { AddColumnModalManager } from "components/modals/newColumn/addColumnModal";
55
import { FilterSettings, LocalSettings } from "cdm/SettingsModel";
66
import { HeaderMenuProps } from "cdm/HeaderModel";
77
import { DatabaseView } from "DatabaseView";
8+
import { FiltersModalManager } from "components/modals/filters/FiltersModal";
9+
import { Table } from "@tanstack/react-table";
810

911
/**
1012
* Base class for all modal responses.
@@ -41,4 +43,13 @@ export type AddColumnModalProps = {
4143
*/
4244
export type AddColumnModalHandlerResponse = {
4345
addColumnModalManager: AddColumnModalManager,
44-
} & BaseModalHandlerResponse
46+
} & BaseModalHandlerResponse;
47+
48+
/** Filters Modal */
49+
export type FiltersModalProps = {
50+
table: Table<RowDataType>,
51+
possibleColumns: string[]
52+
}
53+
export type FiltersModalHandlerResponse = {
54+
filtersModalManager: FiltersModalManager
55+
} & BaseModalHandlerResponse;

src/components/DefaultHeader.tsx

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,8 @@ export default function DefaultHeader(headerProps: DatabaseHeaderProps) {
7373
.columnDef as TableColumn;
7474
/** reducer asociated to database */
7575
const [expanded, setExpanded] = useState(created || false);
76-
const [domReady, setDomReady] = useState(false);
7776
const [referenceElement, setReferenceElement] = useState(null);
7877
const [labelState, setLabelState] = useState(label);
79-
React.useEffect(() => {
80-
if (!domReady) {
81-
setDomReady(true);
82-
}
83-
});
8478

8579
let propertyIcon: JSX.Element;
8680
switch (input) {
@@ -165,21 +159,19 @@ export default function DefaultHeader(headerProps: DatabaseHeaderProps) {
165159
</span>
166160
)}
167161
</div>
168-
{domReady
169-
? ReactDOM.createPortal(
170-
<HeaderMenu
171-
headerProps={headerProps}
172-
propertyIcon={propertyIcon}
173-
expanded={expanded}
174-
setExpanded={setExpanded}
175-
created={created}
176-
referenceElement={referenceElement}
177-
labelState={labelState}
178-
setLabelState={setLabelState}
179-
/>,
180-
activeDocument.body
181-
)
182-
: null}
162+
{ReactDOM.createPortal(
163+
<HeaderMenu
164+
headerProps={headerProps}
165+
propertyIcon={propertyIcon}
166+
expanded={expanded}
167+
setExpanded={setExpanded}
168+
created={created}
169+
referenceElement={referenceElement}
170+
labelState={labelState}
171+
setLabelState={setLabelState}
172+
/>,
173+
activeDocument.body
174+
)}
183175
</>
184176
) : (
185177
<div

src/components/HeaderMenu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { InputType, StyleVariables } from "helpers/Constants";
22
import { dbTrim, c, getLabelHeader } from "helpers/StylesHelper";
33
import AdjustmentsIcon from "components/img/AdjustmentsIcon";
4-
import React, { useEffect, useState } from "react";
4+
import React, { FocusEventHandler, useEffect, useState } from "react";
55
import { usePopper } from "react-popper";
66
import header_action_button_section from "components/headerActions/HeaderActionButtonSection";
77
import header_action_types_section from "components/headerActions/HeaderActiontypesSection";
@@ -164,10 +164,10 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
164164
* When user leaves the input field
165165
* @param e
166166
*/
167-
function handleBlur(e: any) {
167+
const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
168168
e.preventDefault();
169169
persistLabelChange();
170-
}
170+
};
171171

172172
return (
173173
<div>

src/components/NavBar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function NavBar(navBarProps: NavBarProps) {
7272
}}
7373
>
7474
<Toolbar>
75-
<Grid container spacing={3}>
75+
<Grid container spacing={1}>
7676
<Grid item xs="auto">
7777
<IconButton
7878
size="large"
@@ -130,7 +130,7 @@ export function NavBar(navBarProps: NavBarProps) {
130130
<Grid item xs="auto">
131131
<DataviewFilters table={table} />
132132
</Grid>
133-
<Grid item xs="auto">
133+
<Grid item xs={5}>
134134
<PaginationTable table={table} />
135135
</Grid>
136136
</Grid>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { FiltersModalHandlerResponse } from "cdm/ModalsModel";
2+
import { AbstractChain } from "patterns/AbstractFactoryChain";
3+
import { AbstractHandler } from "patterns/AbstractHandler";
4+
import { FilterGroupHandler } from "components/modals/filters/handlers/FilterGroupHandler";
5+
import { AddNewFilterHandler } from "components/modals/filters/handlers/AddNewFilterHandler";
6+
7+
class FilterGroupSection extends AbstractChain<FiltersModalHandlerResponse> {
8+
protected getHandlers(): AbstractHandler<FiltersModalHandlerResponse>[] {
9+
return [
10+
new FilterGroupHandler(),
11+
new AddNewFilterHandler()
12+
];
13+
}
14+
}
15+
16+
export const filter_group_section = new FilterGroupSection();
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import {
2+
FiltersModalHandlerResponse,
3+
FiltersModalProps,
4+
} from "cdm/ModalsModel";
5+
import { DatabaseView } from "DatabaseView";
6+
import { StyleClasses } from "helpers/Constants";
7+
import { Modal } from "obsidian";
8+
import { add_setting_header } from "settings/SettingsComponents";
9+
import { filter_group_section } from "components/modals/filters/FilterGroupSection";
10+
11+
export class FiltersModal extends Modal {
12+
addColumnManager: FiltersModalManager;
13+
enableReset: boolean = false;
14+
constructor(props: FiltersModalProps) {
15+
super(app);
16+
this.addColumnManager = new FiltersModalManager(this, props);
17+
}
18+
19+
onOpen() {
20+
const { contentEl } = this;
21+
contentEl.empty();
22+
this.addColumnManager.constructUI(contentEl);
23+
}
24+
25+
onClose() {
26+
const { contentEl } = this;
27+
contentEl.empty();
28+
}
29+
}
30+
31+
export class FiltersModalManager {
32+
modal: FiltersModal;
33+
props: FiltersModalProps;
34+
constructor(filtersModal: FiltersModal, props: FiltersModalProps) {
35+
this.modal = filtersModal;
36+
this.props = props;
37+
}
38+
constructUI(containerEl: HTMLElement) {
39+
/** Common modal headings */
40+
containerEl.addClass(StyleClasses.FILTERS_MODAL);
41+
add_setting_header(containerEl, `Table Filters`, "h2");
42+
43+
const addColumnBody = containerEl.createDiv();
44+
addColumnBody.addClass(StyleClasses.FILTERS_MODAL_BODY);
45+
addColumnBody.setAttribute("id", StyleClasses.FILTERS_MODAL_BODY);
46+
const initialResponse: FiltersModalHandlerResponse = {
47+
containerEl: addColumnBody,
48+
filtersModalManager: this,
49+
};
50+
this.constructBody(initialResponse);
51+
}
52+
53+
constructBody(response: FiltersModalHandlerResponse) {
54+
/** select new column section */
55+
filter_group_section.run(response);
56+
}
57+
58+
reset(response: FiltersModalHandlerResponse) {
59+
const columnElement = activeDocument.getElementById(
60+
StyleClasses.FILTERS_MODAL_BODY
61+
);
62+
// remove all sections
63+
columnElement.empty();
64+
this.constructBody(response);
65+
}
66+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import Button from "@mui/material/Button";
2+
import {
3+
FiltersModalHandlerResponse,
4+
FiltersModalProps,
5+
} from "cdm/ModalsModel";
6+
import { OperatorFilter, StyleVariables } from "helpers/Constants";
7+
import AddIcon from "@mui/icons-material/Add";
8+
import { AbstractHandlerClass } from "patterns/AbstractHandler";
9+
import React from "react";
10+
import { createRoot } from "react-dom/client";
11+
import { Notice } from "obsidian";
12+
13+
export class AddNewFilterHandler extends AbstractHandlerClass<FiltersModalHandlerResponse> {
14+
settingTitle: string = "Add new filter";
15+
handle(
16+
columnHandlerResponse: FiltersModalHandlerResponse
17+
): FiltersModalHandlerResponse {
18+
const { containerEl, filtersModalManager } = columnHandlerResponse;
19+
createRoot(containerEl.createDiv()).render(
20+
<NewFiltersForm {...filtersModalManager.props} />
21+
);
22+
return this.goNext(columnHandlerResponse);
23+
}
24+
}
25+
26+
const NewFiltersForm = (props: FiltersModalProps) => {
27+
const { table, possibleColumns } = props;
28+
const { tableState } = table.options.meta;
29+
const configActions = tableState.configState((state) => state.actions);
30+
const filters = tableState.configState((state) => state.filters);
31+
32+
const addConditionHandler = () => {
33+
// Check if there is a condition to add
34+
if (possibleColumns.length <= 0) {
35+
new Notice(
36+
"No columns available yet. Include a field in one of your notes before add a filter",
37+
3000
38+
);
39+
return;
40+
}
41+
42+
const alteredFilterState = { ...filters };
43+
alteredFilterState.conditions.push({
44+
field: possibleColumns[0],
45+
operator: OperatorFilter.CONTAINS[0],
46+
value: "",
47+
});
48+
configActions.alterFilters(alteredFilterState);
49+
};
50+
51+
return (
52+
<Button
53+
size="small"
54+
key={`Button-Plus-DataviewFilters`}
55+
variant="outlined"
56+
startIcon={<AddIcon />}
57+
style={{
58+
borderColor: StyleVariables.TEXT_NORMAL,
59+
color: StyleVariables.TEXT_NORMAL,
60+
}}
61+
onClick={addConditionHandler}
62+
>
63+
Add filter
64+
</Button>
65+
);
66+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { FiltersModalHandlerResponse } from "cdm/ModalsModel";
2+
import DataviewFiltersPortal from "components/portals/DataviewFiltersPortal";
3+
import { AbstractHandlerClass } from "patterns/AbstractHandler";
4+
import React from "react";
5+
import { createRoot } from "react-dom/client";
6+
7+
export class FilterGroupHandler extends AbstractHandlerClass<FiltersModalHandlerResponse> {
8+
settingTitle: string = "Content alignment selector";
9+
handle(
10+
columnHandlerResponse: FiltersModalHandlerResponse
11+
): FiltersModalHandlerResponse {
12+
const { containerEl, filtersModalManager } = columnHandlerResponse;
13+
const { table } = filtersModalManager.props;
14+
15+
createRoot(containerEl.createDiv()).render(
16+
<DataviewFiltersPortal table={table} />
17+
);
18+
return this.goNext(columnHandlerResponse);
19+
}
20+
}

src/components/navbar/PaginationTable.tsx

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { PaginationProps } from "cdm/MenuBarModel";
55
import React, { useEffect } from "react";
66
import { PaginationButtonStyle } from "components/styles/NavBarStyles";
77
import { StyleVariables } from "helpers/Constants";
8+
import Grid from "@mui/material/Grid";
89
function PaginationTable(props: PaginationProps) {
910
const { table } = props;
1011
const [page, setPage] = React.useState(1);
@@ -22,8 +23,8 @@ function PaginationTable(props: PaginationProps) {
2223
<>
2324
<ButtonGroup
2425
variant="contained"
25-
size="small"
2626
key={`ButtonGroup-PaginationTable`}
27+
fullWidth={false}
2728
>
2829
<Button
2930
size="small"
@@ -53,17 +54,17 @@ function PaginationTable(props: PaginationProps) {
5354
id="Input-Pagination-number-id"
5455
size="small"
5556
key={`Input-Pagination-number`}
56-
label={`Page of ${table.getPageCount()}`}
57+
label={`Pages: ${table.getPageCount()}`}
5758
type="number"
5859
InputLabelProps={{
5960
shrink: true,
6061
style: { color: StyleVariables.TEXT_NORMAL },
6162
}}
62-
style={{ width: "100px" }}
6363
InputProps={{
6464
inputProps: {
6565
style: { textAlign: "center" },
6666
},
67+
style: { color: StyleVariables.TEXT_NORMAL, width: 120 },
6768
}}
6869
value={page}
6970
onChange={(e) => {
@@ -99,21 +100,7 @@ function PaginationTable(props: PaginationProps) {
99100
>
100101
{">>"}
101102
</Button>
102-
{/*
103-
<select
104-
value={table.getState().pagination.pageSize}
105-
onChange={(e) => {
106-
table.setPageSize(Number(e.target.value));
107-
}}
108-
>
109-
{[10, 20, 30, 40, 50].map((pageSize) => (
110-
<option key={pageSize} value={pageSize}>
111-
Show {pageSize}
112-
</option>
113-
))}
114-
</select> */}
115103
</ButtonGroup>
116-
{/* <div>{table.getRowModel().rows.length} Rows</div> */}
117104
</>
118105
);
119106
}

0 commit comments

Comments
 (0)