Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vue3): migrate to vue3 #884

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": ["@nextcloud/eslint-config/typescript"],
"extends": ["@nextcloud/eslint-config/vue3"],
"overrides": [
// https://github.com/mysticatea/eslint-plugin-node/issues/248#issuecomment-1052550467
{
Expand All @@ -12,4 +12,4 @@
}
}
]
}
}
20 changes: 10 additions & 10 deletions lib/components/FilePicker/FileList.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('FilePicker FileList', () => {
const consoleWarning = vi.spyOn(console, 'warn')

const wrapper = shallowMount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: false,
allowPickDirectory: false,
Expand All @@ -80,7 +80,7 @@ describe('FilePicker FileList', () => {

it('header checkbox is not shown if multiselect is `false`', () => {
const wrapper = shallowMount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: false,
allowPickDirectory: false,
Expand All @@ -95,7 +95,7 @@ describe('FilePicker FileList', () => {

it('header checkbox is shown if multiselect is `true`', async () => {
const wrapper = shallowMount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: true,
allowPickDirectory: false,
Expand All @@ -108,18 +108,18 @@ describe('FilePicker FileList', () => {

await nextTick()

const selectAll = wrapper.find('[data-testid="select-all-checkbox"]')
const selectAll = wrapper.getComponent('[data-testid="select-all-checkbox"]')
expect(selectAll.exists()).toBe(true)
// there is an aria label
expect(selectAll.props('ariaLabel')).toBeTruthy()
// no checked
expect(selectAll.props('checked')).toBe(false)
expect(selectAll.props('modelValue')).toBe(false)
})

it('header checkbox is checked when all nodes are selected', async () => {
const nodes = [...exampleNodes]
const wrapper = shallowMount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: true,
allowPickDirectory: false,
Expand All @@ -130,15 +130,15 @@ describe('FilePicker FileList', () => {
},
})

const selectAll = wrapper.find('[data-testid="select-all-checkbox"]')
expect(selectAll.props('checked')).toBe(true)
const selectAll = wrapper.getComponent('[data-testid="select-all-checkbox"]')
expect(selectAll.props('modelValue')).toBe(true)
})

describe('file list sorting', () => {
it('is sorted initially by name', async () => {
const nodes = [...exampleNodes]
const wrapper = mount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: true,
allowPickDirectory: false,
Expand Down Expand Up @@ -169,7 +169,7 @@ describe('FilePicker FileList', () => {
it('can sort descending by name', async () => {
const nodes = [...exampleNodes]
const wrapper = mount(FileList, {
propsData: {
props: {
currentView: 'files',
multiselect: true,
allowPickDirectory: false,
Expand Down
4 changes: 2 additions & 2 deletions lib/components/FilePicker/FileList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
</span>
<NcCheckboxRadioSwitch v-if="multiselect"
:aria-label="t('Select all entries')"
:checked="allSelected"
:model-value="allSelected"
data-testid="select-all-checkbox"
@update:checked="onSelectAll" />
@update:model-value="onSelectAll" />
</th>
<th :aria-sort="sortByName" class="row-name">
<div class="header-wrapper">
Expand Down
20 changes: 11 additions & 9 deletions lib/components/FilePicker/FileListRow.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
const consoleError = vi.spyOn(console, 'error')

const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: true,
selected: false,
showCheckbox: true,
Expand All @@ -44,12 +44,12 @@
// shallowMounted
expect(wrapper.exists()).toBe(true)
expect(wrapper.element.tagName.toLowerCase()).toBe('tr')
expect(wrapper.find('[data-testid="file-list-row"]').isEmpty()).toBe(false)

Check failure on line 47 in lib/components/FilePicker/FileListRow.spec.ts

View workflow job for this annotation

GitHub Actions / test

lib/components/FilePicker/FileListRow.spec.ts > FilePicker: FileListRow > is shallowMountable

TypeError: wrapper.find(...).isEmpty is not a function ❯ lib/components/FilePicker/FileListRow.spec.ts:47:56
})

it('shows checkbox based on `showCheckbox` property', async () => {
const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: true,
selected: false,
showCheckbox: true,
Expand All @@ -66,17 +66,19 @@

it('Click checkbox triggers select', async () => {
const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: false,
selected: false,
showCheckbox: true,
canPick: true,
node,
cropImagePreviews: true,
},
stubs: {
NcCheckboxRadioSwitch: {
template: '<label><input type="checkbox" @click="$emit(\'update:checked\', true)" ></label>',
global: {
stubs: {
NcCheckboxRadioSwitch: {
template: '<label><input type="checkbox" @click="$emit(\'update:modelValue\', true)" ></label>',
},
},
},
})
Expand All @@ -89,7 +91,7 @@

it('Click element triggers select', async () => {
const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: false,
selected: false,
showCheckbox: true,
Expand All @@ -107,7 +109,7 @@

it('Click element without checkbox triggers select', async () => {
const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: false,
selected: false,
showCheckbox: false,
Expand All @@ -125,7 +127,7 @@

it('Enter triggers select', async () => {
const wrapper = shallowMount(FileListRow, {
propsData: {
props: {
allowPickDirectory: false,
selected: false,
showCheckbox: false,
Expand Down
4 changes: 2 additions & 2 deletions lib/components/FilePicker/FileListRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
}">
<td v-if="showCheckbox" class="row-checkbox" @click.stop="() => {/* Stop the click event */}">
<NcCheckboxRadioSwitch :aria-label="t('Select the row for {nodename}', { nodename: displayName })"
:checked="selected"
:model-value="selected"
:disabled="!isPickable"
data-testid="row-checkbox"
@update:checked="toggleSelected" />
@update:model-value="toggleSelected" />
</td>
<td class="row-name">
<div class="file-picker__name-container" data-testid="row-name">
Expand Down
16 changes: 8 additions & 8 deletions lib/components/FilePicker/FilePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<NcDialog :container="container"
<NcDialog v-model:open="isOpen"
:container="container"
:buttons="dialogButtons"
:name="name"
size="large"
content-classes="file-picker__content"
dialog-classes="file-picker"
navigation-classes="file-picker__navigation"
:open.sync="isOpen"
@update:open="handleClose">
<template #navigation="{ isCollapsed }">
<FilePickerNavigation :is-collapsed="isCollapsed"
:current-view.sync="currentView"
:filter-string.sync="filterString"
<FilePickerNavigation v-model:current-view="currentView"
v-model:filter-string="filterString"
:is-collapsed="isCollapsed"
:disabled-navigation="disabledNavigation" />
</template>

<div class="file-picker__main">
<!-- Header title / file list breadcrumbs -->
<FilePickerBreadcrumbs v-if="currentView === 'files'"
:path.sync="currentPath"
v-model:path="currentPath"
:show-menu="allowPickDirectory"
@create-node="onCreateFolder" />
<div v-else class="file-picker__view">
Expand All @@ -32,13 +32,13 @@
<!-- File list -->
<!-- If loading or files found show file list, otherwise show empty content-->
<FileList v-if="isLoading || filteredFiles.length > 0"
v-model:path="currentPath"
v-model:selected-files="selectedFiles"
:allow-pick-directory="allowPickDirectory"
:current-view="currentView"
:files="filteredFiles"
:multiselect="multiselect"
:loading="isLoading"
:path.sync="currentPath"
:selected-files.sync="selectedFiles"
:name="viewHeadline"
@update:path="currentView = 'files'" />
<NcEmptyContent v-else-if="filterString"
Expand Down
6 changes: 3 additions & 3 deletions lib/components/FilePicker/FilePickerBreadcrumbs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@
@click="emit('update:path', dir.path)" />
</template>
<template v-if="showMenu" #actions>
<NcActions :aria-label="t('Create directory')"
<NcActions v-model:open="actionsOpen"
:aria-label="t('Create directory')"
:force-menu="true"
:force-name="true"
:menu-name="t('New')"
:open.sync="actionsOpen"
type="secondary"
@close="newNodeName = ''">
<template #icon>
<IconPlus :size="20" />
</template>
<NcActionInput ref="nameInput"
:value.sync="newNodeName"
v-model:value="newNodeName"
raimund-schluessler marked this conversation as resolved.
Show resolved Hide resolved
:label="t('New folder')"
:placeholder="t('New folder name')"
@submit="onSubmit"
Expand Down
9 changes: 4 additions & 5 deletions lib/components/FilePicker/FilePickerNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
<Fragment>
<!-- Filter for the file list -->
<NcTextField class="file-picker__filter-input"
:value="filterString"
:model-value="filterString"
:label="t('Filter file list')"
:show-trailing-button="!!filterString"
@update:value="updateFilterValue"
@update:model-value="updateFilterValue"
@trailing-button-click="updateFilterValue('')">
<IconMagnify :size="16" />
<template #trailing-button-icon>
Expand Down Expand Up @@ -37,7 +37,7 @@
:searchable="false"
:options="availableViews"
:value="currentViewObject"
@input="(v) => emit('update:currentView', v.id)" />
@update:model-value="v => emit('update:currentView', v.id)" />
</template>
</Fragment>
</template>
Expand All @@ -48,8 +48,7 @@ import IconMagnify from 'vue-material-design-icons/Magnify.vue'

import { getCurrentUser } from '@nextcloud/auth'
import { NcButton, NcIconSvgWrapper, NcSelect, NcTextField } from '@nextcloud/vue'
import { computed, ref } from 'vue'
import { Fragment } from 'vue-frag'
import { computed, ref, Fragment } from 'vue'
import { t } from '../../utils/l10n'
import { useViews } from '../../composables/views'

Expand Down
4 changes: 2 additions & 2 deletions lib/components/FilePicker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { AsyncComponent } from 'vue'
import type { Component } from 'vue'
import type { DefaultComputed, DefaultData, DefaultMethods } from 'vue/types/options.js'
import { defineAsyncComponent } from 'vue'

Expand All @@ -25,4 +25,4 @@ type IFilePickerProps = (typeof import ('./FilePicker.vue').default)['props']
* }]
* </script>
*/
export const FilePickerVue = defineAsyncComponent(() => import('./FilePicker.vue')) as AsyncComponent<DefaultData<never>, DefaultMethods<never>, DefaultComputed, IFilePickerProps>
export const FilePickerVue = defineAsyncComponent(() => import('./FilePicker.vue')) as Component<DefaultData<never>, DefaultMethods<never>, DefaultComputed, IFilePickerProps>
4 changes: 2 additions & 2 deletions lib/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ export interface IFilePickerButton extends Omit<IDialogButton, 'callback'> {
export type IFilePickerButtonFactory = (selectedNodes: Node[], currentPath: string, currentView: string) => IFilePickerButton[]

/**
* Type of filter functions to filter the FilePicker's file list
*/
* Type of filter functions to filter the FilePicker's file list
*/
export type IFilePickerFilter = (node: Node) => boolean
12 changes: 6 additions & 6 deletions lib/composables/dav.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import type { Ref } from 'vue'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { shallowMount } from '@vue/test-utils'
import { defineComponent, ref, toRef, nextTick } from 'vue'
import { defineComponent, h, ref, toRef, nextTick } from 'vue'
import { useDAVFiles } from './dav'

const nextcloudFiles = vi.hoisted(() => ({
Expand Down Expand Up @@ -44,7 +44,7 @@ const TestComponent = defineComponent({
...dav,
}
},
render: (h) => h('div'),
render: () => h('div'),
})

describe('dav composable', () => {
Expand All @@ -57,7 +57,7 @@ describe('dav composable', () => {
nextcloudFiles.davGetClient.mockImplementationOnce(() => client)

const vue = shallowMount(TestComponent, {
propsData: {
props: {
currentView: 'files',
currentPath: '/',
isPublic: false,
Expand All @@ -83,7 +83,7 @@ describe('dav composable', () => {
nextcloudFiles.davResultToNode.mockImplementation((v) => `node ${v}`)

const vue = shallowMount(TestComponent, {
propsData: {
props: {
currentView: 'files',
currentPath: '/',
isPublic: false,
Expand All @@ -103,7 +103,7 @@ describe('dav composable', () => {
nextcloudFiles.davGetClient.mockImplementationOnce(() => client)

const vue = shallowMount(TestComponent, {
propsData: {
props: {
currentView: 'files',
currentPath: '/',
isPublic: false,
Expand Down Expand Up @@ -131,7 +131,7 @@ describe('dav composable', () => {
nextcloudFiles.davGetClient.mockImplementationOnce(() => client)

const vue = shallowMount(TestComponent, {
propsData: {
props: {
currentView: 'files',
currentPath: '/',
isPublic: false,
Expand Down
4 changes: 2 additions & 2 deletions lib/composables/filesSettings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { describe, it, expect, vi, afterEach, beforeAll, afterAll } from 'vitest'
import { shallowMount } from '@vue/test-utils'
import { defineComponent, nextTick } from 'vue'
import { defineComponent, h, nextTick } from 'vue'
import { useFilesSettings } from './filesSettings'

const axios = vi.hoisted(() => ({
Expand All @@ -23,7 +23,7 @@ const TestComponent = defineComponent({
...settings,
}
},
render: (h) => h('div'),
render: () => h('div'),
})

describe('files app settings composable', () => {
Expand Down
Loading
Loading