mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
[enh] Add Import user view
This commit is contained in:
parent
d90cc05d58
commit
f2dbbe91d0
5 changed files with 171 additions and 9 deletions
|
@ -38,8 +38,8 @@ import { openWebSocket, getResponseData, handleError } from './handlers'
|
||||||
* @param {Boolean} [options.addLocale=false] - Option to append the locale to the query string.
|
* @param {Boolean} [options.addLocale=false] - Option to append the locale to the query string.
|
||||||
* @return {URLSearchParams}
|
* @return {URLSearchParams}
|
||||||
*/
|
*/
|
||||||
export function objectToParams (obj, { addLocale = false } = {}) {
|
export function objectToParams (obj, { addLocale = false } = {}, formData = false) {
|
||||||
const urlParams = new URLSearchParams()
|
const urlParams = (formData) ? new FormData() : new URLSearchParams()
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach(v => urlParams.append(key, v))
|
value.forEach(v => urlParams.append(key, v))
|
||||||
|
@ -96,14 +96,9 @@ export default {
|
||||||
if (method === 'GET') {
|
if (method === 'GET') {
|
||||||
uri += `${uri.includes('?') ? '&' : '?'}locale=${store.getters.locale}`
|
uri += `${uri.includes('?') ? '&' : '?'}locale=${store.getters.locale}`
|
||||||
} else {
|
} else {
|
||||||
options = { ...options, method, body: objectToParams(data, { addLocale: true }) }
|
options = { ...options, method, body: objectToParams(data, { addLocale: true }, true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch('/yunohost/api/' + uri, options)
|
|
||||||
const responseData = await getResponseData(response)
|
|
||||||
store.dispatch('END_REQUEST', { request, success: response.ok, wait })
|
|
||||||
|
|
||||||
return response.ok ? responseData : handleError(request, response, responseData)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
31
app/src/components/globals/formItems/FileItem.vue
Normal file
31
app/src/components/globals/formItems/FileItem.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<b-form-file
|
||||||
|
:id="id"
|
||||||
|
v-model="file"
|
||||||
|
v-on="$listeners"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:drop-placeholder="dropPlaceholder"
|
||||||
|
:state="Boolean(file)"
|
||||||
|
:required="required"
|
||||||
|
:accept="accept"
|
||||||
|
@blur="$parent.$emit('touch', name)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'FileItem',
|
||||||
|
data () {
|
||||||
|
return { file: null }
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
id: { type: String, default: null },
|
||||||
|
placeholder: { type: String, default: null },
|
||||||
|
dropPlaceholder: { type: String, default: null },
|
||||||
|
required: { type: Boolean, default: false },
|
||||||
|
state: { type: Boolean, default: null },
|
||||||
|
name: { type: String, default: null },
|
||||||
|
accept: { type: String, default: null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -293,7 +293,8 @@
|
||||||
"firstname": "John",
|
"firstname": "John",
|
||||||
"lastname": "Doe",
|
"lastname": "Doe",
|
||||||
"groupname": "My group name",
|
"groupname": "My group name",
|
||||||
"domain": "my-domain.com"
|
"domain": "my-domain.com",
|
||||||
|
"file": "Browse a file or drag and drop it"
|
||||||
},
|
},
|
||||||
"logs": "Logs",
|
"logs": "Logs",
|
||||||
"logs_suboperations": "Sub-operations",
|
"logs_suboperations": "Sub-operations",
|
||||||
|
@ -489,6 +490,15 @@
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
"users_new": "New user",
|
"users_new": "New user",
|
||||||
"users_no": "No users.",
|
"users_no": "No users.",
|
||||||
|
"users_import": "Import users",
|
||||||
|
"users_import_csv_file": "CSV File",
|
||||||
|
"users_import_update": "Update existing users",
|
||||||
|
"users_import_delete": "Delete non listed users",
|
||||||
|
"users_import_csv_file_desc": "The CSV file should be in UTF-8 and with columns username, password, groups, email and quota. See <a href=''>example import csv file</a>.",
|
||||||
|
"users_import_update_desc": "If checked, all existing users contained in the csv file will be updated with the ne new value",
|
||||||
|
"users_import_delete_desc": "If checked, all existing users that are not in the csv file will be deleted (and purged).",
|
||||||
|
"users_import_confirm_destructive": "Are you sure you want to delete users that are not present in this file?",
|
||||||
|
"users_import_delete_others": "Delete unlisted users",
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
"warnings": "{count} warnings",
|
"warnings": "{count} warnings",
|
||||||
"words": {
|
"words": {
|
||||||
|
|
|
@ -60,6 +60,16 @@ const routes = [
|
||||||
breadcrumb: ['user-list', 'user-create']
|
breadcrumb: ['user-list', 'user-create']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'user-import',
|
||||||
|
path: '/users/import',
|
||||||
|
component: () => import(/* webpackChunkName: "views/user/import" */ '@/views/user/UserImport'),
|
||||||
|
props: true,
|
||||||
|
meta: {
|
||||||
|
args: { param: 'name' },
|
||||||
|
breadcrumb: ['user-list', 'user-import']
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'user-info',
|
name: 'user-info',
|
||||||
path: '/users/:name',
|
path: '/users/:name',
|
||||||
|
|
116
app/src/views/user/UserImport.vue
Normal file
116
app/src/views/user/UserImport.vue
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<card-form
|
||||||
|
:title="$t('users_import')" icon="user-plus"
|
||||||
|
:validation="$v" :server-error="serverError"
|
||||||
|
@submit.prevent="beforeImport"
|
||||||
|
>
|
||||||
|
<!-- CSV FILE -->
|
||||||
|
<form-field component="FileItem" v-bind="fields.csv" v-model="form.csv"
|
||||||
|
:validation="$v.form.csv" accept=".csv" />
|
||||||
|
<!-- UPDATE -->
|
||||||
|
<form-field component="CheckboxItem" v-bind="fields.update" v-model="form.update"
|
||||||
|
:validation="$v.form.update" />
|
||||||
|
<!-- DELETE -->
|
||||||
|
<form-field component="CheckboxItem" v-bind="fields.delete" v-model="form.delete"
|
||||||
|
:validation="$v.form.delete" />
|
||||||
|
</card-form>
|
||||||
|
<!-- CONFIRM DESTRUCTIVE IMPORT MODAL -->
|
||||||
|
<b-modal
|
||||||
|
id="confirm-destructive-import-modal" ref="confirm-destructive-import-modal" centered
|
||||||
|
body-bg-variant="danger" body-text-variant="light"
|
||||||
|
@ok="onSubmit" hide-header
|
||||||
|
:ok-title="$t('users_import_delete_others')"
|
||||||
|
>
|
||||||
|
{{ $t('users_import_confirm_destructive') }}
|
||||||
|
</b-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import { mapGetters } from 'vuex'
|
||||||
|
import { validationMixin } from 'vuelidate'
|
||||||
|
|
||||||
|
import { formatFormData } from '@/helpers/yunohostArguments'
|
||||||
|
import {
|
||||||
|
required
|
||||||
|
} from '@/helpers/validators'
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'UserImport',
|
||||||
|
|
||||||
|
mixins: [validationMixin],
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
csv: '',
|
||||||
|
update: false,
|
||||||
|
delete: false
|
||||||
|
},
|
||||||
|
|
||||||
|
serverError: '',
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
csv: {
|
||||||
|
label: this.$i18n.t('users_import_csv_file'),
|
||||||
|
description: this.$i18n.t('users_import_csv_file_desc'),
|
||||||
|
props: {
|
||||||
|
id: 'csv',
|
||||||
|
placeholder: this.$i18n.t('placeholder.file')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
label: this.$i18n.t('users_import_update'),
|
||||||
|
description: this.$i18n.t('users_import_update_desc'),
|
||||||
|
props: {
|
||||||
|
id: 'update'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
label: this.$i18n.t('users_import_delete'),
|
||||||
|
description: this.$i18n.t('users_import_delete_desc'),
|
||||||
|
props: {
|
||||||
|
id: 'delete'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validations () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
csv: { required },
|
||||||
|
update: { },
|
||||||
|
delete: { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
beforeImport () {
|
||||||
|
if (this.form.delete) {
|
||||||
|
this.$refs['confirm-destructive-import-modal'].show()
|
||||||
|
} else {
|
||||||
|
this.onSubmit()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onSubmit () {
|
||||||
|
const data = formatFormData(this.form, { flatten: true })
|
||||||
|
this.$store.dispatch(
|
||||||
|
'POST', { uri: 'users/import', data }
|
||||||
|
).then(() => {
|
||||||
|
this.$router.push({ name: 'user-list' })
|
||||||
|
}).catch(error => {
|
||||||
|
this.serverError = error.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created () {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in a new issue