Skip to content

Commit 449ed09

Browse files
committed
refactor(core): remove usage of Vue mixins
As a preparation for modern Vue with composition API and especially `script setup`. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent 37d0b28 commit 449ed09

15 files changed

Lines changed: 124 additions & 140 deletions

core/src/components/MainMenu.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
import { translatePlural as n, translate as t } from '@nextcloud/l10n'
76
import Vue from 'vue'
87
import AppMenu from './AppMenu.vue'
98

@@ -12,13 +11,6 @@ import AppMenu from './AppMenu.vue'
1211
* This is the top left menu where users can navigate between different apps.
1312
*/
1413
export function setUp() {
15-
Vue.mixin({
16-
methods: {
17-
t,
18-
n,
19-
},
20-
})
21-
2214
const container = document.getElementById('header-start__appmenu')
2315
if (!container) {
2416
// no container, possibly we're on a public page

core/src/components/UnifiedSearch/CustomDateRangeModal.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
</template>
4141

4242
<script>
43+
import { t } from '@nextcloud/l10n'
4344
import NcButton from '@nextcloud/vue/components/NcButton'
4445
import NcDateTimePicker from '@nextcloud/vue/components/NcDateTimePickerNative'
4546
import NcModal from '@nextcloud/vue/components/NcModal'
@@ -61,6 +62,12 @@ export default {
6162
},
6263
},
6364
65+
setup() {
66+
return {
67+
t,
68+
}
69+
},
70+
6471
data() {
6572
return {
6673
dateFilter: { startFrom: null, endAt: null },

core/src/components/login/LoginForm.vue

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,16 @@
5151
<h2 class="login-form__headline" data-login-form-headline>
5252
{{ headlineText }}
5353
</h2>
54-
<NcTextField
54+
<LoginNameInput
5555
id="user"
5656
ref="user"
57-
v-model="user"
58-
:label="loginText"
59-
name="user"
60-
:maxlength="255"
57+
:user.sync="user"
6158
:class="{ shake: invalidPassword }"
62-
autocapitalize="none"
63-
:spellchecking="false"
64-
:autocomplete="autoCompleteAllowed ? 'username' : 'off'"
59+
:auto-complete-allowed="autoCompleteAllowed"
60+
:allow-email="emailEnabled"
61+
name="user"
6562
required
66-
:error="userNameInputLengthIs255"
67-
:helper-text="userInputHelperText"
68-
data-login-form-input-user
69-
@change="updateUsername" />
63+
data-login-form-input-user />
7064

7165
<NcPasswordField
7266
id="password"
@@ -131,23 +125,20 @@ import debounce from 'debounce'
131125
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
132126
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
133127
import NcPasswordField from '@nextcloud/vue/components/NcPasswordField'
134-
import NcTextField from '@nextcloud/vue/components/NcTextField'
135128
import LoginButton from './LoginButton.vue'
136-
import AuthMixin from '../../mixins/auth.js'
129+
import LoginNameInput from './LoginNameInput.vue'
137130
138131
export default {
139132
name: 'LoginForm',
140133
141134
components: {
142135
LoginButton,
136+
LoginNameInput,
143137
NcCheckboxRadioSwitch,
144138
NcPasswordField,
145-
NcTextField,
146139
NcNoteCard,
147140
},
148141
149-
mixins: [AuthMixin],
150-
151142
props: {
152143
username: {
153144
type: String,
@@ -285,13 +276,6 @@ export default {
285276
emailEnabled() {
286277
return this.emailStates.every((state) => state === '1')
287278
},
288-
289-
loginText() {
290-
if (this.emailEnabled) {
291-
return t('core', 'Account name or email')
292-
}
293-
return t('core', 'Account name')
294-
},
295279
},
296280
297281
watch: {
@@ -305,9 +289,9 @@ export default {
305289
306290
mounted() {
307291
if (this.username === '') {
308-
this.$refs.user.$refs.inputField.$refs.input.focus()
292+
this.$refs.user.focus()
309293
} else {
310-
this.$refs.password.$refs.inputField.$refs.input.focus()
294+
this.$refs.password.focus()
311295
}
312296
},
313297
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<script lang="ts">
7+
export default {
8+
// Attributes are forwarded to the input element instead of the wrapper,
9+
// otherwise the `id` would be duplicated and break the label association.
10+
inheritAttrs: false,
11+
}
12+
</script>
13+
14+
<script setup lang="ts">
15+
import { t } from '@nextcloud/l10n'
16+
import { useVModel } from '@vueuse/core'
17+
import { computed, ref } from 'vue'
18+
import NcTextField from '@nextcloud/vue/components/NcTextField'
19+
20+
const props = defineProps<{
21+
// eslint-disable-next-line vue/no-unused-properties
22+
user: string
23+
allowEmail?: boolean
24+
autoCompleteAllowed?: boolean
25+
}>()
26+
27+
defineEmits(['update:user'])
28+
29+
defineExpose({
30+
focus,
31+
})
32+
33+
const userName = useVModel(props, 'user')
34+
35+
const inputElement = ref<InstanceType<typeof NcTextField>>()
36+
37+
const hasError = computed(() => userName.value.length >= 255)
38+
const helperText = computed(() => {
39+
if (hasError.value) {
40+
return t('core', 'Email length is at max (255)')
41+
}
42+
return ''
43+
})
44+
45+
/**
46+
* Focus the input element.
47+
*/
48+
function focus() {
49+
inputElement.value?.focus()
50+
}
51+
</script>
52+
53+
<template>
54+
<NcTextField
55+
id="user"
56+
ref="inputElement"
57+
v-bind="$attrs"
58+
v-model="userName"
59+
:label="allowEmail ? t('core', 'Account name or email') : t('core', 'Account name')"
60+
name="user"
61+
:maxlength="255"
62+
autocapitalize="none"
63+
:autocomplete="autoCompleteAllowed ? 'username' : 'off'"
64+
:error="hasError"
65+
:helper-text="helperText" />
66+
</template>

core/src/components/login/PasswordLessLoginForm.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
</template>
5252

5353
<script type="ts">
54+
import { t } from '@nextcloud/l10n'
5455
import { getBaseUrl } from '@nextcloud/router'
5556
import { browserSupportsWebAuthn } from '@simplewebauthn/browser'
5657
import { defineComponent } from 'vue'
@@ -105,6 +106,7 @@ export default defineComponent({
105106
106107
setup() {
107108
return {
109+
t,
108110
supportsWebauthn: browserSupportsWebAuthn(),
109111
}
110112
},

core/src/components/login/ResetPassword.vue

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@
77
<form class="reset-password-form" @submit.prevent="submit">
88
<h2>{{ t('core', 'Reset password') }}</h2>
99

10-
<NcTextField
10+
<LoginNameInput
1111
id="user"
12-
v-model="user"
13-
name="user"
14-
:maxlength="255"
15-
autocapitalize="off"
16-
:label="t('core', 'Login or email')"
17-
:error="userNameInputLengthIs255"
18-
:helper-text="userInputHelperText"
19-
required
20-
@change="updateUsername" />
12+
:user.sync="user"
13+
@update:user="updateUsername" />
2114

2215
<LoginButton :loading="loading" :value="t('core', 'Reset password')" />
2316

@@ -45,26 +38,24 @@
4538

4639
<script lang="ts">
4740
import axios from '@nextcloud/axios'
41+
import { t } from '@nextcloud/l10n'
4842
import { generateUrl } from '@nextcloud/router'
4943
import { defineComponent } from 'vue'
5044
import NcButton from '@nextcloud/vue/components/NcButton'
5145
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
52-
import NcTextField from '@nextcloud/vue/components/NcTextField'
5346
import LoginButton from './LoginButton.vue'
47+
import LoginNameInput from './LoginNameInput.vue'
5448
import logger from '../../logger.js'
55-
import AuthMixin from '../../mixins/auth.js'
5649
5750
export default defineComponent({
5851
name: 'ResetPassword',
5952
components: {
6053
LoginButton,
6154
NcButton,
6255
NcNoteCard,
63-
NcTextField,
56+
LoginNameInput,
6457
},
6558
66-
mixins: [AuthMixin],
67-
6859
props: {
6960
username: {
7061
type: String,
@@ -77,6 +68,12 @@ export default defineComponent({
7768
},
7869
},
7970
71+
setup() {
72+
return {
73+
t,
74+
}
75+
},
76+
8077
data() {
8178
return {
8279
error: false,

core/src/components/login/UpdatePassword.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
<script>
5050
import Axios from '@nextcloud/axios'
51+
import { t } from '@nextcloud/l10n'
5152
import LoginButton from './LoginButton.vue'
5253
5354
export default {
@@ -68,6 +69,12 @@ export default {
6869
},
6970
},
7071
72+
setup() {
73+
return {
74+
t,
75+
}
76+
},
77+
7178
data() {
7279
return {
7380
error: false,

core/src/legacy-unified-search.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,11 @@
44
*/
55

66
import { getCSPNonce } from '@nextcloud/auth'
7-
import { n, t } from '@nextcloud/l10n'
8-
import { getLoggerBuilder } from '@nextcloud/logger'
97
import Vue from 'vue'
108
import UnifiedSearch from './views/LegacyUnifiedSearch.vue'
119

1210
__webpack_nonce__ = getCSPNonce()
1311

14-
const logger = getLoggerBuilder()
15-
.setApp('unified-search')
16-
.detectUser()
17-
.build()
18-
19-
Vue.mixin({
20-
data() {
21-
return {
22-
logger,
23-
}
24-
},
25-
methods: {
26-
t,
27-
n,
28-
},
29-
})
30-
3112
export default new Vue({
3213
el: '#unified-search',
3314
name: 'UnifiedSearchRoot',

core/src/login.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@
55

66
import Vue from 'vue'
77
import LoginView from './views/Login.vue'
8-
import Nextcloud from './mixins/Nextcloud.js'
98
// eslint-disable-next-line no-unused-vars
109
import OC from './OC/index.js' // TODO: Not needed but L10n breaks if removed
1110

12-
Vue.mixin(Nextcloud)
13-
1411
const View = Vue.extend(LoginView)
1512
new View().$mount('#login')

core/src/mixins/Nextcloud.js

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)