🔨 Send settings
This commit is contained in:
parent
f8d174224c
commit
f6baab77ed
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -8,7 +8,6 @@
|
||||
"typescript.inlayHints.propertyDeclarationTypes.enabled": true,
|
||||
"typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true,
|
||||
"typescript.inlayHints.parameterNames.enabled": "literals",
|
||||
"typescript.inlayHints.parameterTypes.enabled": true,
|
||||
"javascript.inlayHints.enumMemberValues.enabled": true,
|
||||
"javascript.inlayHints.propertyDeclarationTypes.enabled": true,
|
||||
"javascript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true,
|
||||
|
@ -3,12 +3,14 @@
|
||||
v-for="(data, index) of snacks"
|
||||
:key="data.uuid"
|
||||
v-model="data.snack"
|
||||
top="true"
|
||||
left="true"
|
||||
location="top start"
|
||||
:style="{ 'margin-top': calcMargin(index) }"
|
||||
:color="data.color"
|
||||
>
|
||||
<div>{{ data.text }}</div>
|
||||
<div>
|
||||
<v-icon class="mr-2">{{ data.icon }}</v-icon>
|
||||
{{ data.text }}
|
||||
</div>
|
||||
<template v-slot:actions>
|
||||
<v-btn
|
||||
variant="text"
|
||||
@ -30,7 +32,7 @@ function calcMargin(i: number) {
|
||||
}
|
||||
|
||||
let snacks = ref<
|
||||
{ text: string; color: string; snack: boolean; uuid: string }[]
|
||||
{ text: string; color: string; snack: boolean; uuid: string; icon: string }[]
|
||||
>([]);
|
||||
|
||||
eventQueuStore.$subscribe((mutation, state) => {
|
||||
@ -42,6 +44,7 @@ eventQueuStore.$subscribe((mutation, state) => {
|
||||
text: event.text,
|
||||
color: event.type,
|
||||
uuid: event.uuid,
|
||||
icon: getIcon(event.type),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -66,9 +69,23 @@ if (eventQueuStore.size != 0) {
|
||||
text: event.text,
|
||||
color: event.type,
|
||||
uuid: event.uuid,
|
||||
icon: getIcon(event.type),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getIcon(type: string) {
|
||||
switch (type) {
|
||||
case "success":
|
||||
return "mdi-check";
|
||||
case "warning":
|
||||
return "mdi-alert";
|
||||
case "error":
|
||||
return "mdi-alert-decagram";
|
||||
default:
|
||||
return "mdi-alert-circle";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -12,13 +12,7 @@
|
||||
></bool-field-component>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<template
|
||||
v-if="
|
||||
!!props.descriptor.mainField
|
||||
? settingStoreRef.values.value[props.descriptor.mainField.id]
|
||||
: true
|
||||
"
|
||||
>
|
||||
<template v-if="isOn">
|
||||
<v-row v-for="item of props.descriptor.fields" :key="item.id">
|
||||
<v-col>
|
||||
<bool-field-component
|
||||
@ -26,10 +20,12 @@
|
||||
:fieldDescription="item"
|
||||
></bool-field-component>
|
||||
<select-field-component
|
||||
:required="isOn"
|
||||
:fieldDescription="item"
|
||||
v-if="isSelect(item.type)"
|
||||
></select-field-component>
|
||||
<text-field-component
|
||||
:required="isOn"
|
||||
:fieldDescription="item"
|
||||
v-if="item.type == 'STRING'"
|
||||
></text-field-component>
|
||||
@ -45,6 +41,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { SettingDescrition } from "@/data/Setting/SettingDescription";
|
||||
import { useSettingStore } from "@/stores/setting";
|
||||
import { computed } from "@vue/reactivity";
|
||||
import { storeToRefs } from "pinia";
|
||||
import boolFieldComponent from "./fields/BoolFieldComponent.vue";
|
||||
import SelectFieldComponent from "./fields/SelectFieldComponent.vue";
|
||||
@ -65,6 +62,12 @@ function isSelect(type: string) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const isOn = computed(() => {
|
||||
return props.descriptor.mainField
|
||||
? !!settingStoreRef.values.value[props.descriptor.mainField.id]
|
||||
: true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -14,14 +14,30 @@
|
||||
width="15"
|
||||
></v-progress-circular>
|
||||
</v-overlay>
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="item of settingsDescription"
|
||||
:key="item.name"
|
||||
md="6"
|
||||
cols="12"
|
||||
>
|
||||
<setting-group-component :descriptor="item"></setting-group-component>
|
||||
<v-form ref="form">
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="item of settingsDescription"
|
||||
:key="item.name"
|
||||
md="6"
|
||||
cols="12"
|
||||
>
|
||||
<setting-group-component :descriptor="item"></setting-group-component>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-form>
|
||||
<v-row justify="center">
|
||||
<v-col cols="1">
|
||||
<v-btn
|
||||
v-on:click="send"
|
||||
color="success"
|
||||
prepend-icon="mdi-content-save"
|
||||
block
|
||||
:disabled="preventSave"
|
||||
v-if="settingsDescription.length > 0"
|
||||
>
|
||||
Save
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
@ -39,10 +55,12 @@ import {
|
||||
import {
|
||||
getSettingDescrition,
|
||||
getSettingValues,
|
||||
sendSetting,
|
||||
} from "@/services/settingsService";
|
||||
import { useEventQueuStore } from "@/stores/eventQueu";
|
||||
import { useSettingStore } from "@/stores/setting";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import SettingGroupComponent from "./SettingGroupComponent.vue";
|
||||
|
||||
const props = defineProps<{ guild: Guild }>();
|
||||
@ -50,8 +68,10 @@ const props = defineProps<{ guild: Guild }>();
|
||||
const settingStore = useSettingStore();
|
||||
const { values, loading, text_channels, voice_channels, roles } =
|
||||
storeToRefs(settingStore);
|
||||
|
||||
loading.value = true;
|
||||
values.value = {};
|
||||
|
||||
const settingsDescription = ref([] as SettingDescrition[]);
|
||||
|
||||
getSettingDescrition().then((value) => {
|
||||
@ -86,11 +106,59 @@ function loadSettings() {
|
||||
for (let item of value) {
|
||||
temp[item.id] = item.value;
|
||||
}
|
||||
|
||||
values.value = temp;
|
||||
settingStore.savedValues = JSON.parse(JSON.stringify(temp));
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
const form = ref(null);
|
||||
const preventSave = ref(false);
|
||||
|
||||
watch(
|
||||
values,
|
||||
() => {
|
||||
const theForm = form.value as any;
|
||||
theForm?.validate().then((value: any) => {
|
||||
preventSave.value =
|
||||
!value.valid ||
|
||||
JSON.stringify(values.value) ==
|
||||
JSON.stringify(settingStore.savedValues);
|
||||
});
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
function send() {
|
||||
const theForm = form.value as any;
|
||||
theForm?.validate().then((value: any) => {
|
||||
if (value.valid) {
|
||||
loading.value = true;
|
||||
sendSetting(
|
||||
props.guild.id,
|
||||
settingStore.values,
|
||||
settingsDescription.value
|
||||
)
|
||||
.then((saved) => {
|
||||
let temp = {} as SettingValue;
|
||||
for (let item of saved) {
|
||||
temp[item.id] = item.value;
|
||||
}
|
||||
values.value = temp;
|
||||
settingStore.savedValues = JSON.parse(JSON.stringify(temp));
|
||||
loading.value = false;
|
||||
const eventQueuStore = useEventQueuStore();
|
||||
eventQueuStore.push({
|
||||
uuid: undefined,
|
||||
type: "success",
|
||||
text: "Settings saved",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -14,6 +14,7 @@
|
||||
:items="items?.value"
|
||||
variant="outlined"
|
||||
v-model="values[fieldDescription.id]"
|
||||
:rules="[required]"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@ -24,10 +25,19 @@ import type { FieldDescriptor } from "@/data/Setting/SettingDescription";
|
||||
import { useSettingStore } from "@/stores/setting";
|
||||
import { computed } from "@vue/reactivity";
|
||||
import { storeToRefs } from "pinia";
|
||||
const props = defineProps<{ fieldDescription: FieldDescriptor }>();
|
||||
const props = defineProps<{
|
||||
fieldDescription: FieldDescriptor;
|
||||
required: boolean;
|
||||
}>();
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
|
||||
function required(value: string) {
|
||||
return props.required
|
||||
? !!values.value[props.fieldDescription.id] || "Required"
|
||||
: true;
|
||||
}
|
||||
|
||||
const { loading, roles, text_channels, voice_channels, values } =
|
||||
storeToRefs(settingStore);
|
||||
const loadingComp = computed(() => {
|
||||
|
@ -11,6 +11,7 @@
|
||||
:loading="loading"
|
||||
variant="outlined"
|
||||
v-model="settingStore.values[fieldDescription.id]"
|
||||
:rules="[required]"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@ -20,11 +21,18 @@
|
||||
import type { FieldDescriptor } from "@/data/Setting/SettingDescription";
|
||||
import { useSettingStore } from "@/stores/setting";
|
||||
import { storeToRefs } from "pinia";
|
||||
defineProps<{ fieldDescription: FieldDescriptor }>();
|
||||
const props = defineProps<{
|
||||
fieldDescription: FieldDescriptor;
|
||||
required: boolean;
|
||||
}>();
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
|
||||
const { loading } = storeToRefs(settingStore);
|
||||
|
||||
function required(value: string) {
|
||||
return props.required ? !!value || "Required" : true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -35,13 +35,6 @@ async function login(code: string): Promise<boolean> {
|
||||
console.log("Loggin fail !");
|
||||
console.log(reason);
|
||||
logout(false, true);
|
||||
|
||||
const eventQueuStore = useEventQueuStore();
|
||||
eventQueuStore.push({
|
||||
uuid: undefined,
|
||||
type: "error",
|
||||
text: "Login fail, Please try aguain.",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import type { RawSettingValue } from "@/data/Setting/RawSettingValue";
|
||||
import type { SettingDescrition } from "@/data/Setting/SettingDescription";
|
||||
import type { SettingValue } from "@/data/Setting/SettingValue";
|
||||
import { useEventQueuStore } from "@/stores/eventQueu";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import axios from "axios";
|
||||
@ -46,4 +47,52 @@ function getSettingValues(guildId: string): Promise<RawSettingValue[]> {
|
||||
});
|
||||
}
|
||||
|
||||
export { getSettingDescrition, getSettingValues };
|
||||
function sendSetting(
|
||||
guildId: string,
|
||||
data: SettingValue,
|
||||
description: SettingDescrition[]
|
||||
): Promise<RawSettingValue[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const userStore = useUserStore();
|
||||
|
||||
const converted = buildValuePayload(data, description);
|
||||
axios
|
||||
.post<RawSettingValue[]>(`/setting/${guildId}/values`, converted, {
|
||||
headers: {
|
||||
authorization: `Bearer ${userStore.token}`,
|
||||
},
|
||||
})
|
||||
.then((value) => {
|
||||
resolve(value.data);
|
||||
})
|
||||
.catch((reason) => {
|
||||
console.error(`Fail to save settings !`);
|
||||
console.log(reason);
|
||||
const eventQueuStore = useEventQueuStore();
|
||||
eventQueuStore.push({
|
||||
uuid: undefined,
|
||||
type: "error",
|
||||
text: "Fail to save settings !",
|
||||
});
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function buildValuePayload(
|
||||
data: SettingValue,
|
||||
description: SettingDescrition[]
|
||||
): RawSettingValue[] {
|
||||
const temp = [] as RawSettingValue[];
|
||||
for (const item of description) {
|
||||
if (item.mainField) {
|
||||
temp.push({ id: item.mainField.id, value: data[item.mainField.id] });
|
||||
}
|
||||
for (const field of item.fields) {
|
||||
temp.push({ id: field.id, value: data[field.id] });
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
export { getSettingDescrition, getSettingValues, sendSetting };
|
||||
|
@ -4,6 +4,7 @@ import { defineStore } from "pinia";
|
||||
export const useSettingStore = defineStore({
|
||||
id: "setting",
|
||||
state: () => ({
|
||||
savedValues: {} as SettingValue,
|
||||
values: {} as SettingValue,
|
||||
text_channels: [] as SettingValue[],
|
||||
voice_channels: [] as SettingValue[],
|
||||
|
@ -13,12 +13,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { login } from "@/services/authService";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
if (route.query.code) {
|
||||
login(route.query.code as string).then(() => {
|
||||
router.push("/");
|
||||
|
Loading…
Reference in New Issue
Block a user