diff --git a/apps/comments/lib/Listener/LoadSidebarScripts.php b/apps/comments/lib/Listener/LoadSidebarScripts.php
index 906fe40fed250..5235de9c0a094 100644
--- a/apps/comments/lib/Listener/LoadSidebarScripts.php
+++ b/apps/comments/lib/Listener/LoadSidebarScripts.php
@@ -34,7 +34,8 @@ public function handle(Event $event): void {
$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', 'files');
Util::addScript(Application::APP_ID, 'comments-tab', 'files');
}
}
diff --git a/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts b/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts
index 699c53f849d48..2cd2e9d16a066 100644
--- a/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts
+++ b/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts
@@ -7,7 +7,7 @@ import type { IFolder, IView } from '@nextcloud/files'
import { File, Permission } from '@nextcloud/files'
import { describe, expect, test, vi } from 'vitest'
-import logger from '../logger.js'
+import logger from '../logger.ts'
import { action } from './inlineUnreadCommentsAction.ts'
const view = {
diff --git a/apps/comments/src/actions/inlineUnreadCommentsAction.ts b/apps/comments/src/actions/inlineUnreadCommentsAction.ts
index 4f77a66244c2c..c871a1d474660 100644
--- a/apps/comments/src/actions/inlineUnreadCommentsAction.ts
+++ b/apps/comments/src/actions/inlineUnreadCommentsAction.ts
@@ -8,8 +8,8 @@ import type { IFileAction } from '@nextcloud/files'
import CommentProcessingSvg from '@mdi/svg/svg/comment-processing.svg?raw'
import { getSidebar } from '@nextcloud/files'
import { n, t } from '@nextcloud/l10n'
-import logger from '../logger.js'
-import { isUsingActivityIntegration } from '../utils/activity.js'
+import logger from '../logger.ts'
+import { isUsingActivityIntegration } from '../utils/activity.ts'
export const action: IFileAction = {
id: 'comments-unread',
diff --git a/apps/comments/src/comments-activity-tab.ts b/apps/comments/src/comments-activity-tab.ts
index c368236052f86..1f17409252c01 100644
--- a/apps/comments/src/comments-activity-tab.ts
+++ b/apps/comments/src/comments-activity-tab.ts
@@ -6,44 +6,38 @@
import type { INode } from '@nextcloud/files'
import moment from '@nextcloud/moment'
-import { createPinia, PiniaVuePlugin } from 'pinia'
-import Vue, { type ComponentPublicInstance } from 'vue'
-import logger from './logger.js'
-import { getComments } from './services/GetComments.js'
-
-Vue.use(PiniaVuePlugin)
-
-let ActivityTabPluginView
-let ActivityTabPluginInstance
+import { createPinia } from 'pinia'
+import { createApp, type ComponentPublicInstance } from 'vue'
+import logger from './logger.ts'
+import { getComments } from './services/GetComments.ts'
/**
* 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()
},
})
@@ -57,8 +51,6 @@ export function registerCommentsPlugins() {
)
logger.debug('Loaded comments', { node, comments })
const { default: CommentView } = await import('./views/ActivityCommentEntry.vue')
- // @ts-expect-error Types are broken for Vue2
- const CommentsViewObject = Vue.extend(CommentView)
return comments.map((comment) => ({
_CommentsViewInstance: undefined as ComponentPublicInstance | undefined,
@@ -66,17 +58,18 @@ export function registerCommentsPlugins() {
timestamp: moment(comment.props?.creationDateTime).toDate().getTime(),
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()
},
}))
})
diff --git a/apps/comments/src/comments-app.js b/apps/comments/src/comments-app.ts
similarity index 79%
rename from apps/comments/src/comments-app.js
rename to apps/comments/src/comments-app.ts
index ea99517e2807c..4b4fd54c55a65 100644
--- a/apps/comments/src/comments-app.js
+++ b/apps/comments/src/comments-app.ts
@@ -3,8 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import logger from './logger.js'
-import CommentsInstance from './services/CommentsInstance.js'
+import logger from './logger.ts'
+import CommentsInstance from './services/CommentsInstance.ts'
// Init Comments
if (window.OCA && !window.OCA.Comments) {
diff --git a/apps/comments/src/components/Comment.vue b/apps/comments/src/components/Comment.vue
index 9e700fbf919d6..7b7fc4cdd4643 100644
--- a/apps/comments/src/components/Comment.vue
+++ b/apps/comments/src/components/Comment.vue
@@ -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" />
@@ -125,8 +125,8 @@ import IconArrowRight from 'vue-material-design-icons/ArrowRight.vue'
import IconClose from 'vue-material-design-icons/Close.vue'
import IconPencilOutline from 'vue-material-design-icons/PencilOutline.vue'
import IconTrashCanOutline from 'vue-material-design-icons/TrashCanOutline.vue'
-import CommentMixin from '../mixins/CommentMixin.js'
-import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.js'
+import CommentMixin from '../mixins/CommentMixin.ts'
+import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.ts'
// Dynamic loading
const NcRichContenteditable = () => import('@nextcloud/vue/components/NcRichContenteditable')
diff --git a/apps/comments/src/files-sidebar.ts b/apps/comments/src/files-sidebar.ts
index 1a39291c48d42..f96c69583ccc1 100644
--- a/apps/comments/src/files-sidebar.ts
+++ b/apps/comments/src/files-sidebar.ts
@@ -7,9 +7,9 @@ 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, h, createApp, getCurrentInstance } from 'vue'
+import { createWebComponent } from 'vue-web-component-wrapper'
import { registerCommentsPlugins } from './comments-activity-tab.ts'
import { isUsingActivityIntegration } from './utils/activity.ts'
@@ -32,17 +32,28 @@ 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 },
- })
- Object.defineProperty(webComponent.prototype, 'shadowRoot', {
- get() { return this },
+ const pluginsWrapper = {
+ install(GivenVue: any) {
+ const Vue = GivenVue
+
+ Vue.mixin({ pinia: createPinia() })
+ },
+ }
+
+ createWebComponent({
+ rootComponent: FilesSidebarTab,
+ elementName: tagName,
+ plugins: pluginsWrapper,
+ cssFrameworkStyles: null,
+ defineCustomElement,
+ h,
+ createApp,
+ getCurrentInstance,
+ disableStyleRemoval: false,
+ disableShadowDOM: true,
+ replaceRootWithHostInCssFramework: false,
+ nonce: __webpack_nonce__,
})
- window.customElements.define(tagName, webComponent)
},
})
}
diff --git a/apps/comments/src/logger.js b/apps/comments/src/logger.ts
similarity index 100%
rename from apps/comments/src/logger.js
rename to apps/comments/src/logger.ts
diff --git a/apps/comments/src/mixins/CommentMixin.js b/apps/comments/src/mixins/CommentMixin.ts
similarity index 93%
rename from apps/comments/src/mixins/CommentMixin.js
rename to apps/comments/src/mixins/CommentMixin.ts
index 92fd3b17acf9b..36e79eb429706 100644
--- a/apps/comments/src/mixins/CommentMixin.js
+++ b/apps/comments/src/mixins/CommentMixin.ts
@@ -5,11 +5,11 @@
import { showError, showUndo, TOAST_UNDO_TIMEOUT } from '@nextcloud/dialogs'
import { mapStores } from 'pinia'
-import logger from '../logger.js'
-import DeleteComment from '../services/DeleteComment.js'
-import EditComment from '../services/EditComment.js'
-import NewComment from '../services/NewComment.js'
-import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.js'
+import logger from '../logger.ts'
+import DeleteComment from '../services/DeleteComment.ts'
+import EditComment from '../services/EditComment.ts'
+import NewComment from '../services/NewComment.ts'
+import { useDeletedCommentLimbo } from '../store/deletedCommentLimbo.ts'
export default {
props: {
diff --git a/apps/comments/src/services/CommentsInstance.js b/apps/comments/src/services/CommentsInstance.ts
similarity index 54%
rename from apps/comments/src/services/CommentsInstance.js
rename to apps/comments/src/services/CommentsInstance.ts
index a768da1c652a2..6a51248a8c930 100644
--- a/apps/comments/src/services/CommentsInstance.js
+++ b/apps/comments/src/services/CommentsInstance.ts
@@ -5,49 +5,46 @@
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.js'
-
-Vue.use(PiniaVuePlugin)
+import logger from '../logger.ts'
__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
}
}
diff --git a/apps/comments/src/services/DavClient.js b/apps/comments/src/services/DavClient.ts
similarity index 93%
rename from apps/comments/src/services/DavClient.js
rename to apps/comments/src/services/DavClient.ts
index 6287b47cf309f..b1832b0f715ab 100644
--- a/apps/comments/src/services/DavClient.js
+++ b/apps/comments/src/services/DavClient.ts
@@ -5,7 +5,7 @@
import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
import { createClient } from 'webdav'
-import { getRootPath } from '../utils/davUtils.js'
+import { getRootPath } from '../utils/davUtils.ts'
// init webdav client
const client = createClient(getRootPath())
diff --git a/apps/comments/src/services/DeleteComment.js b/apps/comments/src/services/DeleteComment.ts
similarity index 93%
rename from apps/comments/src/services/DeleteComment.js
rename to apps/comments/src/services/DeleteComment.ts
index 1ed63d7836a54..46f46a483ffb1 100644
--- a/apps/comments/src/services/DeleteComment.js
+++ b/apps/comments/src/services/DeleteComment.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import client from './DavClient.js'
+import client from './DavClient.ts'
/**
* Delete a comment
diff --git a/apps/comments/src/services/EditComment.js b/apps/comments/src/services/EditComment.ts
similarity index 95%
rename from apps/comments/src/services/EditComment.js
rename to apps/comments/src/services/EditComment.ts
index cd8e5a977047a..c5f7679013b7f 100644
--- a/apps/comments/src/services/EditComment.js
+++ b/apps/comments/src/services/EditComment.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import client from './DavClient.js'
+import client from './DavClient.ts'
/**
* Edit an existing comment
diff --git a/apps/comments/src/services/GetComments.ts b/apps/comments/src/services/GetComments.ts
index 07c22bef4293c..884b66b77d25c 100644
--- a/apps/comments/src/services/GetComments.ts
+++ b/apps/comments/src/services/GetComments.ts
@@ -8,7 +8,7 @@ import type { DAVResult, FileStat, ResponseDataDetailed } from 'webdav'
import { parseXML } from 'webdav'
import { processResponsePayload } from 'webdav/dist/node/response.js'
import { prepareFileFromProps } from 'webdav/dist/node/tools/dav.js'
-import client from './DavClient.js'
+import client from './DavClient.ts'
export const DEFAULT_LIMIT = 20
diff --git a/apps/comments/src/services/NewComment.js b/apps/comments/src/services/NewComment.ts
similarity index 94%
rename from apps/comments/src/services/NewComment.js
rename to apps/comments/src/services/NewComment.ts
index a283b2068307f..32e452e2c20f0 100644
--- a/apps/comments/src/services/NewComment.js
+++ b/apps/comments/src/services/NewComment.ts
@@ -5,9 +5,9 @@
import { getCurrentUser } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
-import { getRootPath } from '../utils/davUtils.js'
-import { decodeHtmlEntities } from '../utils/decodeHtmlEntities.js'
-import client from './DavClient.js'
+import { getRootPath } from '../utils/davUtils.ts'
+import { decodeHtmlEntities } from '../utils/decodeHtmlEntities.ts'
+import client from './DavClient.ts'
/**
* Retrieve the comments list
diff --git a/apps/comments/src/services/ReadComments.ts b/apps/comments/src/services/ReadComments.ts
index 69bf72bb22f2c..873b186700d59 100644
--- a/apps/comments/src/services/ReadComments.ts
+++ b/apps/comments/src/services/ReadComments.ts
@@ -5,7 +5,7 @@
import type { Response } from 'webdav'
-import client from './DavClient.js'
+import client from './DavClient.ts'
/**
* Mark comments older than the date timestamp as read
diff --git a/apps/comments/src/store/deletedCommentLimbo.js b/apps/comments/src/store/deletedCommentLimbo.ts
similarity index 100%
rename from apps/comments/src/store/deletedCommentLimbo.js
rename to apps/comments/src/store/deletedCommentLimbo.ts
diff --git a/apps/comments/src/utils/cancelableRequest.js b/apps/comments/src/utils/cancelableRequest.ts
similarity index 100%
rename from apps/comments/src/utils/cancelableRequest.js
rename to apps/comments/src/utils/cancelableRequest.ts
diff --git a/apps/comments/src/utils/davUtils.js b/apps/comments/src/utils/davUtils.ts
similarity index 100%
rename from apps/comments/src/utils/davUtils.js
rename to apps/comments/src/utils/davUtils.ts
diff --git a/apps/comments/src/utils/decodeHtmlEntities.js b/apps/comments/src/utils/decodeHtmlEntities.ts
similarity index 100%
rename from apps/comments/src/utils/decodeHtmlEntities.js
rename to apps/comments/src/utils/decodeHtmlEntities.ts
diff --git a/apps/comments/src/views/ActivityCommentAction.vue b/apps/comments/src/views/ActivityCommentAction.vue
index e715a231b56a0..c2e21142008cf 100644
--- a/apps/comments/src/views/ActivityCommentAction.vue
+++ b/apps/comments/src/views/ActivityCommentAction.vue
@@ -20,8 +20,8 @@ import { showError } from '@nextcloud/dialogs'
import { t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import Comment from '../components/Comment.vue'
-import logger from '../logger.js'
-import CommentView from '../mixins/CommentView.js'
+import logger from '../logger.ts'
+import CommentView from '../mixins/CommentView.ts'
export default defineComponent({
components: {
diff --git a/apps/comments/src/views/Comments.vue b/apps/comments/src/views/Comments.vue
index 456dedf81d8ef..4b5bf5816e4fb 100644
--- a/apps/comments/src/views/Comments.vue
+++ b/apps/comments/src/views/Comments.vue
@@ -79,11 +79,11 @@ import IconAlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline
import IconMessageReplyTextOutline from 'vue-material-design-icons/MessageReplyTextOutline.vue'
import IconRefresh from 'vue-material-design-icons/Refresh.vue'
import Comment from '../components/Comment.vue'
-import logger from '../logger.js'
+import logger from '../logger.ts'
import CommentView from '../mixins/CommentView.ts'
import { DEFAULT_LIMIT, getComments } from '../services/GetComments.ts'
import { markCommentsAsRead } from '../services/ReadComments.ts'
-import cancelableRequest from '../utils/cancelableRequest.js'
+import cancelableRequest from '../utils/cancelableRequest.ts'
export default {
/* eslint vue/multi-word-component-names: "warn" */
diff --git a/build/frontend-legacy/webpack.modules.cjs b/build/frontend-legacy/webpack.modules.cjs
index 29369519fdaa8..3d40933db0c09 100644
--- a/build/frontend-legacy/webpack.modules.cjs
+++ b/build/frontend-legacy/webpack.modules.cjs
@@ -5,11 +5,6 @@
const path = require('path')
module.exports = {
- comments: {
- 'comments-app': path.join(__dirname, 'apps/comments/src', 'comments-app.js'),
- 'comments-tab': path.join(__dirname, 'apps/comments/src', 'files-sidebar.ts'),
- init: path.join(__dirname, 'apps/comments/src', 'init.ts'),
- },
core: {
'ajax-cron': path.join(__dirname, 'core/src', 'ajax-cron.ts'),
files_client: path.join(__dirname, 'core/src', 'files/client.js'),
diff --git a/build/frontend-legacy/apps/comments b/build/frontend/apps/comments
similarity index 100%
rename from build/frontend-legacy/apps/comments
rename to build/frontend/apps/comments
diff --git a/build/frontend/vite.config.ts b/build/frontend/vite.config.ts
index 2532f31419f3e..43b09776efa60 100644
--- a/build/frontend/vite.config.ts
+++ b/build/frontend/vite.config.ts
@@ -7,6 +7,11 @@ import { createAppConfig } from '@nextcloud/vite-config'
import { resolve } from 'node:path'
const modules = {
+ comments: {
+ 'comments-app': resolve(import.meta.dirname, 'apps/comments/src', 'comments-app.ts'),
+ 'comments-tab': resolve(import.meta.dirname, 'apps/comments/src', 'files-sidebar.ts'),
+ init: resolve(import.meta.dirname, 'apps/comments/src', 'init.ts'),
+ },
dav: {
'settings-admin-caldav': resolve(import.meta.dirname, 'apps/dav/src', 'settings-admin.ts'),
'settings-admin-example-content': resolve(import.meta.dirname, 'apps/dav/src', 'settings-admin-example-content.ts'),
diff --git a/package-lock.json b/package-lock.json
index f898b3b845d4b..03f4e20bb30f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,7 @@
"@nextcloud/initial-state": "^3.0.0",
"@nextcloud/l10n": "^3.4.1",
"@nextcloud/logger": "^3.0.3",
+ "@nextcloud/moment": "^1.3.5",
"@nextcloud/password-confirmation": "^6.0.2",
"@nextcloud/paths": "^3.0.0",
"@nextcloud/router": "^3.1.0",
@@ -34,6 +35,7 @@
"pinia": "^3.0.4",
"sortablejs": "^1.15.7",
"vue": "^3.5.27",
+ "vue-web-component-wrapper": "^1.7.7",
"vuex": "^4.1.0",
"webdav": "^5.9.0"
},
@@ -228,6 +230,7 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
@@ -538,6 +541,7 @@
"integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@keyv/serialize": "^1.1.1"
}
@@ -667,6 +671,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=20.19.0"
},
@@ -707,6 +712,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=20.19.0"
}
@@ -2490,6 +2496,7 @@
"resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-3.4.1.tgz",
"integrity": "sha512-aTFinTcKiK2gEXwLgutXekpZZ8/v/4QiC8C3QCLH5m0o+WtxsBC+fqV142ebC/rfDnzCLhY4ZtswSu8bFbZocg==",
"license": "GPL-3.0-or-later",
+ "peer": true,
"dependencies": {
"@nextcloud/router": "^3.0.1",
"@nextcloud/typings": "^1.9.1",
@@ -2513,6 +2520,20 @@
"node": "^20.0.0 || ^22.0.0 || ^24.0.0"
}
},
+ "node_modules/@nextcloud/moment": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@nextcloud/moment/-/moment-1.3.5.tgz",
+ "integrity": "sha512-sQjQ/D40sdedtq4ywuANSxqG0VhIB/i+QtZ6Voz3nyZWhkyyqGxdj9rQu9AyEvas3/Jlspdom5chc+a8jOmHxQ==",
+ "license": "GPL-3.0-or-later",
+ "dependencies": {
+ "@nextcloud/l10n": "^3.4.0",
+ "moment": "^2.30.1"
+ },
+ "engines": {
+ "node": "^20.0.0",
+ "npm": "^10.0.0"
+ }
+ },
"node_modules/@nextcloud/password-confirmation": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-6.0.2.tgz",
@@ -2632,6 +2653,7 @@
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.5.0.tgz",
"integrity": "sha512-CQxBfHhF+Q+2r7RXd+l/eSjttJU8A2JFUyq5VpvjfpIql355kejc8bbNnM1pKgGRGSBuW9qw5Ohx0puzHge10w==",
"license": "AGPL-3.0-or-later",
+ "peer": true,
"dependencies": {
"@ckpack/vue-color": "^1.6.0",
"@floating-ui/dom": "^1.7.5",
@@ -3608,6 +3630,7 @@
"integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"json-schema-traverse": "^1.0.0",
@@ -3800,6 +3823,7 @@
"integrity": "sha512-zjTUwIsEfT+k9BmXwq1QEFYsb4afBlsI1AXFyWQBgggMzwBFOuu92pGrE5OFx90IOjNl+lUbQoTG7f8S0PkOdg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/types": "^8.53.1",
@@ -4216,6 +4240,7 @@
"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.54.0",
"@typescript-eslint/types": "8.54.0",
@@ -5083,6 +5108,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -5890,6 +5916,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
@@ -6921,6 +6948,7 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@cypress/request": "^3.0.10",
"@cypress/xvfb": "^1.2.4",
@@ -7623,7 +7651,6 @@
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
@@ -7639,7 +7666,6 @@
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"engines": {
"node": ">=0.12"
},
@@ -7671,8 +7697,7 @@
"url": "https://github.com/sponsors/fb55"
}
],
- "license": "BSD-2-Clause",
- "peer": true
+ "license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "5.0.3",
@@ -7680,7 +7705,6 @@
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"domelementtype": "^2.3.0"
},
@@ -7706,7 +7730,6 @@
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
@@ -7893,6 +7916,7 @@
"integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"ansi-colors": "^4.1.1",
"strip-ansi": "^6.0.1"
@@ -8112,6 +8136,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -8976,17 +9001,6 @@
"@floating-ui/core": "^1.1.0"
}
},
- "node_modules/focus-trap": {
- "version": "7.6.6",
- "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.6.tgz",
- "integrity": "sha512-v/Z8bvMCajtx4mEXmOo7QEsIzlIOqRXTIwgUfsFOF9gEsespdbD0AkPIka1bSXZ8Y8oZ+2IVDQZePkTfEHZl7Q==",
- "license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "tabbable": "^6.3.0"
- }
- },
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
@@ -9808,7 +9822,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
@@ -9822,7 +9835,6 @@
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"engines": {
"node": ">=0.12"
},
@@ -12426,7 +12438,6 @@
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
- "dev": true,
"license": "MIT",
"engines": {
"node": "*"
@@ -13313,6 +13324,7 @@
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz",
"integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/devtools-api": "^7.7.7"
},
@@ -13401,6 +13413,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -13416,7 +13429,6 @@
"integrity": "sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"htmlparser2": "^8.0.0",
"js-tokens": "^9.0.0",
@@ -13432,24 +13444,21 @@
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/postcss-media-query-parser": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
"integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/postcss-resolve-nested-selector": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz",
"integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/postcss-safe-parser": {
"version": "6.0.0",
@@ -13457,7 +13466,6 @@
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12.0"
},
@@ -13489,7 +13497,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12.0"
},
@@ -13503,6 +13510,7 @@
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -14295,6 +14303,7 @@
"integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@@ -14499,6 +14508,7 @@
"integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -14925,7 +14935,8 @@
"version": "1.15.7",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz",
"integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/source-map": {
"version": "0.6.1",
@@ -15479,6 +15490,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"@csstools/css-calc": "^3.1.1",
"@csstools/css-parser-algorithms": "^4.0.0",
@@ -15533,7 +15545,6 @@
"integrity": "sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": "^12 || >=14"
},
@@ -15561,7 +15572,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=20.19.0"
},
@@ -15623,7 +15633,6 @@
"integrity": "sha512-H88kCC+6Vtzj76NsC8rv6x/LW8slBzIbyeSjsKVlS+4qaEJoDrcJR4L+8JdrR2ORdTscrBzYWiiT2jq6leYR1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"css-tree": "^3.0.1",
"is-plain-object": "^5.0.0",
@@ -15646,8 +15655,7 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.26.0.tgz",
"integrity": "sha512-ZqI0qjKWHMPcGUfLmlr80NPNVHIOjPMHtIOe1qXYFGS0YBZ1YKAzo9yk8W+gGrLCN0Xdv/RKxqdIsqPakEfmow==",
"dev": true,
- "license": "CC0-1.0",
- "peer": true
+ "license": "CC0-1.0"
},
"node_modules/stylelint-use-logical": {
"version": "2.1.3",
@@ -16561,6 +16569,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -16977,6 +16986,7 @@
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -17590,6 +17600,7 @@
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vitest/expect": "4.0.18",
"@vitest/mocker": "4.0.18",
@@ -17681,6 +17692,7 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz",
"integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.28",
"@vue/compiler-sfc": "3.5.28",
@@ -17865,6 +17877,12 @@
"vue": "3.x"
}
},
+ "node_modules/vue-web-component-wrapper": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/vue-web-component-wrapper/-/vue-web-component-wrapper-1.7.7.tgz",
+ "integrity": "sha512-2uy6VdN8AwSzCeqc9tV4ZK2HKtgZ/NWL1rvdgOsddF1UFtszBZHKyQT9sDBUc4BpyXmP7f8tmI1rI0n/A6Qptw==",
+ "license": "MIT"
+ },
"node_modules/vuex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
diff --git a/package.json b/package.json
index 3bf056dd126dc..f51507d0e9b00 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
"@nextcloud/initial-state": "^3.0.0",
"@nextcloud/l10n": "^3.4.1",
"@nextcloud/logger": "^3.0.3",
+ "@nextcloud/moment": "^1.3.5",
"@nextcloud/password-confirmation": "^6.0.2",
"@nextcloud/paths": "^3.0.0",
"@nextcloud/router": "^3.1.0",
@@ -63,6 +64,7 @@
"pinia": "^3.0.4",
"sortablejs": "^1.15.7",
"vue": "^3.5.27",
+ "vue-web-component-wrapper": "^1.7.7",
"vuex": "^4.1.0",
"webdav": "^5.9.0"
},