Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>pull/41491/head
parent
9c3350b313
commit
db2fec1cec
@ -0,0 +1,85 @@ |
||||
/** |
||||
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de> |
||||
* |
||||
* @author Ferdinand Thiessen <opensource@fthiessen.de> |
||||
* |
||||
* @license AGPL-3.0-or-later |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
import moment from '@nextcloud/moment' |
||||
import Vue from 'vue' |
||||
import logger from './logger.js' |
||||
import { getComments } from './services/GetComments.js' |
||||
|
||||
let ActivityTabPluginView |
||||
let ActivityTabPluginInstance |
||||
|
||||
/** |
||||
* Register the comments plugins for the Activity sidebar |
||||
*/ |
||||
export function registerCommentsPlugins() { |
||||
window.OCA.Activity.registerSidebarAction({ |
||||
mount: async (el, { context, fileInfo, reload }) => { |
||||
if (!ActivityTabPluginView) { |
||||
const { default: ActivityCommmentAction } = await import('./views/ActivityCommentAction.vue') |
||||
ActivityTabPluginView = Vue.extend(ActivityCommmentAction) |
||||
} |
||||
ActivityTabPluginInstance = new ActivityTabPluginView({ |
||||
parent: context, |
||||
propsData: { |
||||
reloadCallback: reload, |
||||
ressourceId: fileInfo.id, |
||||
}, |
||||
}) |
||||
ActivityTabPluginInstance.$mount(el) |
||||
logger.info('Comments plugin mounted in Activity sidebar action', { fileInfo }) |
||||
}, |
||||
unmount: () => { |
||||
// destroy previous instance if available
|
||||
if (ActivityTabPluginInstance) { |
||||
ActivityTabPluginInstance.$destroy() |
||||
} |
||||
}, |
||||
}) |
||||
|
||||
window.OCA.Activity.registerSidebarEntries(async ({ fileInfo, limit, offset }) => { |
||||
const { data: comments } = await getComments({ commentsType: 'files', ressourceId: fileInfo.id }, { limit, offset }) |
||||
logger.debug('Loaded comments', { fileInfo, comments }) |
||||
const { default: CommentView } = await import('./views/ActivityCommentEntry.vue') |
||||
const CommentsViewObject = Vue.extend(CommentView) |
||||
|
||||
return comments.map((comment) => ({ |
||||
timestamp: moment(comment.props.creationDateTime).toDate().getTime(), |
||||
mount(element, { context, reload }) { |
||||
this._CommentsViewInstance = new CommentsViewObject({ |
||||
parent: context, |
||||
propsData: { |
||||
comment, |
||||
ressourceId: fileInfo.id, |
||||
reloadCallback: reload, |
||||
}, |
||||
}) |
||||
this._CommentsViewInstance.$mount(element) |
||||
}, |
||||
unmount() { |
||||
this._CommentsViewInstance.$destroy() |
||||
}, |
||||
})) |
||||
}) |
||||
|
||||
window.OCA.Activity.registerSidebarFilter((activity) => activity.type !== 'comments') |
||||
logger.info('Comments plugin registered for Activity sidebar action') |
||||
} |
||||
@ -0,0 +1,68 @@ |
||||
import axios from '@nextcloud/axios' |
||||
import { getCurrentUser } from '@nextcloud/auth' |
||||
import { loadState } from '@nextcloud/initial-state' |
||||
import { generateOcsUrl } from '@nextcloud/router' |
||||
import { defineComponent } from 'vue' |
||||
|
||||
export default defineComponent({ |
||||
props: { |
||||
ressourceId: { |
||||
type: Number, |
||||
required: true, |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
editorData: { |
||||
actorDisplayName: getCurrentUser()!.displayName as string, |
||||
actorId: getCurrentUser()!.uid as string, |
||||
key: 'editor', |
||||
}, |
||||
userData: {}, |
||||
} |
||||
}, |
||||
methods: { |
||||
/** |
||||
* Autocomplete @mentions |
||||
* |
||||
* @param {string} search the query |
||||
* @param {Function} callback the callback to process the results with |
||||
*/ |
||||
async autoComplete(search, callback) { |
||||
const { data } = await axios.get(generateOcsUrl('core/autocomplete/get'), { |
||||
params: { |
||||
search, |
||||
itemType: 'files', |
||||
itemId: this.ressourceId, |
||||
sorter: 'commenters|share-recipients', |
||||
limit: loadState('comments', 'maxAutoCompleteResults'), |
||||
}, |
||||
}) |
||||
// Save user data so it can be used by the editor to replace mentions
|
||||
data.ocs.data.forEach(user => { this.userData[user.id] = user }) |
||||
return callback(Object.values(this.userData)) |
||||
}, |
||||
|
||||
/** |
||||
* Make sure we have all mentions as Array of objects |
||||
* |
||||
* @param mentions the mentions list |
||||
*/ |
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
genMentionsData(mentions: any[]): Record<string, object> { |
||||
Object.values(mentions) |
||||
.flat() |
||||
.forEach(mention => { |
||||
this.userData[mention.mentionId] = { |
||||
// TODO: support groups
|
||||
icon: 'icon-user', |
||||
id: mention.mentionId, |
||||
label: mention.mentionDisplayName, |
||||
source: 'users', |
||||
primary: getCurrentUser()?.uid === mention.mentionId, |
||||
} |
||||
}) |
||||
return this.userData |
||||
}, |
||||
}, |
||||
}) |
||||
@ -0,0 +1,70 @@ |
||||
<!-- |
||||
- @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de> |
||||
- |
||||
- @author Ferdinand Thiessen <opensource@fthiessen.de> |
||||
- |
||||
- @license AGPL-3.0-or-later |
||||
- |
||||
- This program is free software: you can redistribute it and/or modify |
||||
- it under the terms of the GNU Affero General Public License as |
||||
- published by the Free Software Foundation, either version 3 of the |
||||
- License, or (at your option) any later version. |
||||
- |
||||
- This program is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
- GNU Affero General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Affero General Public License |
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
- |
||||
--> |
||||
|
||||
<template> |
||||
<Comment v-bind="editorData" |
||||
:auto-complete="autoComplete" |
||||
:user-data="userData" |
||||
:editor="true" |
||||
:ressource-id="ressourceId" |
||||
class="comments-action" |
||||
@new="onNewComment" /> |
||||
</template> |
||||
|
||||
<script lang="ts"> |
||||
import { defineComponent } from 'vue' |
||||
import Comment from '../components/Comment.vue' |
||||
import CommentView from '../mixins/CommentView.js' |
||||
import logger from '../logger' |
||||
import { showError } from '@nextcloud/dialogs' |
||||
import { translate as t } from '@nextcloud/l10n' |
||||
|
||||
export default defineComponent({ |
||||
components: { |
||||
Comment, |
||||
}, |
||||
mixins: [CommentView], |
||||
props: { |
||||
reloadCallback: { |
||||
type: Function, |
||||
required: true, |
||||
}, |
||||
}, |
||||
methods: { |
||||
onNewComment() { |
||||
try { |
||||
// just force reload |
||||
this.reloadCallback() |
||||
} catch (e) { |
||||
showError(t('comments', 'Could not reload comments')) |
||||
logger.debug(e) |
||||
} |
||||
}, |
||||
}, |
||||
}) |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.comments-action { |
||||
padding: 0; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,86 @@ |
||||
<!-- |
||||
- @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de> |
||||
- |
||||
- @author Ferdinand Thiessen <opensource@fthiessen.de> |
||||
- |
||||
- @license AGPL-3.0-or-later |
||||
- |
||||
- This program is free software: you can redistribute it and/or modify |
||||
- it under the terms of the GNU Affero General Public License as |
||||
- published by the Free Software Foundation, either version 3 of the |
||||
- License, or (at your option) any later version. |
||||
- |
||||
- This program is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
- GNU Affero General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Affero General Public License |
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
- |
||||
--> |
||||
|
||||
<template> |
||||
<Comment ref="comment" |
||||
tag="li" |
||||
v-bind="comment.props" |
||||
:auto-complete="autoComplete" |
||||
:message="commentMessage" |
||||
:ressource-id="ressourceId" |
||||
:user-data="genMentionsData(comment.props.mentions)" |
||||
class="comments-activity" |
||||
@delete="reloadCallback()" /> |
||||
</template> |
||||
|
||||
<script lang="ts"> |
||||
import { translate as t } from '@nextcloud/l10n' |
||||
|
||||
import Comment from '../components/Comment.vue' |
||||
import CommentView from '../mixins/CommentView' |
||||
|
||||
export default { |
||||
name: 'ActivityCommentEntry', |
||||
|
||||
components: { |
||||
Comment, |
||||
}, |
||||
|
||||
mixins: [CommentView], |
||||
props: { |
||||
comment: { |
||||
type: Object, |
||||
required: true, |
||||
}, |
||||
reloadCallback: { |
||||
type: Function, |
||||
required: true, |
||||
}, |
||||
}, |
||||
|
||||
data() { |
||||
return { |
||||
commentMessage: '', |
||||
} |
||||
}, |
||||
|
||||
watch: { |
||||
comment() { |
||||
this.commentMessage = this.comment.props.message |
||||
}, |
||||
}, |
||||
|
||||
mounted() { |
||||
this.commentMessage = this.comment.props.message |
||||
}, |
||||
|
||||
methods: { |
||||
t, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.comments-activity { |
||||
padding: 0; |
||||
} |
||||
</style> |
||||
Loading…
Reference in new issue