Skip to content

Commit 24087de

Browse files
committed
stable28: fix comment deletion
Signed-off-by: greta <gretadoci@gmail.com>
1 parent 14bf5c4 commit 24087de

File tree

5 files changed

+96
-97
lines changed

5 files changed

+96
-97
lines changed

apps/comments/src/comments-activity-tab.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,16 @@
11
/**
2-
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
3-
*
4-
* @author Ferdinand Thiessen <opensource@fthiessen.de>
5-
*
6-
* @license AGPL-3.0-or-later
7-
*
8-
* This program is free software: you can redistribute it and/or modify
9-
* it under the terms of the GNU Affero General Public License as
10-
* published by the Free Software Foundation, either version 3 of the
11-
* License, or (at your option) any later version.
12-
*
13-
* This program is distributed in the hope that it will be useful,
14-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16-
* GNU Affero General Public License for more details.
17-
*
18-
* You should have received a copy of the GNU Affero General Public License
19-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20-
*
2+
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
214
*/
225
import moment from '@nextcloud/moment'
23-
import Vue from 'vue'
6+
import Vue, { type ComponentPublicInstance } from 'vue'
247
import logger from './logger.js'
258
import { getComments } from './services/GetComments.js'
269

10+
import { PiniaVuePlugin, createPinia } from 'pinia'
11+
12+
Vue.use(PiniaVuePlugin)
13+
2714
let ActivityTabPluginView
2815
let ActivityTabPluginInstance
2916

