diff --git a/.gitignore b/.gitignore
index a724e6a..703e601 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ yarn-error.log
# No need for sharing this
yarn.lock
+.idea
+
diff --git a/src/components/UpdateUser.vue b/src/components/UpdateUser.vue
index 669ad43..af03710 100644
--- a/src/components/UpdateUser.vue
+++ b/src/components/UpdateUser.vue
@@ -15,6 +15,7 @@ import { defineComponent, ref, onMounted } from 'vue';
import MainUserSettings from './settings/MainUserSettings.vue';
import UserSelector from './UserSelector.vue';
import { useMainStore, useUserStore } from '@flaschengeist/api';
+import { Notify } from 'quasar';
export default defineComponent({
name: 'UpdateUser',
@@ -25,12 +26,20 @@ export default defineComponent({
const user = ref(mainStore.currentUser);
onMounted(() => {
- void userStore.getUsers(true)
- })
+ void userStore.getUsers(true);
+ });
async function updateUser(value: FG.User) {
await userStore.updateUser(value);
user.value = value;
+ Notify.create({
+ group: false,
+ type: 'positive',
+ message: 'Ă„nderungen gespeichert',
+ timeout: 4000,
+ progress: true,
+ actions: [{ icon: 'mdi-close', color: 'white' }],
+ });
}
return {
diff --git a/src/components/Widget.vue b/src/components/Widget.vue
index 79dca5c..3133c81 100644
--- a/src/components/Widget.vue
+++ b/src/components/Widget.vue
@@ -4,7 +4,12 @@
-
+
+
@@ -41,6 +46,7 @@ export default defineComponent({
const avatar = ref(true);
const name = ref(mainStore.currentUser.firstname);
const avatarLink = ref(mainStore.currentUser.avatar_url);
+ const avatarError = ref(false);
function error() {
avatar.value = false;
@@ -65,7 +71,7 @@ export default defineComponent({
.filter((user) => user.userid !== mainStore.currentUser.userid)
);
- return { avatar, avatarLink, error, name, hasBirthday, birthday, api };
+ return { avatar, avatarLink, error, name, hasBirthday, birthday, api, avatarError };
},
});
diff --git a/src/components/settings/MainUserSettings.vue b/src/components/settings/MainUserSettings.vue
index 7d48135..8f5e4ed 100644
--- a/src/components/settings/MainUserSettings.vue
+++ b/src/components/settings/MainUserSettings.vue
@@ -66,12 +66,22 @@
filled
label="Avatar"
accept=".jpg, image/*"
- max-file-size="204800"
- hint="Bilddateien, max. 200 KiB"
+ hint="Bilddateien nur JPEG"
+ :clearable="avatar.name !== '' || deleteAvatar"
+ @update:model-value="imagePreview"
+ @clear="clear"
@rejected="onAvatarRejected"
>
-
-
+
+
+
+
+
+
+
+
+
+
@@ -106,7 +116,14 @@
import { Notify } from 'quasar';
import { IsoDateInput, PasswordInput } from '@flaschengeist/api/components';
import { defineComponent, computed, ref, onBeforeMount, PropType, watchEffect } from 'vue';
-import { hasPermission, notEmpty, isEmail, useMainStore, useUserStore } from '@flaschengeist/api';
+import {
+ hasPermission,
+ notEmpty,
+ isEmail,
+ useMainStore,
+ useUserStore,
+ api,
+} from '@flaschengeist/api';
export default defineComponent({
name: 'MainUserSettings',
@@ -131,13 +148,20 @@ export default defineComponent({
const password = ref('');
const newPassword = ref('');
- const avatar = ref();
+ const avatar = ref(new File([], '', {}));
+ const avatarError = ref(false);
const userModel = ref(Object.assign({}, props.user));
const canSetRoles = computed(() => hasPermission('users_set_roles'));
const allRoles = computed(() => userStore.roles.map((role) => role.name));
const isCurrentUser = computed(() => userModel.value.userid === mainStore.currentUser.userid);
+ const _deleteAvatar = ref(false);
+ const deleteAvatar = computed({
+ get: () => _deleteAvatar.value,
+ set: (val: boolean) => (_deleteAvatar.value = val),
+ });
+
/* Reset model if props changed */
watchEffect(() => {
if (props.user.userid && props.user.userid !== userModel.value.userid) reset();
@@ -152,11 +176,11 @@ export default defineComponent({
progress: true,
actions: [{ icon: 'mdi-close', color: 'white' }],
});
- avatar.value = undefined;
+ avatar.value = new File([], '', {});
}
- function save() {
- let changed = userModel.value;
+ async function save() {
+ let changed: FG.User = userModel.value;
if (typeof changed.birthday === 'string') changed.birthday = new Date(changed.birthday);
changed = Object.assign(changed, {
password: password.value,
@@ -169,20 +193,26 @@ export default defineComponent({
emit('update:user', changed);
- if (avatar.value)
- userStore
+ if (avatar.value instanceof File && avatar.value.name)
+ await userStore
.uploadAvatar(changed, avatar.value instanceof File ? avatar.value : avatar.value[0])
.catch((response: Response) => {
if (response && response.status == 400) {
onAvatarRejected();
}
});
+ if (deleteAvatar.value) {
+ await userStore.deleteAvatar(changed);
+ }
+ password.value = '';
}
function reset() {
userModel.value = Object.assign({}, props.user);
password.value = '';
newPassword.value = '';
+ imgsrc.value = undefined;
+ deleteAvatar.value = false;
}
function isFreeUID(val: string) {
@@ -192,6 +222,45 @@ export default defineComponent({
);
}
+ const imgsrc = ref();
+
+ const image = computed(() => {
+ if (imgsrc.value) {
+ return imgsrc.value;
+ }
+ if (props.user.avatar_url && !deleteAvatar.value) {
+ return `${api.defaults.baseURL || ''}${props.user.avatar_url}`;
+ }
+ return 'no-image.svg';
+ });
+
+ function imagePreview() {
+ if (avatar.value && avatar.value instanceof File) {
+ let reader = new FileReader();
+
+ reader.onload = (e) => {
+ imgsrc.value = e.target?.result;
+ };
+
+ reader.readAsDataURL(avatar.value);
+ }
+ }
+ function clear(val: File) {
+ avatar.value = new File([], '', {});
+ imgsrc.value = undefined;
+ deleteAvatar.value = false;
+ }
+
+ function toDeleteAvatar() {
+ avatar.value = new File([], '', {});
+ imgsrc.value = undefined;
+ deleteAvatar.value = true;
+ }
+
+ function error() {
+ avatarError.value = true;
+ }
+
return {
allRoles,
avatar,
@@ -206,6 +275,13 @@ export default defineComponent({
reset,
save,
userModel,
+ image,
+ imagePreview,
+ clear,
+ deleteAvatar,
+ avatarError,
+ toDeleteAvatar,
+ error,
};
},
});
diff --git a/src/pages/AdminSettings.vue b/src/pages/AdminSettings.vue
index 33192d1..60159a0 100644
--- a/src/pages/AdminSettings.vue
+++ b/src/pages/AdminSettings.vue
@@ -65,14 +65,20 @@ export default defineComponent({
}
const tabs: Tab[] = [
- { name: 'user', label: 'Mitglieder', permissions: [PERMISSIONS.EDIT_OTHER, PERMISSIONS.SET_ROLES] },
+ {
+ name: 'user',
+ label: 'Mitglieder',
+ permissions: [PERMISSIONS.EDIT_OTHER, PERMISSIONS.SET_ROLES],
+ },
{ name: 'newUser', label: 'Neues Mitglied', permissions: [PERMISSIONS.SET_ROLES] },
{ name: 'roles', label: 'Rollen', permissions: [PERMISSIONS.ROLES_EDIT] },
];
- const _tabs = computed(() => tabs.filter(tab => {
- return tab.permissions.every(permission => hasPermission(permission))
- }))
+ const _tabs = computed(() =>
+ tabs.filter((tab) => {
+ return tab.permissions.every((permission) => hasPermission(permission));
+ })
+ );
const drawer = ref(false);
diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue
index e0d15b7..182ba43 100644
--- a/src/pages/Settings.vue
+++ b/src/pages/Settings.vue
@@ -23,6 +23,7 @@ import { useMainStore, useUserStore, useSessionStore } from '@flaschengeist/api'
import MainUserSettings from '../components/settings/MainUserSettings.vue';
import { defineComponent, onBeforeMount, ref } from 'vue';
import Session from '../components/settings/Session.vue';
+import { Notify } from 'quasar';
export default defineComponent({
name: 'UserSettings',
@@ -38,6 +39,14 @@ export default defineComponent({
async function updateUser(value: FG.User) {
await userStore.updateUser(value);
+ Notify.create({
+ group: false,
+ type: 'positive',
+ message: 'Ă„nderungen gespeichert',
+ timeout: 4000,
+ progress: true,
+ actions: [{ icon: 'mdi-close', color: 'white' }],
+ });
}
function removeSession(s: FG.Session) {