mirror of
https://github.com/nextcloud/server.git
synced 2026-06-09 00:32:29 -04:00
refactor(comments): migrate to Vue 3
Signed-off-by: Edward Ly <contact@edward.ly>
This commit is contained in:
parent
3aa22804e1
commit
c56ebcecb2
6 changed files with 61 additions and 77 deletions
|
|
@ -34,7 +34,8 @@ class LoadSidebarScripts implements IEventListener {
|
|||
$this->commentsManager->load();
|
||||
|
||||
$this->initialState->provideInitialState('activityEnabled', $this->appManager->isEnabledForUser('activity'));
|
||||
// Add comments sidebar tab script
|
||||
// Add comments sidebar tab script/style
|
||||
Util::addStyle(Application::APP_ID, 'comments-tab');
|
||||
Util::addScript(Application::APP_ID, 'comments-tab', 'files');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,45 +4,40 @@
|
|||
*/
|
||||
|
||||
import type { INode } from '@nextcloud/files'
|
||||
import type { ComponentPublicInstance } from 'vue'
|
||||
|
||||
import { createPinia, PiniaVuePlugin } from 'pinia'
|
||||
import Vue, { type ComponentPublicInstance } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createApp } from 'vue'
|
||||
import logger from './logger.ts'
|
||||
import { getComments } from './services/GetComments.ts'
|
||||
|
||||
Vue.use(PiniaVuePlugin)
|
||||
|
||||
let ActivityTabPluginView
|
||||
let ActivityTabPluginInstance
|
||||
|
||||
/**
|
||||
* Register the comments plugins for the Activity sidebar
|
||||
*/
|
||||
export function registerCommentsPlugins() {
|
||||
let app
|
||||
|
||||
window.OCA.Activity.registerSidebarAction({
|
||||
mount: async (el: HTMLElement, { node, reload }: { node: INode, reload: () => void }) => {
|
||||
const pinia = createPinia()
|
||||
|
||||
if (!ActivityTabPluginView) {
|
||||
if (!app) {
|
||||
const { default: ActivityCommentAction } = await import('./views/ActivityCommentAction.vue')
|
||||
// @ts-expect-error Types are broken for Vue2
|
||||
ActivityTabPluginView = Vue.extend(ActivityCommentAction)
|
||||
app = createApp(
|
||||
ActivityCommentAction,
|
||||
{
|
||||
reloadCallback: reload,
|
||||
resourceId: node.fileid,
|
||||
},
|
||||
)
|
||||
}
|
||||
ActivityTabPluginInstance = new ActivityTabPluginView({
|
||||
el,
|
||||
pinia,
|
||||
propsData: {
|
||||
reloadCallback: reload,
|
||||
resourceId: node.fileid,
|
||||
},
|
||||
})
|
||||
app.use(pinia)
|
||||
app.mount(el)
|
||||
logger.info('Comments plugin mounted in Activity sidebar action', { node })
|
||||
},
|
||||
unmount: () => {
|
||||
// destroy previous instance if available
|
||||
if (ActivityTabPluginInstance) {
|
||||
ActivityTabPluginInstance.$destroy()
|
||||
}
|
||||
app?.unmount()
|
||||
},
|
||||
})
|
||||
|
||||
|
|
@ -56,7 +51,6 @@ export function registerCommentsPlugins() {
|
|||
)
|
||||
logger.debug('Loaded comments', { node, comments })
|
||||
const { default: CommentView } = await import('./views/ActivityCommentEntry.vue')
|
||||
const CommentsViewObject = Vue.extend(CommentView)
|
||||
|
||||
return comments.map((comment) => ({
|
||||
_CommentsViewInstance: undefined as ComponentPublicInstance | undefined,
|
||||
|
|
@ -64,17 +58,18 @@ export function registerCommentsPlugins() {
|
|||
timestamp: Date.parse(comment.props?.creationDateTime as string | undefined ?? ''),
|
||||
|
||||
mount(element: HTMLElement, { reload }) {
|
||||
this._CommentsViewInstance = new CommentsViewObject({
|
||||
el: element,
|
||||
propsData: {
|
||||
this._CommentsViewInstance = createApp(
|
||||
CommentView,
|
||||
{
|
||||
comment,
|
||||
resourceId: node.fileid,
|
||||
reloadCallback: reload,
|
||||
},
|
||||
})
|
||||
)
|
||||
this._CommentsViewInstance.mount(el)
|
||||
},
|
||||
unmount() {
|
||||
this._CommentsViewInstance?.$destroy()
|
||||
this._CommentsViewInstance?.unmount()
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
:model-value="localMessage"
|
||||
:user-data="userData"
|
||||
aria-describedby="tab-comments__editor-description"
|
||||
@update:value="updateLocalMessage"
|
||||
@update:model-value="updateLocalMessage"
|
||||
@submit="onSubmit" />
|
||||
<div class="comment__submit">
|
||||
<NcButton
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
:text="richContent.message"
|
||||
:arguments="richContent.mentions"
|
||||
use-markdown
|
||||
@click.native="onExpand" />
|
||||
@click="onExpand" />
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -4,17 +4,13 @@
|
|||
*/
|
||||
|
||||
import MessageReplyText from '@mdi/svg/svg/message-reply-text.svg?raw'
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
import { registerSidebarTab } from '@nextcloud/files'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import wrap from '@vue/web-component-wrapper'
|
||||
import { createPinia, PiniaVuePlugin } from 'pinia'
|
||||
import Vue from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { defineCustomElement } from 'vue'
|
||||
import { registerCommentsPlugins } from './comments-activity-tab.ts'
|
||||
import { isUsingActivityIntegration } from './utils/activity.ts'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
const tagName = 'comments_files-sidebar-tab'
|
||||
|
||||
if (isUsingActivityIntegration()) {
|
||||
|
|
@ -32,17 +28,15 @@ if (isUsingActivityIntegration()) {
|
|||
async onInit() {
|
||||
const { default: FilesSidebarTab } = await import('./views/FilesSidebarTab.vue')
|
||||
|
||||
Vue.use(PiniaVuePlugin)
|
||||
Vue.mixin({ pinia: createPinia() })
|
||||
const webComponent = wrap(Vue, FilesSidebarTab)
|
||||
// In Vue 2, wrap doesn't support disabling shadow. Disable with a hack
|
||||
Object.defineProperty(webComponent.prototype, 'attachShadow', {
|
||||
value() { return this },
|
||||
const FilesSidebarTabElement = defineCustomElement(FilesSidebarTab, {
|
||||
configureApp(app) {
|
||||
const pinia = createPinia()
|
||||
app.use(pinia)
|
||||
},
|
||||
shadowRoot: false,
|
||||
})
|
||||
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
|
||||
get() { return this },
|
||||
})
|
||||
window.customElements.define(tagName, webComponent)
|
||||
|
||||
window.customElements.define(tagName, FilesSidebarTabElement)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,51 +3,45 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
import { n, t } from '@nextcloud/l10n'
|
||||
import { createPinia, PiniaVuePlugin } from 'pinia'
|
||||
import Vue from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createApp } from 'vue'
|
||||
import CommentsApp from '../views/Comments.vue'
|
||||
import logger from '../logger.ts'
|
||||
|
||||
Vue.use(PiniaVuePlugin)
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
// Add translates functions
|
||||
Vue.mixin({
|
||||
data() {
|
||||
return {
|
||||
logger,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
t,
|
||||
n,
|
||||
},
|
||||
})
|
||||
|
||||
export default class CommentInstance {
|
||||
/**
|
||||
* Initialize a new Comments instance for the desired type
|
||||
*
|
||||
* @param {string} resourceType the comments endpoint type
|
||||
* @param {object} options the vue options (propsData, parent, el...)
|
||||
* @param {object} options the vue options (propsData, parent, el...)
|
||||
*/
|
||||
constructor(resourceType = 'files', options = {}) {
|
||||
const pinia = createPinia()
|
||||
|
||||
// Merge options and set `resourceType` property
|
||||
options = {
|
||||
...options,
|
||||
propsData: {
|
||||
const app = createApp(
|
||||
CommentsApp,
|
||||
{
|
||||
...(options.propsData ?? {}),
|
||||
resourceType,
|
||||
},
|
||||
pinia,
|
||||
}
|
||||
// Init Comments component
|
||||
const View = Vue.extend(CommentsApp)
|
||||
return new View(options)
|
||||
)
|
||||
|
||||
// Add translates functions
|
||||
app.mixin({
|
||||
data() {
|
||||
return {
|
||||
logger,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
t,
|
||||
n,
|
||||
},
|
||||
})
|
||||
|
||||
app.use(pinia)
|
||||
// app.mount(options.el)
|
||||
return app
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@
|
|||
<Comment
|
||||
v-for="comment in comments"
|
||||
:key="comment.props.id"
|
||||
v-model="comment.props.message"
|
||||
tag="li"
|
||||
v-bind="comment.props"
|
||||
:auto-complete="autoComplete"
|
||||
:resource-type="resourceType"
|
||||
:message.sync="comment.props.message"
|
||||
:resource-id="currentResourceId"
|
||||
:user-data="genMentionsData(comment.props.mentions)"
|
||||
class="comments__list"
|
||||
|
|
|
|||
Loading…
Reference in a new issue