Skip to content

Commit

Permalink
Changing description ans acceptance criteria refactored; use unicode …
Browse files Browse the repository at this point in the history
…to base64 everywhere
  • Loading branch information
ErikVerheul committed Aug 6, 2024
1 parent f3b0701 commit 205f6c7
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 150 deletions.
7 changes: 6 additions & 1 deletion src/common_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export function b64ToUni(bytes) {
return new TextDecoder().decode(base64ToBytes(bytes))
}

export function areStringsEqual(str1, str2) {
const retVal = str1.localeCompare(str2)
return retVal === 0
}

//////////////// expand, collapse and show or hide the children of the node ////////////
export function showNode(node) {
if (node) {
Expand Down Expand Up @@ -185,4 +190,4 @@ export function isValidEmail(email) {
return re.test(email)
}

export default { uniTob64, b64ToUni, expandNode, collapseNode, showNode, hideNode, addToArray, createId, createLoadEventText, dedup, getLocationInfo, getSprintById, getSprintNameById, localTimeAndMilis, removeFromArray, isValidEmail }
export default { uniTob64, b64ToUni, areStringsEqual, expandNode, collapseNode, showNode, hideNode, addToArray, createId, createLoadEventText, dedup, getLocationInfo, getSprintById, getSprintNameById, localTimeAndMilis, removeFromArray, isValidEmail }
6 changes: 3 additions & 3 deletions src/components/admin/admin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { STATE, LEVEL } from '../../constants.js'
import { createId } from '../../common_functions.js'
import { uniTob64, createId } from '../../common_functions.js'
import common_admin from './common_admin'
import store from '../../store/store.js'

Expand Down Expand Up @@ -81,8 +81,8 @@ const methods = {
reqarea: null,
title: this.productTitle,
followers: [],
description: window.btoa(''),
acceptanceCriteria: window.btoa('<p>Please do not neglect</p>'),
description: uniTob64('<p><br></p>'),
acceptanceCriteria: uniTob64('<p>Please do not neglect</p>'),
priority,
comments: [{
ignoreEvent: 'comments initiated',
Expand Down
35 changes: 17 additions & 18 deletions src/components/views/coarse_product/c_product_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,25 +103,24 @@ const methods = {

/* Event handling */
onNodesSelected(fromContextMenu) {
// update explicitly as the tree is not receiving focus due to the "user-select: none" css setting causing that @blur on the editor is not emitted
if (this.isDescriptionEdited) this.updateDescription(this.getPreviousNodeSelected)
if (this.isAcceptanceEdited) this.updateAcceptance(this.getPreviousNodeSelected)
// load the document
store.dispatch('loadDoc', {
id: this.getLastSelectedNode._id,
onSuccessCallback: () => {
// preset the req area color if available
this.selReqAreaColor = this.getLastSelectedNode.data.reqAreaItemColor
// if the user clicked on a node of another product (not root)
if (this.getLastSelectedNode._id !== 'root' && store.state.currentProductId !== this.getLastSelectedNode.productId) {
// update current productId and title
store.commit('switchCurrentProduct', this.getLastSelectedNode.productId)
}
if (this.getLastSelectedNode._id !== 'requirement-areas') {
if (!fromContextMenu) this.showSelectionEvent(store.state.selectedNodes)
} else this.showLastEvent('Create / maintain Requirement Areas here', SEV.INFO)
const onSuccessCallback = () => {
// preset the req area color if available
this.selReqAreaColor = this.getLastSelectedNode.data.reqAreaItemColor
// if the user clicked on a node of another product (not root)
if (this.getLastSelectedNode._id !== 'root' && store.state.currentProductId !== this.getLastSelectedNode.productId) {
// update current productId and title
store.commit('switchCurrentProduct', this.getLastSelectedNode.productId)
}
})
if (this.getLastSelectedNode._id !== 'requirement-areas') {
if (!fromContextMenu) this.showSelectionEvent(store.state.selectedNodes)
} else this.showLastEvent('Create / maintain Requirement Areas here', SEV.INFO)
}

// update explicitly as the tree is not receiving focus due to the "user-select: none" css setting causing that @blur on the editor is not emitted
if (this.isDescriptionEdited) { this.updateDescription({ node: this.getPreviousNodeSelected, cb: onSuccessCallback }) } else
if (this.isAcceptanceEdited) { this.updateAcceptance({ node: this.getPreviousNodeSelected, cb: onSuccessCallback }) } else
// load the selected document
store.dispatch('loadDoc', { id: this.getLastSelectedNode._id, onSuccessCallback })
},

/* Use this event to check if the drag is allowed. If not, issue a warning */
Expand Down
10 changes: 5 additions & 5 deletions src/components/views/coarse_product/c_product_view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
<h3 align="right">State:</h3>
</BCol>
<BCol cols="1">
<h3 align="right">
<h3 align="right">
<BDropdown right :text=getItemStateText(store.state.currentDoc.state)>
<BDropdownItem @click="onStateChange(STATE.NEW)">{{ getItemStateText(STATE.NEW) }}</BDropdownItem>
<BDropdownItem @click="onStateChange(STATE.READY)">{{ getItemStateText(STATE.READY) }}</BDropdownItem>
Expand Down Expand Up @@ -204,7 +204,7 @@
</div>
</div>
<div class="pane" :style="{ height: '30%', maxHeight: '60%', minWidth: '100%', maxWidth: '100%' }">
<QuillEditor v-model:content="description" contentType="html" @update:content="initNewDescription" @blur="updateDescription()"></QuillEditor>
<QuillEditor v-model:content="description" contentType="html" @update:content="initNewDescription" @blur="updateDescription({ node: getLastSelectedNode, cb: null })"></QuillEditor>
</div>
<template v-if="!isReqAreaItemSelected">
<multipane-resizer></multipane-resizer>
Expand All @@ -214,7 +214,7 @@
</div>
</div>
<div class="pane" :style="{ height: '30%', maxHeight: '60%', minWidth: '100%', maxWidth: '100%' }">
<QuillEditor v-model:content="acceptanceCriteria" contentType="html" @update:content="initNewAcceptance" @blur="updateAcceptance()"></QuillEditor>
<QuillEditor v-model:content="acceptanceCriteria" contentType="html" @update:content="initNewAcceptance" @blur="updateAcceptance({ node: getLastSelectedNode, cb: null })"></QuillEditor>
</div>
</template>
<multipane-resizer></multipane-resizer>
Expand All @@ -230,8 +230,8 @@
<div class="d-table-cell tar">
<BButton v-if="store.state.selectedForView === 'comments' && !isCommentsFilterActive || store.state.selectedForView === 'history' && !isHistoryFilterActive" variant="primary"
@click="startFiltering = true">Filter {{ store.state.selectedForView }}</BButton>
<BButton v-else-if="store.state.selectedForView !== 'attachments'" variant="primary" @click="stopFiltering">Clear {{ store.state.selectedForView }} filter</BButton>
<BButton v-else @click="doAddition = true" variant="primary">Add attachments</BButton>
<BButton v-else-if="store.state.selectedForView !== 'attachments'" variant="primary" @click="stopFiltering">Clear {{ store.state.selectedForView }} filter</BButton>
<BButton v-else @click="doAddition = true" variant="primary">Add attachments</BButton>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/common_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ const methods = {
conditionalFor: [],
title: newNode.title,
followers: newNode.data.followers,
description: uniTob64(''),
description: uniTob64('<p><br></p>'),
acceptanceCriteria: newNode.level < this.TASKLEVEL ? uniTob64('<p>Please do not neglect</p>') : uniTob64('<p>See the acceptance criteria of the story/spike/defect.</p>'),
priority: newNode.data.priority,
comments: [{
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/common_listings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ function data() {
editMyComment: false,
editMyHistComment: false,
commentObjToBeReplaced: {},
myLastCommentText: "<p></p>",
myLastHistCommentText: "<p></p>"
myLastCommentText: "<p><br></p>",
myLastHistCommentText: "<p><br></p>"
}
}
Expand Down
56 changes: 35 additions & 21 deletions src/components/views/common_view.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SEV, LEVEL, STATE } from '../../constants.js'
import { collapseNode } from '../../common_functions.js'
import { areStringsEqual } from '../../common_functions.js'
import { constants, authorization, utilities } from '../mixins/generic.js'
import store from '../../store/store.js'

Expand All @@ -14,10 +14,8 @@ function data() {
spikeSubtype: 1,
defectSubtype: 2,
docToUpdate: null,
newDescription: "<p></p>",
newAcceptance: "<p></p>",
isDescriptionEdited: false,
isAcceptanceEdited: false,
newDescription: "<p><br></p>",
newAcceptance: "<p><br></p>",
editorToolbar: [
[{ header: [false, 1, 2, 3, 4, 5, 6] }],
['bold', 'italic', 'underline', 'strike'],
Expand All @@ -30,11 +28,13 @@ function data() {
// comments, history and attachments
doAddition: false,
startFiltering: false,
isDescriptionEdited: false,
isAcceptanceEdited: false,
isCommentsFilterActive: false,
isHistoryFilterActive: false,
newComment: "<p></p>",
newComment: "<p><br></p>",
fileInfo: null,
newHistory: "<p></p>",
newHistory: "<p><br></p>",
filterForCommentPrep: '',
filterForHistoryPrep: '',
// move data
Expand Down Expand Up @@ -143,7 +143,7 @@ const computed = {
let retVal = store.state.currentDoc.description
if (retVal === "") {
// correct empty field
retVal = "<p></p>"
retVal = "<p><br></p>"
}
return retVal
},
Expand All @@ -157,7 +157,7 @@ const computed = {
let retVal = store.state.currentDoc.acceptanceCriteria
if (retVal === "") {
// correct empty field
retVal = "<p></p>"
retVal = "<p><br></p>"
}
return retVal
},
Expand All @@ -182,14 +182,14 @@ const watch = {
}
if (store.state.selectedForView === 'comments') {
if (this.canCreateComments) {
this.newComment = "<p></p>"
this.newComment = "<p><br></p>"
this.$refs.commentsEditorRef.show()
} else {
this.showLastEvent('Sorry, your assigned role(s) disallow you to create comments', SEV.WARNING)
}
}
if (store.state.selectedForView === 'history') {
this.newHistory = "<p></p>"
this.newHistory = "<p><br></p>"
this.$refs.historyEditorRef.show()
}
}
Expand Down Expand Up @@ -552,32 +552,46 @@ const methods = {
},

/* Tree and database update methods */
updateDescription(node = this.getLastSelectedNode) {
if (this.isDescriptionEdited && (store.state.currentDoc.description !== this.newDescription)) {
// update skipped when not changed
updateDescription(payload) {
// node is either the current node (descripton changed and a click outside description and not on a node) or
// the previous selected node (description changed and clicked on a node)
const node = payload.node
if (areStringsEqual(store.state.currentDoc.description, this.newDescription)) {
// update skipped when not changed; load the doc of last clicked node
this.isDescriptionEdited = false
store.dispatch('loadDoc', { id: this.getLastSelectedNode._id, onSuccessCallback: payload.cb })
} else {
const toDispatch = [{ loadDoc: { id: this.getLastSelectedNode._id, onSuccessCallback: payload.cb } }]
if (this.haveAccessInTree(node.productId, this.getCurrentItemLevel, store.state.currentDoc.team, 'change the description of this item')) {
store.dispatch('saveDescription', {
node,
newDescription: this.newDescription,
timestamp: Date.now()
timestamp: Date.now(),
toDispatch
})
}
} else this.isDescriptionEdited = false
}
},

updateAcceptance(node = this.getLastSelectedNode) {
updateAcceptance(payload) {
// node is either the current node (descripton changed and a click outside description and not on a node) or
// the previous selected node (description changed and clicked on a node)
const node = payload.node
if (node._id !== 'requirement-areas' && node.parentId !== 'requirement-areas') {
if (this.isAcceptanceEdited && (store.state.currentDoc.acceptanceCriteria !== this.newAcceptance)) {
// update skipped when not changed
if (areStringsEqual(store.state.currentDoc.acceptanceCriteria, this.newAcceptance)) {
// update skipped when not changed; load the doc of last clicked node
this.isAcceptanceEdited = false
store.dispatch('loadDoc', { id: this.getLastSelectedNode._id, onSuccessCallback: payload.cb })
} else {
const toDispatch = [{ loadDoc: { id: this.getLastSelectedNode._id, onSuccessCallback: payload.cb } }]
if (this.haveAccessInTree(node.productId, this.getCurrentItemLevel, store.state.currentDoc.team, 'change the acceptance criteria of this item')) {
store.dispatch('saveAcceptance', {
node,
newAcceptance: this.newAcceptance,
timestamp: Date.now()
timestamp: Date.now(),
toDispatch
})
}
} else this.isAcceptanceEdited = false
}
}
},
Expand Down
53 changes: 8 additions & 45 deletions src/components/views/detail_product/d_product_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ const methods = {

/* event handling */
onNodesSelected(fromContextMenu) {
const afterNewItemLoad = () => {
const onSuccessCallback = () => {
this.isDescriptionEdited = false
this.isAcceptanceEdited = false
// if the user clicked on a node of another product (not root)
const currentProductId = store.state.currentProductId
if (this.getLastSelectedNode._id !== 'root' && currentProductId !== this.getLastSelectedNode.productId) {
Expand All @@ -125,51 +127,12 @@ const methods = {
}
if (!fromContextMenu) this.showSelectionEvent(store.state.selectedNodes)
}
const toDispatch = [{
loadDoc: {
id: this.getLastSelectedNode._id,
onSuccessCallback: afterNewItemLoad()
}
}]
// update explicitly as the tree is not receiving focus due to the "user-select: none" css setting causing that @blur on the editor is not emitted immediately
if (this.isDescriptionEdited) {
this.isDescriptionEdited = false
const node = this.getPreviousNodeSelected
if (store.state.currentDoc.description !== this.newDescription) {
// update skipped when not changed
if (this.haveAccessInTree(node.productId, this.getCurrentItemLevel, store.state.currentDoc.team, 'change the description of this item')) {
store.dispatch('saveDescription', {
node,
newDescription: this.newDescription,
timestamp: Date.now(),
toDispatch
})
}
}
} else if (this.isAcceptanceEdited) {
this.isAcceptanceEdited = false
const node = this.getPreviousNodeSelected
if (node._id !== 'requirement-areas' && node.parentId !== 'requirement-areas') {
// update skipped when not changed
if (store.state.currentDoc.acceptanceCriteria !== this.newAcceptance) {
if (this.haveAccessInTree(node.productId, this.getCurrentItemLevel, store.state.currentDoc.team, 'change the acceptance criteria of this item')) {
store.dispatch('saveAcceptance', {
node,
newAcceptance: this.newAcceptance,
timestamp: Date.now(),
toDispatch
})
}
}
}

} else {
// just load the selected document
store.dispatch('loadDoc', {
id: this.getLastSelectedNode._id,
onSuccessCallback: afterNewItemLoad()
})
}
// update explicitly as the tree is not receiving focus due to the "user-select: none" css setting causing that @blur on the editor is not emitted
if (this.isDescriptionEdited) { this.updateDescription({ node: this.getPreviousNodeSelected, cb: onSuccessCallback }) } else
if (this.isAcceptanceEdited) { this.updateAcceptance({ node: this.getPreviousNodeSelected, cb: onSuccessCallback }) } else
// load the selected document
store.dispatch('loadDoc', { id: this.getLastSelectedNode._id, onSuccessCallback })
},

/* Use this event to check if the drag is allowed. If not, issue a warning */
Expand Down
5 changes: 3 additions & 2 deletions src/components/views/detail_product/d_product_view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@
</div>
</div>
<div class="pane" :style="{ height: '30%', maxHeight: '60%', minWidth: '100%', maxWidth: '100%' }">
<QuillEditor v-model:content="description" contentType="html" @update:content="initNewDescription" @blur="updateDescription()"></QuillEditor>
<QuillEditor v-model:content="description" contentType="html" @update:content="initNewDescription" @blur="updateDescription({ node: getLastSelectedNode, cb: null })">
</QuillEditor>
</div>
<multipane-resizer></multipane-resizer>
<div class="pane" :style="{ height: '45px', top: '5px' }">
Expand All @@ -238,7 +239,7 @@
</div>
</div>
<div class="pane" :style="{ height: '30%', maxHeight: '60%', minWidth: '100%', maxWidth: '100%' }">
<QuillEditor v-model:content="acceptanceCriteria" contentType="html" @update:content="initNewAcceptance" @blur="updateAcceptance()"></QuillEditor>
<QuillEditor v-model:content="acceptanceCriteria" contentType="html" @update:content="initNewAcceptance" @blur="updateAcceptance({ node: getLastSelectedNode, cb: null })"></QuillEditor>
</div>
<multipane-resizer></multipane-resizer>
<div class="pane" :style="{ height: '75px', top: '5px' }">
Expand Down
14 changes: 7 additions & 7 deletions src/store/modules/initdb.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LEVEL, MISC } from '../../constants.js'
import { createId } from '../../common_functions.js'
import { uniTob64, createId } from '../../common_functions.js'
import globalAxios from 'axios'

// IMPORTANT: all updates on the backlogitem documents must add history in order for the changes feed to work properly (if omitted the previous event will be processed again)
Expand Down Expand Up @@ -499,8 +499,8 @@ const actions = {
title: 'The root of all products in this database',
team: 'n/a',
followers: [],
description: window.btoa('<p>Database root document</p>'),
acceptanceCriteria: window.btoa('<p>not applicable</p>'),
description: uniTob64('<p>Database root document</p>'),
acceptanceCriteria: uniTob64('<p>not applicable</p>'),
priority: 0,
comments: [{
ignoreEvent: 'comments initiated',
Expand Down Expand Up @@ -579,8 +579,8 @@ const actions = {
spikepersonhours: 0,
title: 'REQUIREMENT AREAS',
followers: [],
description: window.btoa('<p>To insert one or more requirement areas inside this node right-click on this nodes title in the tree view.</p>'),
acceptanceCriteria: window.btoa('<p>n/a</p>'),
description: uniTob64('<p>To insert one or more requirement areas inside this node right-click on this nodes title in the tree view.</p>'),
acceptanceCriteria: uniTob64('<p>n/a</p>'),
// do not set a priority, must be null
comments: [{
ignoreEvent: 'comments initiated',
Expand Down Expand Up @@ -625,8 +625,8 @@ const actions = {
reqarea: null,
title,
followers: [],
description: window.btoa(''),
acceptanceCriteria: window.btoa('<p>Please do not neglect</p>'),
description: uniTob64('<p><br></p>'),
acceptanceCriteria: uniTob64('<p>Please do not neglect</p>'),
priority: 0,
comments: [{
ignoreEvent: 'comments initiated',
Expand Down
Loading

0 comments on commit 205f6c7

Please sign in to comment.