feat: make notes keep open when suddenly closed (#7)
Main CI-Frontend / Build & Push (push) Successful in 39s
Main CI-Frontend / Build & Push (push) Successful in 39s
## What - New feature allowing open notes to be restore, if the tab is closed ## Why - Making users' life easier ## Mood <img width="200" src="https://media3.giphy.com/media/S5uASkxZ5eGcwf2vHM/giphy.gif?cid=36b14facu3gasrwzy8axqb43wcuo1tsdjvjcslyk9t9jzvab&ep=v1_gifs_search&rid=giphy.gif&ct=g"/> Reviewed-on: #7
This commit was merged in pull request #7.
This commit is contained in:
@@ -55,7 +55,19 @@ vi.mock('../../components/AlertError', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../components/ModalMarkdown', () => ({
|
||||
default: (props: any) => <div data-testid="modal-markdown">{props.show ? 'Modal Open' : ''}</div>
|
||||
default: (props: any) => (
|
||||
<div data-testid="modal-markdown">
|
||||
{props.show ? (
|
||||
<div>
|
||||
<div data-testid="modal-title">{props.title}</div>
|
||||
<div data-testid="modal-content">{props.markdownText}</div>
|
||||
<button data-testid="modal-close" onClick={props.onHide}>Close</button>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}));
|
||||
|
||||
vi.mock('../../components/TaskTitle', () => ({
|
||||
@@ -67,7 +79,14 @@ vi.mock('../../components/TaskTimeLeft', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../../components/TaskTag', () => ({
|
||||
default: (props: any) => <div data-testid="task-tag">{props.tag}</div>
|
||||
default: (props: any) => (
|
||||
<div data-testid="task-tag">
|
||||
{props.tag}
|
||||
{props.taskOrNote === 'note' && props.onClick && (
|
||||
<a href="#" data-testid="open-it" onClick={props.onClick}>Open it</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}));
|
||||
|
||||
vi.mock('../../components/NoteTitle', () => ({
|
||||
@@ -545,6 +564,79 @@ describe('Home Component', () => {
|
||||
expect(screen.getAllByTestId('task-title')[0].textContent).toBe('Task 1');
|
||||
});
|
||||
});
|
||||
|
||||
test('saves note ID to localStorage when opening modal', async () => {
|
||||
await act(async () => {
|
||||
renderHome();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByTestId('open-it').length).toBe(2);
|
||||
});
|
||||
|
||||
const openItLinks = screen.getAllByTestId('open-it');
|
||||
await act(async () => {
|
||||
fireEvent.click(openItLinks[1]);
|
||||
});
|
||||
|
||||
expect(localStorage.getItem('OPEN_NOTE_ID')).toBe('1');
|
||||
expect(screen.getByTestId('modal-title').textContent).toBe('Note 1');
|
||||
expect(screen.getByTestId('modal-content').textContent).toBe('Line 1\nLine 2\nLine 3');
|
||||
});
|
||||
|
||||
test('restores open note modal from localStorage on reload', async () => {
|
||||
localStorage.setItem('OPEN_NOTE_ID', '2');
|
||||
|
||||
await act(async () => {
|
||||
renderHome();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('modal-title').textContent).toBe('Note 2');
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('modal-content').textContent).toBe('This is a sample\nnote content');
|
||||
});
|
||||
|
||||
test('does not restore modal if localStorage note ID not found', async () => {
|
||||
localStorage.setItem('OPEN_NOTE_ID', '999');
|
||||
|
||||
await act(async () => {
|
||||
renderHome();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByTestId('note-title').length).toBe(2);
|
||||
});
|
||||
|
||||
const modal = screen.getByTestId('modal-markdown');
|
||||
expect(modal.textContent).toBe('');
|
||||
expect(localStorage.getItem('OPEN_NOTE_ID')).toBeNull();
|
||||
});
|
||||
|
||||
test('clears localStorage when closing modal', async () => {
|
||||
await act(async () => {
|
||||
renderHome();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByTestId('open-it').length).toBe(2);
|
||||
});
|
||||
|
||||
const openItLinks = screen.getAllByTestId('open-it');
|
||||
await act(async () => {
|
||||
fireEvent.click(openItLinks[1]);
|
||||
});
|
||||
|
||||
expect(localStorage.getItem('OPEN_NOTE_ID')).toBe('1');
|
||||
|
||||
const closeButton = screen.getByTestId('modal-close');
|
||||
await act(async () => {
|
||||
fireEvent.click(closeButton);
|
||||
});
|
||||
|
||||
expect(localStorage.getItem('OPEN_NOTE_ID')).toBeNull();
|
||||
});
|
||||
/*
|
||||
test('getFirstRows properly formats note preview', async () => {
|
||||
await act(async () => {
|
||||
|
||||
@@ -28,6 +28,8 @@ import TaskTimeLeft from '../../components/TaskTimeLeft';
|
||||
import TaskTag from '../../components/TaskTag';
|
||||
import NoteTitle from '../../components/NoteTitle';
|
||||
|
||||
const OPEN_NOTE_ID_KEY = 'OPEN_NOTE_ID';
|
||||
|
||||
/**
|
||||
* Home page component.
|
||||
*
|
||||
@@ -299,7 +301,10 @@ function Home(): React.ReactNode {
|
||||
return preview.join('\n');
|
||||
};
|
||||
|
||||
const handleCloseModal = () => setShowMarkdownView(false);
|
||||
const handleCloseModal = () => {
|
||||
setShowMarkdownView(false);
|
||||
localStorage.removeItem(OPEN_NOTE_ID_KEY);
|
||||
};
|
||||
|
||||
const getSelectedLabel = (): string => {
|
||||
if (selectedOption === 'everything') return t('home_radio_everything');
|
||||
@@ -345,6 +350,22 @@ function Home(): React.ReactNode {
|
||||
applyFilter(filterText, selectedOption, savedTasks, savedNotes);
|
||||
}, [savedTasks, savedNotes, filterText, selectedOption]);
|
||||
|
||||
useEffect(() => {
|
||||
const openNoteId = localStorage.getItem(OPEN_NOTE_ID_KEY);
|
||||
if (openNoteId && notes.length > 0) {
|
||||
const noteId = Number(openNoteId);
|
||||
const foundNote = notes.find(n => n.id === noteId);
|
||||
if (foundNote) {
|
||||
setModalTitle(foundNote.title);
|
||||
setModalContent(foundNote.description);
|
||||
setShowMarkdownView(true);
|
||||
}
|
||||
else {
|
||||
localStorage.removeItem(OPEN_NOTE_ID_KEY);
|
||||
}
|
||||
}
|
||||
}, [notes]);
|
||||
|
||||
return (
|
||||
<Container fluid>
|
||||
<ContentHeader
|
||||
@@ -602,6 +623,7 @@ function Home(): React.ReactNode {
|
||||
setModalTitle(note.title);
|
||||
setModalContent(note.description);
|
||||
setShowMarkdownView(true);
|
||||
localStorage.setItem(OPEN_NOTE_ID_KEY, note.id.toString());
|
||||
}}
|
||||
/>
|
||||
</Card.Footer>
|
||||
|
||||
Reference in New Issue
Block a user