Skip to content

Commit d4eae42

Browse files
authored
Merge pull request #1616 from nextcloud/ernolf/fix/persist-guest-allowlist
fix(settings): save the guest allowlist again
2 parents 1da3109 + 457cfda commit d4eae42

1 file changed

Lines changed: 107 additions & 13 deletions

File tree

src/views/GuestSettings.vue

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,50 @@
8484
{{ t('guests', 'Limit guest access to an app\'s allowlist') }}
8585
</NcCheckboxRadioSwitch>
8686

87-
<p v-if="config.useWhitelist" class="allowlist">
88-
<NcSelect
89-
v-model="config.whitelist"
90-
:options="config.whiteListableApps"
91-
:multiple="true"
92-
:closeOnSelect="false"
93-
:clearSearchOnSelect="false"
94-
@input="saveConfig" />
87+
<div v-if="config.useWhitelist" class="allowlist">
88+
<!-- Read-only display with an edit (pencil) button -->
89+
<div v-if="!editingAllowlist" class="allowlist__row allowlist__row--display">
90+
<ul v-if="allowlistApps.length" class="allowlist__apps">
91+
<li v-for="app in allowlistApps" :key="app" class="allowlist__app">
92+
{{ app }}
93+
</li>
94+
</ul>
95+
<span v-else class="allowlist__empty">{{ t('guests', 'No apps selected') }}</span>
96+
<NcButton
97+
variant="tertiary"
98+
:aria-label="t('guests', 'Edit allowlist')"
99+
:title="t('guests', 'Edit allowlist')"
100+
@click="startEditAllowlist">
101+
<template #icon>
102+
<Pencil :size="20" />
103+
</template>
104+
</NcButton>
105+
</div>
106+
<!-- Edit mode: changes are only persisted when confirmed -->
107+
<div v-else class="allowlist__row">
108+
<NcSelect
109+
v-model="whitelistDraft"
110+
class="allowlist__select"
111+
:options="config.whiteListableApps"
112+
:multiple="true"
113+
keepOpen />
114+
<NcButton
115+
variant="tertiary"
116+
:aria-label="t('guests', 'Confirm allowlist')"
117+
:title="t('guests', 'Confirm allowlist')"
118+
@click="confirmAllowlist">
119+
<template #icon>
120+
<Check :size="20" />
121+
</template>
122+
</NcButton>
123+
</div>
95124
<NcButton variant="secondary" class="reset-button" @click="reset">
96125
<template #icon>
97126
<History :size="16" />
98127
</template>
99128
{{ t('guests', 'Reset allowlist') }}
100129
</NcButton>
101-
</p>
130+
</div>
102131
</div>
103132
<div v-if="!loaded">
104133
<div class="loading" />
@@ -121,13 +150,16 @@ import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
121150
import NcSelect from '@nextcloud/vue/components/NcSelect'
122151
import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'
123152
import NcSettingsSelectGroup from '@nextcloud/vue/components/NcSettingsSelectGroup'
153+
import Check from 'vue-material-design-icons/Check.vue'
124154
import History from 'vue-material-design-icons/History.vue'
155+
import Pencil from 'vue-material-design-icons/Pencil.vue'
125156
import GuestList from '../components/GuestList.vue'
126157
import { logger } from '../services/logger.ts'
127158
128159
export default {
129160
name: 'GuestSettings',
130161
components: {
162+
Check,
131163
GuestList,
132164
History,
133165
NcButton,
@@ -136,6 +168,7 @@ export default {
136168
NcSelect,
137169
NcSettingsSection,
138170
NcSettingsSelectGroup,
171+
Pencil,
139172
},
140173
141174
data() {
@@ -145,6 +178,8 @@ export default {
145178
saved: false,
146179
saving: false,
147180
savingTimeout: null,
181+
editingAllowlist: false,
182+
whitelistDraft: [],
148183
config: {
149184
useWhitelist: false,
150185
allowExternalStorage: false,
@@ -159,6 +194,15 @@ export default {
159194
},
160195
161196
computed: {
197+
allowlistApps() {
198+
// getAppWhitelist() returns [''] for an empty allowlist (explode of an
199+
// empty string), so drop empty entries to show the placeholder instead
200+
// of a blank chip.
201+
return (this.config.whitelist ?? [])
202+
.map((app) => (typeof app === 'string' ? app : (app.label ?? app.id ?? app.name ?? String(app))))
203+
.filter(Boolean)
204+
},
205+
162206
statusText() {
163207
if (this.error) {
164208
return t('guests', 'Error')
@@ -180,6 +224,19 @@ export default {
180224
methods: {
181225
t,
182226
227+
startEditAllowlist() {
228+
// Drop the empty entry from an empty allowlist so the selector does
229+
// not start with a blank, removable tag.
230+
this.whitelistDraft = (this.config.whitelist ?? []).filter(Boolean)
231+
this.editingAllowlist = true
232+
},
233+
234+
confirmAllowlist() {
235+
this.config.whitelist = [...this.whitelistDraft]
236+
this.editingAllowlist = false
237+
this.saveConfig()
238+
},
239+
183240
async loadConfig() {
184241
const { data } = await axios.get(generateUrl('apps/guests/config'))
185242
this.config = data
@@ -208,6 +265,9 @@ export default {
208265
try {
209266
const { data } = await axios.post(generateUrl('apps/guests/whitelist/reset'))
210267
this.config.whitelist = data.whitelist
268+
if (this.editingAllowlist) {
269+
this.whitelistDraft = [...data.whitelist]
270+
}
211271
this.saved = true
212272
} catch (error) {
213273
this.error = true
@@ -266,12 +326,46 @@ export default {
266326
}
267327
268328
.allowlist {
269-
max-width: 500px;
329+
max-width: 690px;
330+
margin-inline-start: var(--default-clickable-area);
270331
271-
.multiselect {
272-
width: calc(100% - 48px);
273-
margin-right: 0;
332+
&__row {
333+
display: flex;
334+
align-items: center;
335+
gap: 8px;
274336
margin-top: 1rem;
337+
338+
&--display {
339+
align-items: flex-start;
340+
}
341+
}
342+
343+
&__apps {
344+
flex: 1 1 auto;
345+
display: flex;
346+
flex-wrap: wrap;
347+
gap: 4px;
348+
min-width: 0;
349+
padding-top: 4px;
350+
}
351+
352+
&__app {
353+
padding: 2px 10px;
354+
background-color: var(--color-background-dark);
355+
border-radius: var(--border-radius-pill, 1rem);
356+
color: var(--color-text-maxcontrast);
357+
font-size: 0.9em;
358+
}
359+
360+
&__empty {
361+
flex: 1 1 auto;
362+
padding-top: 6px;
363+
color: var(--color-text-maxcontrast);
364+
}
365+
366+
&__select {
367+
flex: 1 1 auto;
368+
min-width: 0;
275369
}
276370
277371
.reset-button {

0 commit comments

Comments
 (0)