Skip to content
Merged
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
51 changes: 51 additions & 0 deletions .github/workflows/lint-eslint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud-libraries/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT

name: Lint eslint

on: pull_request

permissions:
contents: read

concurrency:
group: lint-eslint-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest

name: eslint

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false

- name: Read package.json
uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0
id: versions

- name: Set up node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: ${{ steps.versions.outputs.node-version }}

- name: Set up npm
run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}'

- name: Install dependencies
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: npm ci

- name: Lint
run: npm run lint
18 changes: 10 additions & 8 deletions lib/components/FilePicker/FileListRow.spec.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 { VueWrapper } from '@vue/test-utils'
import type { Wrapper } from '@vue/test-utils'
import type { ComponentProps } from 'vue-component-type-helpers'

import { afterEach, describe, expect, it, vi } from 'vitest'
Expand All @@ -13,25 +13,27 @@ import { shallowMount } from '@vue/test-utils'
import FileListRow from './FileListRow.vue'
import { nextTick } from 'vue'

type SubmitAction = (wrapper: VueWrapper<any>) => Promise<void>
/* eslint-disable @typescript-eslint/no-explicit-any, jsdoc/require-jsdoc */

type SubmitAction = (wrapper: Wrapper<any>) => Promise<void>
type ElementEvent = { 'update:selected': boolean | undefined, 'enter-directory': Folder | undefined }

async function clickCheckboxAction(wrapper: VueWrapper<any>) {
async function clickCheckboxAction(wrapper: Wrapper<any>) {
wrapper.find('input[type="checkbox"]').trigger('click')
}

async function clickElementAction(wrapper: VueWrapper<any>) {
async function clickElementAction(wrapper: Wrapper<any>) {
wrapper.find('[data-testid="row-name"]').trigger('click')
}

async function pressEnterAction(wrapper: VueWrapper<any>) {
async function pressEnterAction(wrapper: Wrapper<any>) {
wrapper.element.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter' }))
await nextTick()
}

function testSubmitNode(name: string, propsData: ComponentProps<typeof FileListRow>, eventPayload: ElementEvent, actionCallback: SubmitAction) {
it(name, async () => {
const wrapper = shallowMount(FileListRow, {
const wrapper = shallowMount(FileListRow as any, {
propsData,
stubs: {
NcCheckboxRadioSwitch: {
Expand Down Expand Up @@ -113,7 +115,7 @@ describe('FilePicker: FileListRow', () => {
const consoleWarn = vi.spyOn(console, 'warn')
const consoleError = vi.spyOn(console, 'error')

const wrapper = shallowMount(FileListRow, {
const wrapper = shallowMount(FileListRow as any, {
propsData: {
allowPickDirectory: true,
selected: false,
Expand All @@ -134,7 +136,7 @@ describe('FilePicker: FileListRow', () => {
})

it('shows checkbox based on `showCheckbox` property', async () => {
const wrapper = shallowMount(FileListRow, {
const wrapper = shallowMount(FileListRow as any, {
propsData: {
allowPickDirectory: true,
selected: false,
Expand Down
22 changes: 11 additions & 11 deletions lib/components/FilePicker/FilePickerBreadcrumbs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,17 @@ function validateInput() {
}

switch (error.reason) {
case InvalidFilenameErrorReason.Character:
validity = t('"{char}" is not allowed inside a folder name.', { char: error.segment })
break
case InvalidFilenameErrorReason.ReservedName:
validity = t('"{segment}" is a reserved name and not allowed for folder names.', { segment: error.segment })
break
case InvalidFilenameErrorReason.Extension:
validity = t('Folder names must not end with "{extension}".', { extension: error.segment })
break
default:
validity = t('Invalid folder name.')
case InvalidFilenameErrorReason.Character:
validity = t('"{char}" is not allowed inside a folder name.', { char: error.segment })
break
case InvalidFilenameErrorReason.ReservedName:
validity = t('"{segment}" is a reserved name and not allowed for folder names.', { segment: error.segment })
break
case InvalidFilenameErrorReason.Extension:
validity = t('Folder names must not end with "{extension}".', { extension: error.segment })
break
default:
validity = t('Invalid folder name.')
}
}
if (input) {
Expand Down
10 changes: 5 additions & 5 deletions lib/components/FilePicker/FilePreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<script setup lang="ts">
import type { INode } from '@nextcloud/files'

import { mdiAccountPlus, mdiGroup, mdiLink, mdiLock, mdiNetwork, mdiTag } from '@mdi/js'
import { mdiAccountGroupOutline, mdiAccountPlus, mdiKey, mdiLink, mdiNetworkOutline, mdiTagOutline } from '@mdi/js'
import { FileType } from '@nextcloud/files'
import { ShareType } from '@nextcloud/sharing'
import { computed, ref, toRef } from 'vue'
Expand Down Expand Up @@ -57,12 +57,12 @@ const folderDecorationIcon = computed(() => {

// Encrypted folders
if (props.node.attributes?.['is-encrypted'] === 1) {
return mdiLock
return mdiKey
}

// System tags
if (props.node.attributes?.['is-tag']) {
return mdiTag
return mdiTagOutline
}

// Link and mail shared folders
Expand All @@ -79,9 +79,9 @@ const folderDecorationIcon = computed(() => {
switch (props.node.attributes?.['mount-type']) {
case 'external':
case 'external-session':
return mdiNetwork
return mdiNetworkOutline
case 'group':
return mdiGroup
return mdiAccountGroupOutline
case 'shared':
return mdiAccountPlus
}
Expand Down
8 changes: 4 additions & 4 deletions lib/components/PublicAuthPrompt.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@

<!-- Form -->
<NcTextField ref="input"
v-model="name"
class="public-auth-prompt__input"
data-cy-public-auth-prompt-dialog-name
:label="t('Name')"
:placeholder="t('Enter your name')"
:required="!cancellable"
v-model="name"
minlength="2"
maxlength="64"
name="name" />
Expand Down Expand Up @@ -114,14 +114,14 @@ export default defineComponent({
},
},

emits: ['close'],

setup() {
return {
t,
}
},

emits: ['close'],

data() {
return {
name: '',
Expand Down Expand Up @@ -172,7 +172,7 @@ export default defineComponent({
},
immediate: true,
},

name() {
// Check validity of the new name
const newName = this.name.trim?.() || ''
Expand Down
22 changes: 11 additions & 11 deletions lib/utils/guestNameValidity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ export function getGuestNameValidity(name: string): string {
}

switch (error.reason) {
case InvalidFilenameErrorReason.Character:
return t('"{char}" is not allowed inside a name.', { char: error.segment })
case InvalidFilenameErrorReason.ReservedName:
return t('"{segment}" is a reserved name and not allowed.', { segment: error.segment })
case InvalidFilenameErrorReason.Extension:
if (error.segment.match(/\.[a-z]/i)) {
return t('"{extension}" is not an allowed name.', { extension: error.segment })
}
return t('Names must not end with "{extension}".', { extension: error.segment })
default:
return t('Invalid name.')
case InvalidFilenameErrorReason.Character:
return t('"{char}" is not allowed inside a name.', { char: error.segment })
case InvalidFilenameErrorReason.ReservedName:
return t('"{segment}" is a reserved name and not allowed.', { segment: error.segment })
case InvalidFilenameErrorReason.Extension:
if (error.segment.match(/\.[a-z]/i)) {
return t('"{extension}" is not an allowed name.', { extension: error.segment })
}
return t('Names must not end with "{extension}".', { extension: error.segment })
default:
return t('Invalid name.')
}
}
}