Image Upload
This commit is contained in:
parent
0771b43f56
commit
91ede95530
4 changed files with 117 additions and 34 deletions
|
@ -9,7 +9,14 @@
|
||||||
<button type="submit" class="!w-fit !h-fit !p-0">
|
<button type="submit" class="!w-fit !h-fit !p-0">
|
||||||
<CheckIcon class="h-5 w-5 cursor-pointer" />
|
<CheckIcon class="h-5 w-5 cursor-pointer" />
|
||||||
</button>
|
</button>
|
||||||
<button type="reset" class="!w-fit !h-fit !p-0" @click="enableEdit = false">
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="!w-fit !h-fit !p-0"
|
||||||
|
@click="
|
||||||
|
enableEdit = false;
|
||||||
|
$emit('reset');
|
||||||
|
"
|
||||||
|
>
|
||||||
<XMarkIcon class="h-5 w-5 cursor-pointer" />
|
<XMarkIcon class="h-5 w-5 cursor-pointer" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,6 +55,7 @@ export default defineComponent({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
emits: ["reset"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
enableEdit: false as boolean,
|
enableEdit: false as boolean,
|
||||||
|
|
|
@ -1,31 +1,48 @@
|
||||||
<template>
|
<template>
|
||||||
<BaseSetting title="Vereins-Auftritt Einstellungen" :submit-function="submit" v-slot="{ enableEdit }">
|
<BaseSetting title="Vereins-Auftritt Einstellungen" :submit-function="submit" v-slot="{ enableEdit }" @reset="reset">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p>Vereins-Icon</p>
|
<p>Vereins-Icon</p>
|
||||||
<AppIcon v-if="clubSettings['club.icon'] != '' && !overwriteIcon" class="h-10! max-w-full mx-auto" />
|
<div class="flex flex-row gap-2">
|
||||||
<img v-else-if="overwriteIcon" ref="icon_img" class="hidden w-full h-20 object-contain" />
|
<AppIcon v-if="icon != '' && !overwriteIcon" class="h-10! max-w-full mx-auto" />
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else-if="!overwriteIcon"
|
||||||
class="flex h-10 w-full border-2 border-gray-300 rounded-md items-center justify-center text-sm cursor-pointer"
|
class="flex h-10 w-full border-2 border-gray-300 rounded-md items-center justify-center text-sm"
|
||||||
@click="($refs.icon as HTMLInputElement).click()"
|
:class="{ 'cursor-pointer': enableEdit }"
|
||||||
|
@click="enableEdit ? ($refs.icon as HTMLInputElement).click() : null"
|
||||||
>
|
>
|
||||||
Kein eigenes Icon ausgewählt
|
Kein eigenes Icon ausgewählt
|
||||||
</div>
|
</div>
|
||||||
|
<img ref="icon_img" class="hidden w-full h-20 object-contain" />
|
||||||
|
<XMarkIcon
|
||||||
|
v-if="enableEdit && (icon != '' || overwriteIcon)"
|
||||||
|
class="h-5 w-5 cursor-pointer"
|
||||||
|
@click="resetImage('icon')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<input class="hidden!" type="file" ref="icon" accept="image/*" @change="previewImage('icon')" />
|
<input class="hidden!" type="file" ref="icon" accept="image/*" @change="previewImage('icon')" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p>Vereins-Logo</p>
|
<p>Vereins-Logo</p>
|
||||||
<AppLogo v-if="clubSettings['club.logo'] != '' && !overwriteLogo" class="h-10! max-w-full mx-auto" />
|
<div class="flex flex-row gap-2">
|
||||||
<img v-else-if="overwriteLogo" ref="logo_img" class="hidden w-full h-20 object-contain" />
|
<AppLogo v-if="logo != '' && !overwriteLogo" class="h-10! max-w-full mx-auto" />
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else-if="!overwriteLogo"
|
||||||
class="flex h-10 w-full border-2 border-gray-300 rounded-md items-center justify-center text-sm cursor-pointer"
|
class="flex h-10 w-full border-2 border-gray-300 rounded-md items-center justify-center text-sm"
|
||||||
@click="($refs.logo as HTMLInputElement).click()"
|
:class="{ 'cursor-pointer': enableEdit }"
|
||||||
|
@click="enableEdit ? ($refs.logo as HTMLInputElement).click() : null"
|
||||||
>
|
>
|
||||||
Kein eigenes Logo ausgewählt
|
Kein eigenes Logo ausgewählt
|
||||||
</div>
|
</div>
|
||||||
<input class="hidden!" type="file" ref="logo" accept="image/*" @change="previewImage('logo')" /></div
|
<img ref="logo_img" class="hidden w-full h-20 object-contain" />
|
||||||
></BaseSetting>
|
<XMarkIcon
|
||||||
|
v-if="enableEdit && (logo != '' || overwriteLogo)"
|
||||||
|
class="h-5 w-5 cursor-pointer"
|
||||||
|
@click="resetImage('logo')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<input class="hidden!" type="file" ref="logo" accept="image/*" @change="previewImage('logo')" />
|
||||||
|
</div>
|
||||||
|
</BaseSetting>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -37,12 +54,20 @@ import AppLogo from "@/components/AppLogo.vue";
|
||||||
import { useAbilityStore } from "@/stores/ability";
|
import { useAbilityStore } from "@/stores/ability";
|
||||||
import type { SettingString } from "@/types/settingTypes";
|
import type { SettingString } from "@/types/settingTypes";
|
||||||
import BaseSetting from "./BaseSetting.vue";
|
import BaseSetting from "./BaseSetting.vue";
|
||||||
|
import { XMarkIcon } from "@heroicons/vue/24/outline";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
watch: {
|
||||||
|
clubSettings() {
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
logo: "",
|
||||||
|
icon: "",
|
||||||
overwriteIcon: false as boolean,
|
overwriteIcon: false as boolean,
|
||||||
overwriteLogo: false as boolean,
|
overwriteLogo: false as boolean,
|
||||||
};
|
};
|
||||||
|
@ -54,8 +79,35 @@ export default defineComponent({
|
||||||
return this.readByTopic("club");
|
return this.readByTopic("club");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useSettingStore, ["updateSettings", "uploadImage"]),
|
...mapActions(useSettingStore, ["updateSettings", "uploadImage"]),
|
||||||
|
reset() {
|
||||||
|
this.icon = this.clubSettings["club.icon"];
|
||||||
|
this.overwriteIcon = false;
|
||||||
|
(this.$refs.icon_img as HTMLImageElement).style.display = "none";
|
||||||
|
(this.$refs.icon as HTMLInputElement).value = "";
|
||||||
|
|
||||||
|
this.logo = this.clubSettings["club.logo"];
|
||||||
|
this.overwriteLogo = false;
|
||||||
|
(this.$refs.logo_img as HTMLImageElement).style.display = "none";
|
||||||
|
(this.$refs.logo as HTMLInputElement).value = "";
|
||||||
|
},
|
||||||
|
resetImage(inputname: "icon" | "logo") {
|
||||||
|
if (inputname == "icon") {
|
||||||
|
this.icon = "";
|
||||||
|
this.overwriteIcon = false;
|
||||||
|
(this.$refs.icon_img as HTMLImageElement).style.display = "none";
|
||||||
|
(this.$refs.icon as HTMLInputElement).value = "";
|
||||||
|
} else {
|
||||||
|
this.logo = "";
|
||||||
|
this.overwriteLogo = false;
|
||||||
|
(this.$refs.logo_img as HTMLImageElement).style.display = "none";
|
||||||
|
(this.$refs.logo as HTMLInputElement).value = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
previewImage(inputname: "icon" | "logo") {
|
previewImage(inputname: "icon" | "logo") {
|
||||||
let input = this.$refs[inputname] as HTMLInputElement;
|
let input = this.$refs[inputname] as HTMLInputElement;
|
||||||
let previewElement = this.$refs[inputname + "_img"] as HTMLImageElement;
|
let previewElement = this.$refs[inputname + "_img"] as HTMLImageElement;
|
||||||
|
@ -68,6 +120,12 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.readAsDataURL(input.files[0]);
|
reader.readAsDataURL(input.files[0]);
|
||||||
|
|
||||||
|
if (inputname == "icon") {
|
||||||
|
this.overwriteIcon = true;
|
||||||
|
} else {
|
||||||
|
this.overwriteLogo = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
previewElement.src = "";
|
previewElement.src = "";
|
||||||
previewElement.style.display = "none";
|
previewElement.style.display = "none";
|
||||||
|
@ -76,11 +134,11 @@ export default defineComponent({
|
||||||
submit(e: any) {
|
submit(e: any) {
|
||||||
return this.uploadImage([
|
return this.uploadImage([
|
||||||
{
|
{
|
||||||
key: "club.icon" as SettingString,
|
key: "club.icon",
|
||||||
value: (this.$refs.icon as HTMLInputElement).files?.[0],
|
value: (this.$refs.icon as HTMLInputElement).files?.[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "club.logo" as SettingString,
|
key: "club.logo",
|
||||||
value: (this.$refs.logo as HTMLInputElement).files?.[0],
|
value: (this.$refs.logo as HTMLInputElement).files?.[0],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<label for="secure">Secure-Verbindung (setzen bei Port 465)</label>
|
<label for="secure">Secure-Verbindung (setzen bei Port 465)</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label for="password">Passwort (optional)</label>
|
<label for="password">Passwort (optional - leeres Feld setzt Passwort nicht zurück)</label>
|
||||||
<input id="password" type="password" :readonly="!enableEdit" autocomplete="new-password" />
|
<input id="password" type="password" :readonly="!enableEdit" autocomplete="new-password" />
|
||||||
</div>
|
</div>
|
||||||
</BaseSetting>
|
</BaseSetting>
|
||||||
|
|
|
@ -54,25 +54,42 @@ export const useSettingStore = defineStore("setting", {
|
||||||
key: K,
|
key: K,
|
||||||
value: SettingValueMapping[K]
|
value: SettingValueMapping[K]
|
||||||
): Promise<AxiosResponse<any, any>> {
|
): Promise<AxiosResponse<any, any>> {
|
||||||
return await http.put("/admin/setting", {
|
return await http
|
||||||
|
.put("/admin/setting", {
|
||||||
setting: key,
|
setting: key,
|
||||||
value: value,
|
value: value,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
this.settings[key] = value;
|
||||||
|
return res;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async updateSettings<K extends SettingString>(
|
async updateSettings<K extends SettingString>(
|
||||||
data: { key: K; value: SettingValueMapping[K] }[]
|
data: { key: K; value: SettingValueMapping[K] }[]
|
||||||
): Promise<AxiosResponse<any, any>> {
|
): Promise<AxiosResponse<any, any>> {
|
||||||
return await http.put("/admin/setting/multi", data);
|
return await http.put("/admin/setting/multi", data).then((res) => {
|
||||||
|
for (const element of data) {
|
||||||
|
this.settings[element.key] = element.value;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
async uploadImage(data: { key: SettingString; value?: File }[]): Promise<AxiosResponse<any, any>> {
|
async uploadImage(data: { key: "club.logo" | "club.icon"; value?: File }[]): Promise<AxiosResponse<any, any>> {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
for (let entry of data) {
|
for (let entry of data) {
|
||||||
if (entry.value) formData.append(entry.key, entry.value);
|
if (entry.value) formData.append(entry.key, entry.value);
|
||||||
}
|
}
|
||||||
return await http.put("/admin/setting/images", formData, {
|
return await http
|
||||||
|
.put("/admin/setting/images", formData, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
for (const element of data) {
|
||||||
|
this.settings[element.key] = element.value ? "configured" : "";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async resetSetting(key: SettingString): Promise<AxiosResponse<any, any>> {
|
async resetSetting(key: SettingString): Promise<AxiosResponse<any, any>> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue