Skip to content

Commit 1ad982d

Browse files
skjnldsvbackportbot[bot]
authored andcommitted
feat: add guest auth prompt component
Signed-off-by: skjnldsv <skjnldsv@protonmail.com> [skip ci]
1 parent 961a4d0 commit 1ad982d

File tree

5 files changed

+284
-0
lines changed

5 files changed

+284
-0
lines changed

l10n/messages.pot

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ msgstr ""
1414
msgid "All files"
1515
msgstr ""
1616

17+
msgid "Cancel"
18+
msgstr ""
19+
1720
msgid "Choose"
1821
msgstr ""
1922

@@ -46,6 +49,12 @@ msgstr ""
4649
msgid "Current view selector"
4750
msgstr ""
4851

52+
msgid "Enter your name"
53+
msgstr ""
54+
55+
msgid "Failed to set nickname."
56+
msgstr ""
57+
4958
msgid "Favorites"
5059
msgstr ""
5160

@@ -61,6 +70,9 @@ msgstr ""
6170
msgid "Folder name cannot be empty."
6271
msgstr ""
6372

73+
msgid "Guest identification"
74+
msgstr ""
75+
6476
msgid "Home"
6577
msgstr ""
6678

@@ -94,6 +106,9 @@ msgstr ""
94106
msgid "No matching files"
95107
msgstr ""
96108

109+
msgid "Please enter a name with at least 2 characters."
110+
msgstr ""
111+
97112
msgid "Recent"
98113
msgstr ""
99114

@@ -109,8 +124,17 @@ msgstr ""
109124
msgid "Size"
110125
msgstr ""
111126

127+
msgid "Submit name"
128+
msgstr ""
129+
112130
msgid "Undo"
113131
msgstr ""
114132

