Use separate preview for description and allow toggling checkboxes
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
46
package-lock.json
generated
46
package-lock.json
generated
@@ -3857,7 +3857,6 @@
|
|||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
@@ -11820,6 +11819,14 @@
|
|||||||
"type-check": "~0.3.2"
|
"type-check": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"linkify-it": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
||||||
|
"requires": {
|
||||||
|
"uc.micro": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||||
@@ -12049,6 +12056,30 @@
|
|||||||
"integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==",
|
"integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"markdown-it": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"entities": "~2.0.0",
|
||||||
|
"linkify-it": "^2.0.0",
|
||||||
|
"mdurl": "^1.0.1",
|
||||||
|
"uc.micro": "^1.0.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"entities": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"markdown-it-task-lists": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA=="
|
||||||
|
},
|
||||||
"markdown-table": {
|
"markdown-table": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz",
|
||||||
@@ -12107,6 +12138,11 @@
|
|||||||
"unist-util-visit": "^1.1.0"
|
"unist-util-visit": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mdurl": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||||
|
},
|
||||||
"mem": {
|
"mem": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
||||||
@@ -15881,8 +15917,7 @@
|
|||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
@@ -17320,6 +17355,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.1.0.tgz",
|
||||||
"integrity": "sha512-W3kLbx+ML9PBl5Bzso/lTvVxk4BCveSNAtQeht59FEtxCdGThmn6wSHA4Xq3eQYAK24NHdisMM4JmsK0GFy/pg=="
|
"integrity": "sha512-W3kLbx+ML9PBl5Bzso/lTvVxk4BCveSNAtQeht59FEtxCdGThmn6wSHA4Xq3eQYAK24NHdisMM4JmsK0GFy/pg=="
|
||||||
},
|
},
|
||||||
|
"uc.micro": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||||
|
},
|
||||||
"unherit": {
|
"unherit": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz",
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
"@nextcloud/vue": "^1.5.0",
|
"@nextcloud/vue": "^1.5.0",
|
||||||
"blueimp-md5": "^2.13.0",
|
"blueimp-md5": "^2.13.0",
|
||||||
"dompurify": "^2.0.8",
|
"dompurify": "^2.0.8",
|
||||||
|
"markdown-it": "^10.0.0",
|
||||||
|
"markdown-it-task-lists": "^2.1.1",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"nextcloud-vue-collections": "^0.7.2",
|
"nextcloud-vue-collections": "^0.7.2",
|
||||||
"p-queue": "^6.3.0",
|
"p-queue": "^6.3.0",
|
||||||
|
|||||||
@@ -127,9 +127,22 @@
|
|||||||
href="https://deck.readthedocs.io/en/latest/Markdown/"
|
href="https://deck.readthedocs.io/en/latest/Markdown/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="icon icon-info" />
|
class="icon icon-info" />
|
||||||
|
<Actions v-if="canEdit">
|
||||||
|
<ActionButton v-if="!descriptionEditing" icon="icon-rename" @click="showEditor()">
|
||||||
|
{{ t('deck', 'Edit description') }}
|
||||||
|
</ActionButton>
|
||||||
|
<ActionButton v-else icon="icon-toggle" @click="hideEditor()">
|
||||||
|
{{ t('deck', 'View description') }}
|
||||||
|
</ActionButton>
|
||||||
|
</Actions>
|
||||||
</h5>
|
</h5>
|
||||||
<!-- FIXME: make sure the editor is disabled when canEdit is false -->
|
|
||||||
<VueEasymde ref="markdownEditor"
|
<div v-if="!descriptionEditing"
|
||||||
|
id="description-preview"
|
||||||
|
@click="clickedPreview"
|
||||||
|
v-html="renderedDescription" />
|
||||||
|
<VueEasymde v-else
|
||||||
|
ref="markdownEditor"
|
||||||
:value="copiedCard.description"
|
:value="copiedCard.description"
|
||||||
:configs="mdeConfig"
|
:configs="mdeConfig"
|
||||||
@input="updateDescription" />
|
@input="updateDescription" />
|
||||||
@@ -168,6 +181,11 @@ import { CollectionList } from 'nextcloud-vue-collections'
|
|||||||
import CardSidebarTabAttachments from './CardSidebarTabAttachments'
|
import CardSidebarTabAttachments from './CardSidebarTabAttachments'
|
||||||
import CardSidebarTabComments from './CardSidebarTabComments'
|
import CardSidebarTabComments from './CardSidebarTabComments'
|
||||||
import CardSidebarTabActivity from './CardSidebarTabActivity'
|
import CardSidebarTabActivity from './CardSidebarTabActivity'
|
||||||
|
import MarkdownIt from 'markdown-it'
|
||||||
|
import MarkdownItTaskLists from 'markdown-it-task-lists'
|
||||||
|
|
||||||
|
const markdownIt = new MarkdownIt()
|
||||||
|
markdownIt.use(MarkdownItTaskLists, { enabled: true, label: true, labelAfter: true })
|
||||||
|
|
||||||
const capabilities = window.OC.getCapabilities()
|
const capabilities = window.OC.getCapabilities()
|
||||||
|
|
||||||
@@ -202,8 +220,10 @@ export default {
|
|||||||
addedLabelToCard: null,
|
addedLabelToCard: null,
|
||||||
copiedCard: null,
|
copiedCard: null,
|
||||||
allLabels: null,
|
allLabels: null,
|
||||||
desc: null,
|
|
||||||
saving: false,
|
saving: false,
|
||||||
|
markdownIt: null,
|
||||||
|
descriptionEditing: false,
|
||||||
mdeConfig: {
|
mdeConfig: {
|
||||||
autoDownloadFontAwesome: false,
|
autoDownloadFontAwesome: false,
|
||||||
spellChecker: false,
|
spellChecker: false,
|
||||||
@@ -265,14 +285,30 @@ export default {
|
|||||||
this.saving = false
|
this.saving = false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
renderedDescription() {
|
||||||
|
return markdownIt.render(this.copiedCard.description)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'currentCard': {
|
currentCard() {
|
||||||
immediate: true,
|
this.initialize()
|
||||||
handler() {
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
setInterval(this.updateRelativeTimestamps, 10000)
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
clearInterval(this.updateRelativeTimestamps)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initialize()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initialize() {
|
||||||
if (!this.currentCard) {
|
if (!this.currentCard) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.copiedCard = JSON.parse(JSON.stringify(this.currentCard))
|
this.copiedCard = JSON.parse(JSON.stringify(this.currentCard))
|
||||||
this.allLabels = this.currentCard.labels
|
this.allLabels = this.currentCard.labels
|
||||||
|
|
||||||
@@ -285,15 +321,36 @@ export default {
|
|||||||
this.desc = this.currentCard.description
|
this.desc = this.currentCard.description
|
||||||
this.updateRelativeTimestamps()
|
this.updateRelativeTimestamps()
|
||||||
},
|
},
|
||||||
|
showEditor() {
|
||||||
|
if (!this.canEdit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.descriptionEditing = true
|
||||||
},
|
},
|
||||||
|
hideEditor() {
|
||||||
|
this.descriptionEditing = false
|
||||||
},
|
},
|
||||||
created() {
|
clickedPreview(e) {
|
||||||
setInterval(this.updateRelativeTimestamps, 10000)
|
if (e.target.getAttribute('type') === 'checkbox') {
|
||||||
|
const clickedIndex = [...document.querySelector('#description-preview').querySelectorAll('input')].findIndex((li) => li.id === e.target.id)
|
||||||
|
const reg = /\[(X|\s|_|-)\]/ig
|
||||||
|
let nth = 0
|
||||||
|
const updatedDescription = this.copiedCard.description.replace(reg, (match, i, original) => {
|
||||||
|
let result = match
|
||||||
|
if ('' + nth++ === '' + clickedIndex) {
|
||||||
|
if (match.match(/^\[\s\]/i)) {
|
||||||
|
result = match.replace(/\[\s\]/i, '[x]')
|
||||||
|
}
|
||||||
|
if (match.match(/^\[x\]/i)) {
|
||||||
|
result = match.replace(/\[x\]/i, '[ ]')
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
})
|
||||||
|
this.updateDescription(updatedDescription)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
destroyed() {
|
|
||||||
clearInterval(this.updateRelativeTimestamps)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateRelativeTimestamps() {
|
updateRelativeTimestamps() {
|
||||||
this.lastModifiedRelative = OC.Util.relativeModifiedDate(this.currentCard.lastModified * 1000)
|
this.lastModifiedRelative = OC.Util.relativeModifiedDate(this.currentCard.lastModified * 1000)
|
||||||
this.lastCreatedRemative = OC.Util.relativeModifiedDate(this.currentCard.createdAt * 1000)
|
this.lastCreatedRemative = OC.Util.relativeModifiedDate(this.currentCard.createdAt * 1000)
|
||||||
@@ -377,6 +434,8 @@ export default {
|
|||||||
@import "~easymde/dist/easymde.min.css";
|
@import "~easymde/dist/easymde.min.css";
|
||||||
.vue-easymde, .CodeMirror {
|
.vue-easymde, .CodeMirror {
|
||||||
border: none;
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
.editor-preview,
|
.editor-preview,
|
||||||
.editor-statusbar {
|
.editor-statusbar {
|
||||||
@@ -398,11 +457,16 @@ export default {
|
|||||||
|
|
||||||
.icon-info {
|
.icon-info {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 16px;
|
width: 32px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
float: right;
|
float: right;
|
||||||
opacity: .7;
|
opacity: .7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-toggle, .icon-rename {
|
||||||
|
float: right;
|
||||||
|
margin-top: -14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aside::v-deep section {
|
aside::v-deep section {
|
||||||
@@ -469,4 +533,13 @@ export default {
|
|||||||
.multiselect.multiselect--active::v-deep .multiselect__tags-wrap {
|
.multiselect.multiselect--active::v-deep .multiselect__tags-wrap {
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#description-preview {
|
||||||
|
min-height: 100px;
|
||||||
|
|
||||||
|
&::v-deep input {
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user