Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added markdown previews #34

Merged
merged 6 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ enables you to _work on what matters_.
## Current features

- **Why**-centric for maximizing impact.
- Markdown support and **syntax highlighting** for task descriptions.
- Markdown support with **syntax highlighting**.
- Manage task lists (e.g. "Team 1", "Team 2", "Architecture Board",...).
- Manage tasks (rank, categorize, describe business value / impact,...).
- Manage task categories (e.g. "Quality Improvement", "Time Saving", "Documentation", "Security"...).
Expand All @@ -30,7 +30,7 @@ enables you to _work on what matters_.
- Docker support.
- Manage notes.

## Preview (29th September 2023)
## Preview (30th September 2023)

### Home

Expand All @@ -52,6 +52,10 @@ enables you to _work on what matters_.

<kbd><img src="./static/Notes.png" alt="Notes"></kbd>

### Adding notes

<kbd><img src="./static/AddNote.png" alt="Notes"></kbd>

### Mobile

<kbd><img src="./static/Mobile.png" alt="Mobile"></kbd>
Expand Down
24 changes: 12 additions & 12 deletions src/Chrono/ClientApp/src/Features/Notes/NoteEditControl.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {useEffect, useState} from "react";
import {useNavigate} from "react-router-dom";
import {Button, Confirm, Container, Dropdown, Form, Icon, Input, TextArea,} from "semantic-ui-react";
import {Button, Confirm, Container, Dropdown, Form, Icon, Input} from "semantic-ui-react";
import {createNote, deleteNote, getNote, updateNote} from "./NoteService";

// Shared
import {Note} from "../../Shared/Entities/Note";
import {MarkdownEditor} from "../../Shared/Components/MarkdownEditor/MarkdownEditor";