115133
msgid "Upload some content or sync with your devices!"
116134
msgstr ""
135+
136+
msgid "You are currently not identified."
137+
msgstr ""
138+
139+
msgid "You cannot leave the name empty."
140+
msgstr ""
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<template>
7+
<NcDialog :buttons="dialogButtons"
8+
class="public-auth-prompt"
9+
data-cy-public-auth-prompt-dialog
10+
is-form
11+
no-close
12+
:name="title"
13+
@submit="onSubmit">
14+
<p v-if="text" class="public-auth-prompt__text">
15+
{{ text }}
16+
</p>
17+
18+
<!-- Header -->
19+
<NcNoteCard class="public-auth-prompt__header"
20+
:text="notice"
21+
type="info" />
22+
23+
<!-- Form -->
24+
<NcTextField ref="input"
25+
class="public-auth-prompt__input"
26+
data-cy-public-auth-prompt-dialog-name
27+
:label="t('Name')"
28+
:placeholder="t('Enter your name')"
29+
:required="!cancellable"
30+
v-model="name"
31+
minlength="2"
32+
name="name" />
33+
</NcDialog>
34+
</template>
35+
36+
<script lang="ts">
37+
import { defineComponent } from 'vue'
38+
import { getBuilder } from '@nextcloud/browser-storage'
39+
import { setGuestNickname } from '@nextcloud/auth'
40+
import { showError } from '@nextcloud/dialogs'
41+
42+
import NcButton from '@nextcloud/vue/components/NcButton'
43+
import NcDialog from '@nextcloud/vue/components/NcDialog'
44+
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
45+
import NcTextField from '@nextcloud/vue/components/NcTextField'
46+
47+
import { t } from '../utils/l10n.ts'
48+
49+
const storage = getBuilder('public').build()
50+
51+
export default defineComponent({
52+
name: 'PublicAuthPrompt',
53+
54+
components: {
55+
NcDialog,
56+
NcNoteCard,
57+
NcTextField,
58+
},
59+
60+
props: {
61+
/**
62+
* Preselected nickname
63+
* @default '' No name preselected by default
64+
*/
65+
nickname: {
66+
type: String,
67+
default: '',
68+
},
69+
70+
/**
71+
* Dialog title
72+
*/
73+
title: {
74+
type: String,
75+
default: t('Guest identification'),
76+
},
77+
78+
/**
79+
* Dialog text under the dialog title
80+
* e.g 'Enter your name to access the file'
81+
* @default '' Not shown by default
82+
*/
83+
text: {
84+
type: String,
85+
default: '',
86+
},
87+
88+
/**
89+
* Dialog notice
90+
* @default 'You are currently not identified.'
91+
*/
92+
notice: {
93+
type: String,
94+
default: t('You are currently not identified.'),
95+
},
96+
97+
/**
98+
* Dialog submit button label
99+
* @default 'Submit name'
100+
*/
101+
submitLabel: {
102+
type: String,
103+
default: t('Submit name'),
104+
},
105+
106+
/**
107+
* Whether the dialog is cancellable
108+
* @default false
109+
*/
110+
cancellable: {
111+
type: Boolean,
112+
default: false,
113+
},
114+
},
115+
116+
setup() {
117+
return {
118+
t,
119+
}
120+
},
121+
122+
emits: ['close'],
123+
124+
data() {
125+
return {
126+
name: '',
127+
}
128+
},
129+
130+
computed: {
131+
dialogButtons() {
132+
const cancelButton = {
133+
label: t('Cancel'),
134+
variant: 'tertiary',
135+
callback: () => this.$emit('close'),
136+
}
137+
138+
const submitButton = {
139+
label: this.submitLabel,
140+
type: 'submit',
141+
variant: 'primary',
142+
}
143+
144+
// If the dialog is cancellable, add a cancel button
145+
if (this.cancellable) {
146+
return [cancelButton, submitButton]
147+
}
148+
149+
return [submitButton]
150+
},
151+
},
152+
153+
watch: {
154+
/** Reset name to pre-selected nickname (e.g. Talk / Collabora ) */
155+
nickname: {
156+
handler() {
157+
this.name = this.nickname
158+
},
159+
immediate: true,
160+
},
161+
},
162+
163+
methods: {
164+
onSubmit() {
165+
const input = this.$refs.input as HTMLInputElement
166+
const nickname = this.name.trim()
167+
168+
if (nickname === '') {
169+
// Show error if the nickname is empty
170+
input.setCustomValidity(t('You cannot leave the name empty.'))
171+
input.reportValidity()
172+
input.focus()
173+
return
174+
}
175+
176+
if (nickname.length < 2) {
177+
// Show error if the nickname is too short
178+
input.setCustomValidity(t('Please enter a name with at least 2 characters.'))
179+
input.reportValidity()
180+
input.focus()
181+
return
182+
}
183+
184+
try {
185+
// Set the nickname
186+
setGuestNickname(nickname)
187+
} catch (e) {
188+
showError(t('Failed to set nickname.'))
189+
console.error('Failed to set nickname', e)
190+
input.focus()
191+
return
192+
}
193+
194+
// Set the dialog as shown
195+
storage.setItem('public-auth-prompt-shown', 'true')
196+
197+
// Close the dialog
198+
this.$emit('close', this.name)
199+
},
200+
},
201+
})
202+
</script>
203+
<style scoped lang="scss">
204+
.public-auth-prompt {
205+
&__text {
206+
// Smaller than dialog title
207+
font-size: 1.25em;
208+
margin-block: 0 calc(3 * var(--default-grid-baseline));
209+
}
210+
211+
&__header {
212+
margin-block: 0 calc(3 * var(--default-grid-baseline));
213+
// No extra top margin for the first child
214+
&:first-child {
215+
margin-top: 0;
216+
}
217+
}
218+
219+
&__input {
220+
margin-block: calc(4 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline));
221+
}
222+
}
223+
</style>

lib/public-auth.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import type { ComponentProps } from 'vue-component-type-helpers'
7+
import { defineAsyncComponent } from 'vue'
8+
import { spawnDialog } from '@nextcloud/vue/functions/dialog'
9+
10+
import type PublicAuthPrompt from './components/PublicAuthPrompt.vue'
11+
12+
type PublicAuthPromptProps = ComponentProps<typeof PublicAuthPrompt>
13+
14+
/**
15+
* Show the public auth prompt dialog
16+
* This is used to ask the current user their nickname
17+
* as well as show some additional contextual information
18+
* @param props The props to pass to the dialog, see PublicAuthPrompt.vue for details
19+
*/
20+
export function showGuestUserPrompt(props: PublicAuthPromptProps) {
21+
return new Promise((resolve) => {
22+
spawnDialog(
23+
defineAsyncComponent(() => import('./components/PublicAuthPrompt.vue')),
24+
props,
25+
resolve,
26+
)
27+
})
28+
}

package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@mdi/js": "^7.4.47",
4444
"@nextcloud/auth": "^2.4.0",
4545
"@nextcloud/axios": "^2.5.1",
46+
"@nextcloud/browser-storage": "^0.4.0",
4647
"@nextcloud/event-bus": "^3.3.2",
4748
"@nextcloud/files": "^3.10.2",
4849
"@nextcloud/initial-state": "^2.2.0",

0 commit comments

Comments
 (0)