feat: improve markdown rendering and add home filter context

This commit is contained in:
2026-02-11 10:57:43 -03:00
parent 5eb7eb6677
commit 98ad43602a
8 changed files with 475 additions and 94 deletions
+294
View File
@@ -26,6 +26,7 @@
"react-markdown": "^10.1.0",
"react-router": "^7.13.0",
"react-router-bootstrap": "^0.26.3",
"remark-gfm": "^4.0.1",
"typescript": "^5.9.3",
"vite": "^7.3.1"
},
@@ -6649,6 +6650,16 @@
"node": ">=10"
}
},
"node_modules/markdown-table": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
"integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -6659,6 +6670,34 @@
"node": ">= 0.4"
}
},
"node_modules/mdast-util-find-and-replace": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
"integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"escape-string-regexp": "^5.0.0",
"unist-util-is": "^6.0.0",
"unist-util-visit-parents": "^6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mdast-util-from-markdown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
@@ -6683,6 +6722,107 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
"integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
"license": "MIT",
"dependencies": {
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-gfm-autolink-literal": "^2.0.0",
"mdast-util-gfm-footnote": "^2.0.0",
"mdast-util-gfm-strikethrough": "^2.0.0",
"mdast-util-gfm-table": "^2.0.0",
"mdast-util-gfm-task-list-item": "^2.0.0",
"mdast-util-to-markdown": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm-autolink-literal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
"integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"ccount": "^2.0.0",
"devlop": "^1.0.0",
"mdast-util-find-and-replace": "^3.0.0",
"micromark-util-character": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm-footnote": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
"integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"devlop": "^1.1.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-to-markdown": "^2.0.0",
"micromark-util-normalize-identifier": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm-strikethrough": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
"integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-to-markdown": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm-table": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
"integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"devlop": "^1.0.0",
"markdown-table": "^3.0.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-to-markdown": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-gfm-task-list-item": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
"integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"devlop": "^1.0.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-to-markdown": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdast-util-mdx-expression": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
@@ -6888,6 +7028,127 @@
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-extension-gfm": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
"integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
"license": "MIT",
"dependencies": {
"micromark-extension-gfm-autolink-literal": "^2.0.0",
"micromark-extension-gfm-footnote": "^2.0.0",
"micromark-extension-gfm-strikethrough": "^2.0.0",
"micromark-extension-gfm-table": "^2.0.0",
"micromark-extension-gfm-tagfilter": "^2.0.0",
"micromark-extension-gfm-task-list-item": "^2.0.0",
"micromark-util-combine-extensions": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-autolink-literal": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
"integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
"license": "MIT",
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-footnote": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
"integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-core-commonmark": "^2.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-normalize-identifier": "^2.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-strikethrough": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
"integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-util-chunked": "^2.0.0",
"micromark-util-classify-character": "^2.0.0",
"micromark-util-resolve-all": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-table": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
"integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-tagfilter": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
"integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
"license": "MIT",
"dependencies": {
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-extension-gfm-task-list-item": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
"integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
"license": "MIT",
"dependencies": {
"devlop": "^1.0.0",
"micromark-factory-space": "^2.0.0",
"micromark-util-character": "^2.0.0",
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/micromark-factory-destination": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
@@ -8218,6 +8479,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/remark-gfm": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
"integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"mdast-util-gfm": "^3.0.0",
"micromark-extension-gfm": "^3.0.0",
"remark-parse": "^11.0.0",
"remark-stringify": "^11.0.0",
"unified": "^11.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-parse": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
@@ -8251,6 +8530,21 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-stringify": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
"integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
"mdast-util-to-markdown": "^2.0.0",
"unified": "^11.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+1
View File
@@ -29,6 +29,7 @@
"react-markdown": "^10.1.0",
"react-router": "^7.13.0",
"react-router-bootstrap": "^0.26.3",
"remark-gfm": "^4.0.1",
"typescript": "^5.9.3",
"vite": "^7.3.1"
},
+24 -84
View File
@@ -2,6 +2,7 @@ import React from 'react';
import { test, describe, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, act, fireEvent, waitFor } from '@testing-library/react';
import AuthContext from '../../context/AuthContext';
import FilterProvider from '../../context/FilterProvider';
import { BrowserRouter } from 'react-router-dom';
import api from '../../api-service/api';
import { TaskResponse } from '../../types/TaskResponse';
@@ -140,9 +141,20 @@ const authContextValue = {
};
describe('Home Component', () => {
const renderHome = () => render(
<AuthContext.Provider value={authContextValue}>
<FilterProvider>
<BrowserRouter>
<Home />
</BrowserRouter>
</FilterProvider>
</AuthContext.Provider>
);
beforeEach(() => {
// Reset mocks and setup default responses
vi.clearAllMocks();
localStorage.clear();
(api.getJSON as any).mockImplementation((url: string) => {
if (url.includes('tags')) {
return Promise.resolve(mockTags);
@@ -169,13 +181,7 @@ describe('Home Component', () => {
test('renders with initial data', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
expect(screen.getByTestId('content-header')).toBeDefined();
@@ -193,13 +199,7 @@ describe('Home Component', () => {
test('filters tasks and notes when search text is entered', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -224,13 +224,7 @@ describe('Home Component', () => {
test('filters by radio button selection', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -273,13 +267,7 @@ describe('Home Component', () => {
test('filters by tag selection', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -314,13 +302,7 @@ describe('Home Component', () => {
test('marks task as done', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -355,13 +337,7 @@ describe('Home Component', () => {
test('deletes note', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -397,13 +373,7 @@ describe('Home Component', () => {
test('opens markdown modal when clicking on note tag', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -431,13 +401,7 @@ describe('Home Component', () => {
});
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
// Should show error message
@@ -447,13 +411,7 @@ describe('Home Component', () => {
test('keeps filter selection after marking task as done', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -499,13 +457,7 @@ describe('Home Component', () => {
test('keeps filter selection after deleting a note', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -551,13 +503,7 @@ describe('Home Component', () => {
test('keeps text search after marking task as done', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -598,13 +544,7 @@ describe('Home Component', () => {
/*
test('getFirstRows properly formats note preview', async () => {
await act(async () => {
render(
<AuthContext.Provider value={authContextValue}>
<BrowserRouter>
<Home />
</BrowserRouter>
</AuthContext.Provider>
);
renderHome();
});
await waitFor(() => {
@@ -2,6 +2,7 @@ import React from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import './style.css';
type Props = {
@@ -41,7 +42,7 @@ const ModalMarkdown: React.FC<Props> = (props: Props): React.ReactNode => {
</Modal.Title>
</Modal.Header>
<Modal.Body className="markdown-modal">
<Markdown>{props.markdownText}</Markdown>
<Markdown remarkPlugins={[remarkGfm]}>{props.markdownText}</Markdown>
</Modal.Body>
<Modal.Footer>
<Button variant="outline-secondary" onClick={props.onHide}>
+143 -2
View File
@@ -1,15 +1,156 @@
.markdown-modal {
font-size: 14px;
line-height: 1.6;
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 1.25em;
margin-bottom: 0.5em;
font-weight: 600;
line-height: 1.25;
}
h1 {
font-size: 2em;
padding-bottom: 0.3em;
border-bottom: 1px solid var(--bs-border-color);
}
h2 {
font-size: 1.5em;
padding-bottom: 0.3em;
border-bottom: 1px solid var(--bs-border-color);
}
h3 {
font: 1.25em;
font-size: 1.25em;
}
h4 {
font-size: 1em;
}
h5 {
font-size: 0.875em;
}
h6 {
font-size: 0.85em;
color: var(--bs-secondary-color);
}
p {
font-size: 14px;
margin-top: 0;
margin-bottom: 1em;
}
a {
color: var(--bs-link-color);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
ul,
ol {
margin-top: 0;
margin-bottom: 1em;
padding-left: 2em;
}
ul ul,
ul ol,
ol ul,
ol ol {
margin-bottom: 0;
}
/* Task list checkboxes */
li input[type='checkbox'] {
margin-right: 0.4em;
pointer-events: none;
}
li.task-list-item {
list-style: none;
margin-left: -1.5em;
}
blockquote {
margin: 0 0 1em;
padding: 0 1em;
color: var(--bs-secondary-color);
border-left: 4px solid var(--bs-border-color);
}
blockquote > :last-child {
margin-bottom: 0;
}
code {
padding: 0.2em 0.4em;
font-size: 85%;
background-color: var(--bs-tertiary-bg);
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
}
pre {
margin-top: 0;
margin-bottom: 1em;
padding: 1em;
overflow: auto;
background-color: var(--bs-tertiary-bg);
border-radius: 6px;
}
pre code {
padding: 0;
background-color: transparent;
font-size: 100%;
}
table {
width: 100%;
margin-bottom: 1em;
border-collapse: collapse;
border-spacing: 0;
overflow: auto;
}
table th,
table td {
padding: 6px 13px;
border: 1px solid var(--bs-border-color);
}
table th {
font-weight: 600;
background-color: var(--bs-tertiary-bg);
}
table tr:nth-child(even) {
background-color: var(--bs-tertiary-bg);
}
hr {
height: 1px;
margin: 1.5em 0;
border: none;
background-color: var(--bs-border-color);
}
img {
max-width: 100%;
}
del {
text-decoration: line-through;
}
}
+6 -3
View File
@@ -2,6 +2,7 @@ import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import AuthProvider from './context/AuthProvider';
import FilterProvider from './context/FilterProvider';
import SidebarProvider from './context/SidebarProvider';
import './i18n';
@@ -14,9 +15,11 @@ const root = createRoot(
root.render(
<React.StrictMode>
<AuthProvider>
<SidebarProvider>
<App />
</SidebarProvider>
<FilterProvider>
<SidebarProvider>
<App />
</SidebarProvider>
</FilterProvider>
</AuthProvider>
</React.StrictMode>
);
+4 -3
View File
@@ -17,6 +17,7 @@ import ApiConfig from '../../api-service/apiConfig';
import { handleDefaultLang } from '../../lang-service/LangHandler';
import { translateServerResponse, translateTaskResponse } from '../../utils/TranslatorUtils';
import AuthContext from '../../context/AuthContext';
import FilterContext from '../../context/FilterContext';
import ContentHeader from '../../components/ContentHeader';
import AlertError from '../../components/AlertError';
import { ThreeDotsVertical } from 'react-bootstrap-icons';
@@ -36,6 +37,7 @@ import NoteTitle from '../../components/NoteTitle';
*/
function Home(): React.ReactNode {
const { user } = useContext(AuthContext);
const { filterText, selectedOption, setFilterText, setSelectedOption } = useContext(FilterContext);
const { i18n, t } = useTranslation();
const [errorMessage, setErrorMessage] = useState<string>('');
const [tags, setTags] = useState<string[]>([]);
@@ -43,12 +45,10 @@ function Home(): React.ReactNode {
const [showMarkdownView, setShowMarkdownView] = useState<boolean>(false);
const [modalTitle, setModalTitle] = useState<string>('');
const [modalContent, setModalContent] = useState<string>('');
const [filterText, setFilterText] = useState<string>('');
const [tasks, setTasks] = useState<TaskResponse[]>([]);
const [notes, setNotes] = useState<NoteResponse[]>([]);
const [savedNotes, setSavedNotes] = useState<NoteResponse[]>([]);
const [savedTasks, setSavedTasks] = useState<TaskResponse[]>([]);
const [selectedOption, setSelectedOption] = useState<string>('everything');
/**
* Handles the error by setting the error message.
@@ -129,7 +129,8 @@ function Home(): React.ReactNode {
const anyTitleMatch = note.title.toLowerCase().includes(text.toLowerCase());
const anyContentMatch = note.description.toLowerCase().includes(text.toLowerCase());
const anyUrlMatch = note.url?.includes(text.toLowerCase());
return anyTitleMatch || anyContentMatch || anyUrlMatch;
const anyTagMatch = note.tag?.toLowerCase().includes(text.toLowerCase());
return anyTitleMatch || anyContentMatch || anyUrlMatch || anyTagMatch;
});
if (tagToFilter === 'untagged') {
+1 -1
View File
@@ -45,7 +45,7 @@ services:
volumes:
- "./server:/app"
healthcheck:
test: curl -f http://localhost:8585/actuator/health | grep '"status":"UP"'
test: curl -f http://localhost:8585/health | grep '"status":"UP"'
interval: 1m30s
timeout: 15s
retries: 3