@@ -33,18 +20,22 @@ let ActivityTabPluginInstance
3320
export function registerCommentsPlugins() {
3421
window.OCA.Activity.registerSidebarAction({
3522
mount: async (el, { context, fileInfo, reload }) => {
23+
const pinia = createPinia()
24+
3625
if (!ActivityTabPluginView) {
37-
const { default: ActivityCommmentAction } = await import('./views/ActivityCommentAction.vue')
38-
ActivityTabPluginView = Vue.extend(ActivityCommmentAction)
26+
const { default: ActivityCommentAction } = await import('./views/ActivityCommentAction.vue')
27+
/** @ts-expect-error Types are broken for Vue2 */
28+
ActivityTabPluginView = Vue.extend(ActivityCommentAction)
3929
}
4030
ActivityTabPluginInstance = new ActivityTabPluginView({
31+
el,
4132
parent: context,
33+
pinia,
4234
propsData: {
4335
reloadCallback: reload,
4436
resourceId: fileInfo.id,
4537
},
4638
})
47-
ActivityTabPluginInstance.$mount(el)
4839
logger.info('Comments plugin mounted in Activity sidebar action', { fileInfo })
4940
},
5041
unmount: () => {
@@ -59,23 +50,27 @@ export function registerCommentsPlugins() {
5950
const { data: comments } = await getComments({ resourceType: 'files', resourceId: fileInfo.id }, { limit, offset })
6051
logger.debug('Loaded comments', { fileInfo, comments })
6152
const { default: CommentView } = await import('./views/ActivityCommentEntry.vue')
53+
/** @ts-expect-error Types are broken for Vue2 */
6254
const CommentsViewObject = Vue.extend(CommentView)
6355

6456
return comments.map((comment) => ({
65-
timestamp: moment(comment.props.creationDateTime).toDate().getTime(),
66-
mount(element, { context, reload }) {
57+
_CommentsViewInstance: undefined as ComponentPublicInstance | undefined,
58+
59+
timestamp: moment(comment.props?.creationDateTime).toDate().getTime(),
60+
61+
mount(element: HTMLElement, { context, reload }) {
6762
this._CommentsViewInstance = new CommentsViewObject({
63+
el: element,
6864
parent: context,
6965
propsData: {
7066
comment,
7167
resourceId: fileInfo.id,
7268
reloadCallback: reload,
7369
},
7470
})
75-
this._CommentsViewInstance.$mount(element)
7671
},
7772
unmount() {
78-
this._CommentsViewInstance.$destroy()
73+
this._CommentsViewInstance?.$destroy()
7974
},
8075
}))
8176
})

apps/comments/src/components/Comment.vue

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,10 @@
11
<!--
2-
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
3-
-
4-
- @author John Molakvoæ <skjnldsv@protonmail.com>
5-
-
6-
- @license GNU AGPL version 3 or any later version
7-
-
8-
- This program is free software: you can redistribute it and/or modify
9-
- it under the terms of the GNU Affero General Public License as
10-
- published by the Free Software Foundation, either version 3 of the
11-
- License, or (at your option) any later version.
12-
-
13-
- This program is distributed in the hope that it will be useful,
14-
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15-
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16-
- GNU Affero General Public License for more details.
17-
-
18-
- You should have received a copy of the GNU Affero General Public License
19-
- along with this program. If not, see <http://www.gnu.org/licenses/>.
20-
-
21-
-->
2+
- SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
225
<template>
236
<component :is="tag"
24-
v-show="!deleted"
7+
v-show="!deleted && !isLimbo"
258
:class="{'comment--loading': loading}"
269
class="comment">
2710
<!-- Comment header toolbar -->
@@ -69,7 +52,10 @@
6952
<div v-if="id && loading" class="comment_loading icon-loading-small" />
7053

7154
<!-- Relative time to the comment creation -->
72-
<Moment v-else-if="creationDateTime" class="comment__timestamp" :timestamp="timestamp" />
55+
<NcDateTime v-else-if="creationDateTime"
56+
class="comment__timestamp"
57+
:timestamp="timestamp"
58+
:ignore-seconds="true" />
7359
</div>
7460

7561
<!-- Message editor -->
@@ -119,22 +105,24 @@
119105
<script>
120106
import { getCurrentUser } from '@nextcloud/auth'
121107
import { translate as t } from '@nextcloud/l10n'
122-
import moment from '@nextcloud/moment'
123108
124109
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
125110
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
126111
import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js'
127112
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
128113
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
114+
import NcDateTime from '@nextcloud/vue/dist/Components/NcDateTime.js'
115+
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
129116
import RichEditorMixin from '@nextcloud/vue/dist/Mixins/richEditor.js'
130117
131118
import IconArrowRight from 'vue-material-design-icons/ArrowRight.vue'
132119
import IconClose from 'vue-material-design-icons/Close.vue'
133120
import IconDelete from 'vue-material-design-icons/Delete.vue'
134121
import IconEdit from 'vue-material-design-icons/Pencil.vue'
135122
136-
import Moment from './Moment.vue'
137123
import CommentMixin from '../mixins/CommentMixin.js'
124+
import { mapStores } from 'pinia'
125+
import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.js'
138126
139127
// Dynamic loading
140128
const NcRichContenteditable = () => import('@nextcloud/vue/dist/Components/NcRichContenteditable.js')
@@ -147,15 +135,15 @@ export default {
147135
IconClose,
148136
IconDelete,
149137
IconEdit,
150-
Moment,
151138
NcActionButton,
152139
NcActions,
153140
NcActionSeparator,
154141
NcAvatar,
155142
NcButton,
143+
NcDateTime,
144+
NcLoadingIcon,
156145
NcRichContenteditable,
157146
},
158-
159147
mixins: [RichEditorMixin, CommentMixin],
160148
161149
inheritAttrs: false,
@@ -207,6 +195,7 @@ export default {
207195
},
208196
209197
computed: {
198+
...mapStores(useDeletedCommentLimbo),
210199
211200
/**
212201
* Is the current user the author of this comment
@@ -233,9 +222,15 @@ export default {
233222
return !this.localMessage || this.localMessage.trim() === ''
234223
},
235224
225+
/**
226+
* Timestamp of the creation time (in ms UNIX time)
227+
*/
236228
timestamp() {
237-
// seconds, not milliseconds
238-
return parseInt(moment(this.creationDateTime).format('x'), 10) / 1000
229+
return Date.parse(this.creationDateTime)
230+
},
231+
232+
isLimbo() {
233+
return this.deletedCommentLimboStore.checkForId(this.id)
239234
},
240235
},
241236
@@ -350,7 +345,7 @@ $comment-padding: 10px;
350345
351346
&__submit {
352347
position: absolute !important;
353-
bottom: 0;
348+
bottom: 5px;
354349
right: 0;
355350
}
356351

apps/comments/src/mixins/CommentMixin.js

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
11
/**
2-
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
3-
*
4-
* @author John Molakvoæ <skjnldsv@protonmail.com>
5-
*
6-
* @license AGPL-3.0-or-later
7-
*
8-
* This program is free software: you can redistribute it and/or modify
9-
* it under the terms of the GNU Affero General Public License as
10-
* published by the Free Software Foundation, either version 3 of the
11-
* License, or (at your option) any later version.
12-
*
13-
* This program is distributed in the hope that it will be useful,
14-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16-
* GNU Affero General Public License for more details.
17-
*
18-
* You should have received a copy of the GNU Affero General Public License
19-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20-
*
2+
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
214
*/
225

236
import { showError, showUndo, TOAST_UNDO_TIMEOUT } from '@nextcloud/dialogs'
247
import NewComment from '../services/NewComment.js'
258
import DeleteComment from '../services/DeleteComment.js'
269
import EditComment from '../services/EditComment.js'
10+
import { mapStores } from 'pinia'
11+
import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.js'
2712
import logger from '../logger.js'
2813

2914
export default {
@@ -54,6 +39,10 @@ export default {
5439
}
5540
},
5641

42+
computed: {
43+
...mapStores(useDeletedCommentLimbo),
44+
},
45+
5746
methods: {
5847
// EDITION
5948
onEdit() {
@@ -81,11 +70,14 @@ export default {
8170

8271
// DELETION
8372
onDeleteWithUndo() {
73+
this.$emit('delete')
8474
this.deleted = true
75+
this.deletedCommentLimboStore.addId(this.id)
8576
const timeOutDelete = setTimeout(this.onDelete, TOAST_UNDO_TIMEOUT)
8677
showUndo(t('comments', 'Comment deleted'), () => {
8778
clearTimeout(timeOutDelete)
8879
this.deleted = false
80+
this.deletedCommentLimboStore.removeId(this.id)
8981
})
9082
},
9183
async onDelete() {
@@ -97,6 +89,7 @@ export default {
9789
showError(t('comments', 'An error occurred while trying to delete the comment'))
9890
console.error(error)
9991
this.deleted = false
92+
this.deletedCommentLimboStore.removeId(this.id)
10093
}
10194
},
10295

apps/comments/src/services/CommentsInstance.js

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
11
/**
2-
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
3-
*
4-
* @author John Molakvoæ <skjnldsv@protonmail.com>
5-
*
6-
* @license AGPL-3.0-or-later
7-
*
8-
* This program is free software: you can redistribute it and/or modify
9-
* it under the terms of the GNU Affero General Public License as
10-
* published by the Free Software Foundation, either version 3 of the
11-
* License, or (at your option) any later version.
12-
*
13-
* This program is distributed in the hope that it will be useful,
14-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16-
* GNU Affero General Public License for more details.
17-
*
18-
* You should have received a copy of the GNU Affero General Public License
19-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20-
*
2+
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
214
*/
225

23-
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
24-
import { getRequestToken } from '@nextcloud/auth'
6+
import { getCSPNonce } from '@nextcloud/auth'
7+
import { t, n } from '@nextcloud/l10n'
8+
import { PiniaVuePlugin, createPinia } from 'pinia'
259
import Vue from 'vue'
2610
import CommentsApp from '../views/Comments.vue'
2711
import logger from '../logger.js'
2812

13+
Vue.use(PiniaVuePlugin)
2914
// eslint-disable-next-line camelcase
30-
__webpack_nonce__ = btoa(getRequestToken())
15+
__webpack_nonce__ = getCSPNonce()
3116

3217
// Add translates functions
3318
Vue.mixin({
@@ -51,13 +36,16 @@ export default class CommentInstance {
5136
* @param {object} options the vue options (propsData, parent, el...)
5237
*/
5338
constructor(resourceType = 'files', options = {}) {
39+
const pinia = createPinia()
40+
5441
// Merge options and set `resourceType` property
5542
options = {
5643
...options,
5744
propsData: {
5845
...(options.propsData ?? {}),
5946
resourceType,
6047
},
48+
pinia,
6149
}
6250
// Init Comments component
6351
const View = Vue.extend(CommentsApp)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { defineStore } from 'pinia'
7+
8+
export const useDeletedCommentLimbo = defineStore('deletedCommentLimbo', {
9+
state: () => ({
10+
idsInLimbo: [],
11+
}),
12+
actions: {
13+
addId(id) {
14+
this.idsInLimbo.push(id)
15+
},
16+
17+
removeId(id) {
18+
const index = this.idsInLimbo.indexOf(id)
19+
if (index > -1) {
20+
this.idsInLimbo.splice(index, 1)
21+
}
22+
},
23+
24+
checkForId(id) {
25+
this.idsInLimbo.includes(id)
26+
},
27+
},
28+
})

0 commit comments

Comments
 (0)