From 8bbebb4be248c148dcb885eb8fdaca0061fde6e1 Mon Sep 17 00:00:00 2001 From: David Morais Date: Sun, 21 Apr 2019 23:30:48 +0100 Subject: [PATCH 1/2] Update task list items design Close #PM169 --- app/components/Cards/CardItem.scss | 13 +++++++- app/components/UI/TaskListInput.jsx | 52 +++++++++++++++-------------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/app/components/Cards/CardItem.scss b/app/components/Cards/CardItem.scss index ca857c08..e88ede65 100644 --- a/app/components/Cards/CardItem.scss +++ b/app/components/Cards/CardItem.scss @@ -179,7 +179,18 @@ $code-background: #08090a; } } } - + } + ul { + .task-list-item { + input { + position: relative; + vertical-align: bottom; + opacity: 1; + cursor: pointer; + height: 20px; + width: 20px; + } + } } div { display: flex; diff --git a/app/components/UI/TaskListInput.jsx b/app/components/UI/TaskListInput.jsx index 217571a3..edea477f 100644 --- a/app/components/UI/TaskListInput.jsx +++ b/app/components/UI/TaskListInput.jsx @@ -7,32 +7,34 @@ class TaskListInput extends Component { const { text, editCard, defaultChecked } = this.props; return ( - { - e.stopPropagation(); - const { card, saveFunc } = editCard; - const inputTextContent = e.target.parentElement.textContent; - let newText = ''; - if (e.target.checked) { - const inputText = `[ ]${inputTextContent}`; - newText = text.replace(inputText, `[X]${inputTextContent}`); - } else { - const inputText = - (text.indexOf(`[X]${inputTextContent}`) !== -1 && `[X]${inputTextContent}`) || - (text.indexOf(`[x]${inputTextContent}`) !== -1 && `[x]${inputTextContent}`) || - null; - newText = text.replace(inputText, `[ ] ${inputTextContent}`); - } + + { + e.stopPropagation(); + const { card, saveFunc } = editCard; + const inputTextContent = e.target.parentElement.textContent; + let newText = ''; + if (e.target.checked) { + const inputText = `[ ]${inputTextContent}`; + newText = text.replace(inputText, `[X]${inputTextContent}`); + } else { + const inputText = + (text.indexOf(`[X]${inputTextContent}`) !== -1 && `[X]${inputTextContent}`) || + (text.indexOf(`[x]${inputTextContent}`) !== -1 && `[x]${inputTextContent}`) || + null; + newText = text.replace(inputText, `[ ] ${inputTextContent}`); + } - saveFunc({ - ...card, - text: newText, - }); - }} - /> + saveFunc({ + ...card, + text: newText, + }); + }} + /> + ); } } From 177de29ecdda15a17e6a233362ee8decd67e3b56 Mon Sep 17 00:00:00 2001 From: David Morais Date: Mon, 22 Apr 2019 16:51:02 +0100 Subject: [PATCH 2/2] Fix issue with task list not updating if markdown was found in the task description - Add a regexp to filter the tasks, making it easier to manipulate data - Add a function that retrieves task data from the card, including number of completed tasks vs total tasks - This can be used later to add a graphic indicator of the number of tasks per card - Tested with bold and other markdown markers - Update react showdown repository - Close #PM151 --- app/components/UI/TaskListInput.jsx | 66 +++++++++++++++++++++++------ app/package.json | 2 +- app/utils/regexp.js | 2 + 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/app/components/UI/TaskListInput.jsx b/app/components/UI/TaskListInput.jsx index edea477f..7cc4dd92 100644 --- a/app/components/UI/TaskListInput.jsx +++ b/app/components/UI/TaskListInput.jsx @@ -1,10 +1,51 @@ import React, { Component } from 'react'; +import regexp from 'Utils/regexp'; import PropTypes from 'prop-types'; -class TaskListInput extends Component { +const FORBIDDEN_CHARACTERS = ['#', '*', 'ยด', '~', '`']; +function dropMdChars(text) { + const textArray = []; + const isNotForbidden = char => FORBIDDEN_CHARACTERS.indexOf(char) === -1; + for (let i = 0; i < text.length; i += 1) { + const char = text[i]; + if (isNotForbidden(char)) { + textArray.push(char); + } + } + return textArray.join(''); +} + +function getTaskDataFromInput(text) { + const taskData = { + tasks: [], + completed: 0, + }; + const tasks = text.match(regexp.extractTasksFromMarkdownRegExp)[0].split('- '); + for (let i = 0; i < tasks.length; i += 1) { + const task = tasks[i]; + if (task) { + const rawContent = task.slice(4, task.length - 1).trim(); + const completed = (task.slice(0, 3) === '[X]' && true) || false; + const textContent = dropMdChars(rawContent).trim(); + taskData.tasks.push({ + rawContent, + completed, + textContent, + }); + if (completed) { + taskData.completed += 1; + } + } + } + return taskData; +} + +class TaskListInput extends Component { render() { - const { text, editCard, defaultChecked } = this.props; + const { + text, editCard, defaultChecked, + } = this.props; return ( @@ -15,19 +56,18 @@ class TaskListInput extends Component { onChange={(e) => { e.stopPropagation(); const { card, saveFunc } = editCard; - const inputTextContent = e.target.parentElement.textContent; + const taskData = getTaskDataFromInput(text); let newText = ''; - if (e.target.checked) { - const inputText = `[ ]${inputTextContent}`; - newText = text.replace(inputText, `[X]${inputTextContent}`); - } else { - const inputText = - (text.indexOf(`[X]${inputTextContent}`) !== -1 && `[X]${inputTextContent}`) || - (text.indexOf(`[x]${inputTextContent}`) !== -1 && `[x]${inputTextContent}`) || - null; - newText = text.replace(inputText, `[ ] ${inputTextContent}`); + const taskIndex = taskData.tasks + .map(t => t.textContent) + .indexOf(e.target.parentElement.textContent.trim()); + if (taskIndex !== -1) { + const task = taskData.tasks[taskIndex]; + const { rawContent, completed } = task; + const newRawContent = completed ? `[ ] ${rawContent}` : `[X] ${rawContent}`; + const targetContent = completed ? `[X] ${rawContent}` : `[ ] ${rawContent}`; + newText = text.replace(targetContent, newRawContent); } - saveFunc({ ...card, text: newText, diff --git a/app/package.json b/app/package.json index 1834652a..3aaae765 100644 --- a/app/package.json +++ b/app/package.json @@ -31,7 +31,7 @@ "react-masonry-component": "^6.2.1", "react-redux": "^5.0.6", "react-router-dom": "4.1.1", - "react-showdown": "https://github.com/psybork/react-showdown.git", + "react-showdown": "https://github.com/dmorais92/react-showdown.git", "react-simplemde-editor": "^3.6.16", "react-tooltip": "^3.10.0", "recompose": "^0.30.0", diff --git a/app/utils/regexp.js b/app/utils/regexp.js index 35022de7..92b60d07 100644 --- a/app/utils/regexp.js +++ b/app/utils/regexp.js @@ -1,7 +1,9 @@ const codeRegExp = new RegExp(/`{3}[\s\S]*?`{3}/g); const backticksRegExp = new RegExp(/(?:```[a-z]*)/g); +const extractTasksFromMarkdownRegExp = new RegExp(/^((?:- )?\[( |X)\] [\#\S\w\s\`\*\~]*([\w]*[\`\*\~]+[\w\S\. ]*))/m); export default { codeRegExp, + extractTasksFromMarkdownRegExp, backticksRegExp, };