enum NoteEditControlMode {
Add,
Expand Down Expand Up @@ -88,16 +89,13 @@ const NoteEditControl = (props: {
}}
required
></Form.Field>
<Form.Field
control={TextArea}
label="Content"
placeholder="Content"
value={text}
onChange={(e: any) => {
setText(e.target.value);
}}
required
></Form.Field>
<MarkdownEditor
textLabel="Content"
text={text}
onTextChanged={(e: any) => setText(e.target.value)}
textAreaRows={20}
required={true}
/>
{note?.lastModifiedBy && (
<div style={{color: "gray", marginBottom: "0.75em"}}>
{`Last modified by ${note.lastModifiedBy} on ${new Date(
Expand Down Expand Up @@ -147,4 +145,6 @@ const NoteEditControl = (props: {
);
};

export {NoteEditControl, NoteEditControlMode};
export {
NoteEditControl, NoteEditControlMode
};
2 changes: 1 addition & 1 deletion src/Chrono/ClientApp/src/Features/Notes/NotePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const NotePage = () => {
<Card.Header>
<a href={`/notes/${n.id}`}>{n.title}</a>
</Card.Header>
<Card.Meta>{n.lastModified + ""}</Card.Meta>
<Card.Meta>{n.created}</Card.Meta>
<Card.Description>
{n.preview}
</Card.Description>
Expand Down
19 changes: 8 additions & 11 deletions src/Chrono/ClientApp/src/Features/Tasks/TaskEditControl.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./TaskEditControl.css";
import {useEffect, useState} from "react";
import {useNavigate} from "react-router-dom";
import {Button, Confirm, Container, Dropdown, Form, Icon, Input, TextArea,} from "semantic-ui-react";
import {Button, Confirm, Container, Dropdown, Form, Icon, Input,} from "semantic-ui-react";
import TaskCategoryEditControl from "./TaskCategoryEditControl";

// Shared
Expand All @@ -10,6 +10,7 @@ import {Category} from "../../Shared/Entities/Category";
import {TaskListOptions} from "../../Shared/Entities/TaskListOptions";
import {createTask, deleteTask, getTask, updateTask,} from "../../Shared/Services/TaskService";
import {getTaskList, getTaskListOptions} from "../../Shared/Services/TaskListService";
import {MarkdownEditor} from "../../Shared/Components/MarkdownEditor/MarkdownEditor";

enum TaskControlMode {
Add,
Expand Down Expand Up @@ -153,17 +154,13 @@ const TaskEditControl = (props: {
required={taskListOptions?.requireBusinessValue}
disabled={task?.done}
></Form.Field>
<Form.Field
control={TextArea}
label="Description"
placeholder="Description"
value={description}
onChange={(e: any) => {
setDescription(e.target.value);
}}
<MarkdownEditor
textLabel="Description"
text={description}
textAreaRows={10}
onTextChanged={(e: any) => setDescription(e.target.value)}
required={taskListOptions?.requireDescription}
disabled={task?.done}
></Form.Field>
disabled={task?.done}/>
<Form.Field
label="Position"
control={Input}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
div.ui.attached.menu {
font-size: 0.8em;
}

.markdown-preview {
margin-top: 0 !important;
padding-top: 11px !important;
overflow-wrap: anywhere;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import "./MarkdownEditor.css"
import {Form, Segment, Tab, TextArea,} from "semantic-ui-react";
import {dracula} from 'react-syntax-highlighter/dist/esm/styles/hljs';
import ReactMarkdown from "react-markdown";
import SyntaxHighlighter from "react-syntax-highlighter";

type MarkdownEditorProps = {
textLabel: string;
text: string;
onTextChanged: (e: any) => void;
textAreaRows?: number;
required?: boolean;
disabled?: boolean;
}

export const MarkdownEditor = (props: MarkdownEditorProps) => {
const tabPanes = [
{
menuItem: "Write",
render: () => {
return (
<Tab.Pane>
<Form.Field
control={TextArea}
placeholder={props.textLabel}
value={props.text}
onChange={props.onTextChanged}
rows={props.textAreaRows}
required={props.required}
disabled={props.disabled}
></Form.Field>
</Tab.Pane>
);
}
},
{
menuItem: "Preview",
render: () => {
return (
<Tab.Pane>
<Segment className="markdown-preview">
<ReactMarkdown children={props.text} components={{
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
{...props}
children={String(children).replace(/\n$/, '')}
style={dracula}
language={match[1]}
PreTag="div"
/>
) : (
<code {...props} className={className}>
{children}
</code>
)
}
}}/>

</Segment>
</Tab.Pane>
);
}
}
];

return (
<div className={props.required ? "required field" : "field"}>
<label>{props.textLabel}</label>
<Tab panes={tabPanes} menu={{attached: true, tabular: false}}/>
</div>
);
};
2 changes: 1 addition & 1 deletion src/Chrono/ClientApp/src/Shared/Entities/Note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export type NotePreview = {
id: number;
title: string;
preview: string;
lastModified: string;
created: string;
}

export type GetMyNotesResponse = {
Expand Down
7 changes: 4 additions & 3 deletions src/Chrono/Features/Notes/GetMyNotes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ public GetMyNotesHandler(IApplicationDbContext context, ICurrentUserService curr
public Task<GetMyNotesResponse> Handle(GetMyNotes request, CancellationToken cancellationToken)
{
var result = _context.Notes
.OrderByDescending(n => n.LastModified)
.OrderByDescending(n => n.Created)
.AsEnumerable()
.Where(n => n.IsPermitted(_currentUserService.UserId))
.Select(n => new NotePreview
{
Id = n.Id,
Title = n.Title,
Preview = _textService.Truncate(n.Text, MaxTextPreviewLength),
LastModified = n.LastModified.ToLocalTime().ToString(CultureInfo.InvariantCulture)
// Persisted in UTC.
Created = n.Created.ToLocalTime().ToString(CultureInfo.InvariantCulture)
})
.ToArray();

Expand All @@ -57,7 +58,7 @@ public class NotePreview
public int Id { get; init; }
public string Title { get; init; }
public string Preview { get; set; }
public string LastModified { get; set; }
public string Created { get; set; }
}

[Authorize] [Route("api/notes")] [Tags("Notes")]
Expand Down
Binary file added static/AddNote.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/AddTask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.