This commit is contained in:
@@ -42,7 +42,9 @@ vi.mock('react-router', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('react-bootstrap-icons', () => ({
|
||||
ThreeDotsVertical: () => <div data-testid="three-dots-icon">•••</div>
|
||||
ThreeDotsVertical: () => <div data-testid="three-dots-icon">•••</div>,
|
||||
CheckSquare: () => <div data-testid="task-icon">☑</div>,
|
||||
JournalText: () => <div data-testid="note-icon">📝</div>
|
||||
}));
|
||||
|
||||
// Mock components
|
||||
@@ -217,6 +219,8 @@ describe('Home Component', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByTestId('task-title').length).toBe(2);
|
||||
expect(screen.getAllByTestId('note-title').length).toBe(2);
|
||||
expect(screen.getAllByTestId('task-icon').length).toBe(2);
|
||||
expect(screen.getAllByTestId('note-icon').length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import Button from 'react-bootstrap/Button';
|
||||
import Modal from 'react-bootstrap/Modal';
|
||||
import Markdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
@@ -75,41 +74,41 @@ const ModalMarkdown: React.FC<Props> = (props: Props): React.ReactNode => {
|
||||
)}
|
||||
</Modal.Body>
|
||||
<Modal.Footer className="d-flex flex-wrap gap-2 justify-content-end">
|
||||
<Button
|
||||
variant="outline-secondary"
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleHide}
|
||||
className="modal-action-btn"
|
||||
className="home-new-item-secondary task-note-btn"
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
variant={showSource ? 'info' : 'outline-info'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleToggleSource}
|
||||
data-testid="modal-source-button"
|
||||
className="modal-action-btn"
|
||||
className={`${showSource ? 'home-new-item' : 'home-new-item-secondary'} task-note-btn`}
|
||||
>
|
||||
Source
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline-primary"
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCopy}
|
||||
data-testid="modal-copy-button"
|
||||
className="modal-action-btn"
|
||||
className="home-new-item-secondary task-note-btn"
|
||||
>
|
||||
{copied ? 'Copied!' : 'Copy'}
|
||||
</Button>
|
||||
</button>
|
||||
{props.onSave && (
|
||||
<Button
|
||||
variant="primary"
|
||||
<button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
handleHide();
|
||||
await props.onSave!();
|
||||
}}
|
||||
data-testid="modal-save-button"
|
||||
className="home-new-item modal-action-btn"
|
||||
className="home-new-item task-note-btn"
|
||||
>
|
||||
{props.saveButtonLabel ?? 'Save note'}
|
||||
</Button>
|
||||
</button>
|
||||
)}
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
|
||||
@@ -168,11 +168,6 @@
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
.modal-action-btn {
|
||||
border-radius: 3px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.markdown-source {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -24,7 +24,7 @@ function TaskTag(props: React.PropsWithChildren<Props>): React.ReactNode {
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col className="d-inline-block text-muted card-tag poppins-regular">
|
||||
<Col className="d-inline-block card-tag poppins-regular">
|
||||
{tagContent}
|
||||
{' '}
|
||||
{props.taskOrNote}
|
||||
@@ -40,7 +40,7 @@ function TaskTag(props: React.PropsWithChildren<Props>): React.ReactNode {
|
||||
</>
|
||||
)}
|
||||
</Col>
|
||||
<Col className="d-inline-block text-muted card-tag ms-5 text-end poppins-regular">
|
||||
<Col className="d-inline-block card-tag ms-5 text-end poppins-regular">
|
||||
{props.lastUpdate}
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
.card-tag {
|
||||
font-size: 13px;
|
||||
color: rgba(var(--bs-body-color-rgb), 0.55);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,14 @@ a:hover, .btn-link:hover {
|
||||
background-color: #d91638;
|
||||
}
|
||||
|
||||
.home-item-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.task-note-btn {
|
||||
height: 48px;
|
||||
}
|
||||
@@ -391,7 +399,6 @@ p.search-result-item-title {
|
||||
|
||||
.task-card {
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.dropdown-toggle::after {
|
||||
|
||||
@@ -20,7 +20,7 @@ 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';
|
||||
import { CheckSquare, JournalText, ThreeDotsVertical } from 'react-bootstrap-icons';
|
||||
import { NavLink } from 'react-router';
|
||||
import ModalMarkdown from '../../components/ModalMarkdown';
|
||||
import TaskTitle from '../../components/TaskTitle';
|
||||
@@ -498,6 +498,9 @@ function Home(): React.ReactNode {
|
||||
<Row>
|
||||
<Col xs={10}>
|
||||
<Card.Title>
|
||||
<span className="home-item-icon">
|
||||
<CheckSquare />
|
||||
</span>
|
||||
<TaskTitle
|
||||
title={task.description}
|
||||
done={task.done}
|
||||
@@ -558,6 +561,9 @@ function Home(): React.ReactNode {
|
||||
<Row>
|
||||
<Col xs={10}>
|
||||
<Card.Title>
|
||||
<span className="home-item-icon">
|
||||
<JournalText />
|
||||
</span>
|
||||
<NoteTitle
|
||||
title={note.title}
|
||||
noteUrl={note.url}
|
||||
|
||||
@@ -538,23 +538,25 @@ function NoteAdd(): React.ReactNode {
|
||||
/>
|
||||
</Form.Group>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="home-new-item task-note-btn mt-3"
|
||||
>
|
||||
{t('note_form_submit')}
|
||||
</button>
|
||||
<div className="d-flex justify-content-end gap-2 mt-3">
|
||||
<button
|
||||
type="submit"
|
||||
className="home-new-item task-note-btn"
|
||||
>
|
||||
{t('note_form_submit')}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="ms-2 home-new-item-secondary task-note-btn"
|
||||
onClick={() => {
|
||||
clearDraft();
|
||||
navigate('/home');
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="home-new-item-secondary task-note-btn"
|
||||
onClick={() => {
|
||||
clearDraft();
|
||||
navigate('/home');
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
</Card.Body>
|
||||
|
||||
@@ -381,24 +381,41 @@ function TaskAdd(): React.ReactNode {
|
||||
onSubmit={handleSubmit}
|
||||
autoComplete="off"
|
||||
>
|
||||
{/* Description */}
|
||||
<FormInput
|
||||
labelText={t('task_form_desc_label')}
|
||||
iconName="PencilFill"
|
||||
required={true}
|
||||
type="text"
|
||||
name="description"
|
||||
placeholder={t('task_form_desc_placeholder')}
|
||||
value={taskDescription}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTaskDescription(e.target.value);
|
||||
hasUserEdited.current = true;
|
||||
saveDraft(e.target.value, taskUrl, dueDate, highPriority, selectedTags);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Row>
|
||||
<Col xs={12} sm={12} xxl={6}>
|
||||
<Col xs={12} md={6} xxl={6}>
|
||||
{/* Description */}
|
||||
<FormInput
|
||||
labelText={t('task_form_desc_label')}
|
||||
iconName="PencilFill"
|
||||
required={true}
|
||||
type="text"
|
||||
name="description"
|
||||
placeholder={t('task_form_desc_placeholder')}
|
||||
value={taskDescription}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTaskDescription(e.target.value);
|
||||
hasUserEdited.current = true;
|
||||
saveDraft(e.target.value, taskUrl, dueDate, highPriority, selectedTags);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} md={3} xxl={3}>
|
||||
{/* Due date */}
|
||||
<FormInput
|
||||
labelText={t('task_form_duedate_label')}
|
||||
iconName="CalendarCheck"
|
||||
required={false}
|
||||
type="date"
|
||||
name="dueDate"
|
||||
placeholder={t('task_form_duedate_placeholder')}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setDueDate(e.target.value);
|
||||
hasUserEdited.current = true;
|
||||
saveDraft(taskDescription, taskUrl, e.target.value, highPriority, selectedTags);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} md={3} xxl={3}>
|
||||
{/* Task URL */}
|
||||
<FormInput
|
||||
labelText={t('task_form_url_label')}
|
||||
@@ -415,23 +432,10 @@ function TaskAdd(): React.ReactNode {
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} xxl={6}>
|
||||
{/* Due date */}
|
||||
<FormInput
|
||||
labelText={t('task_form_duedate_label')}
|
||||
iconName="CalendarCheck"
|
||||
required={false}
|
||||
type="date"
|
||||
name="dueDate"
|
||||
placeholder={t('task_form_duedate_placeholder')}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setDueDate(e.target.value);
|
||||
hasUserEdited.current = true;
|
||||
saveDraft(taskDescription, taskUrl, e.target.value, highPriority, selectedTags);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} sm={12} xxl={12}>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col xs={12}>
|
||||
{/* Tag with suggestion dropdown */}
|
||||
<Form.Group className="mb-3" ref={tagContainerRef} style={{ position: 'relative' }}>
|
||||
<Form.Label>Tags</Form.Label>
|
||||
@@ -521,23 +525,25 @@ function TaskAdd(): React.ReactNode {
|
||||
}}
|
||||
/>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="home-new-item task-note-btn"
|
||||
>
|
||||
{t('task_form_submit')}
|
||||
</button>
|
||||
<div className="d-flex justify-content-end gap-2">
|
||||
<button
|
||||
type="submit"
|
||||
className="home-new-item task-note-btn"
|
||||
>
|
||||
{t('task_form_submit')}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="ms-2 home-new-item-secondary task-note-btn"
|
||||
onClick={() => {
|
||||
clearDraft();
|
||||
navigate('/home');
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="home-new-item-secondary task-note-btn"
|
||||
onClick={() => {
|
||||
clearDraft();
|
||||
navigate('/home');
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
|
||||
@@ -32,7 +32,8 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
sourcemap: mode === 'development'
|
||||
},
|
||||
server: {
|
||||
port: 5000
|
||||
port: 5000,
|
||||
allowedHosts: ['.ngrok-free.dev']
|
||||
},
|
||||
preview: {
|
||||
port: 5000
|
||||
|
||||
Reference in New Issue
Block a user