Clean up multiworld preset handling
This commit is contained in:
@@ -1,16 +1,25 @@
|
|||||||
<script>
|
<script>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from "vue";
|
||||||
|
import { mapState, mapActions } from "pinia";
|
||||||
|
|
||||||
import localforage from "localforage";
|
import usePresetStore from "@/stores/preset.js";
|
||||||
import settingsData from "@/data/settings.yaml";
|
|
||||||
import generatorSettings from "@/data/generator-settings.yaml";
|
function settingsMatch(settings, preset) {
|
||||||
import presets from "@/data/presets.yaml";
|
for (const settingName of Object.keys(settings)) {
|
||||||
|
if (settingName == "player_name") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (preset[settingName] != settings[settingName]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selected: "custom",
|
selected: "custom",
|
||||||
localPresets: [],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: [
|
emits: [
|
||||||
@@ -19,79 +28,45 @@ export default defineComponent({
|
|||||||
],
|
],
|
||||||
props: {
|
props: {
|
||||||
generator: null,
|
generator: null,
|
||||||
},
|
prefix: null,
|
||||||
async mounted() {
|
|
||||||
this.localPresets = await localforage.getItem(`local_presets_${this.generator}`) ?? [];
|
|
||||||
for (const preset of this.localPresets) {
|
|
||||||
this.fillPreset(preset);
|
|
||||||
}
|
|
||||||
await this.updateLocalPresets();
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
settings() {
|
...mapState(usePresetStore, {
|
||||||
const settings = {};
|
allGlobalPresets: "globalPresets",
|
||||||
for (const name of Object.keys(generatorSettings[this.generator])) {
|
allLocalPresets: "localPresets",
|
||||||
var generatorValue = generatorSettings[this.generator][name]
|
}),
|
||||||
if (generatorValue == "all") {
|
globalPresets() {
|
||||||
settings[name] = settingsData[name];
|
return this.allGlobalPresets[this.generator];
|
||||||
} else if (Array.isArray(generatorValue)) {
|
|
||||||
const { values, ...newObj } = settingsData[this.name];
|
|
||||||
newObj.values = {};
|
|
||||||
for (const value of generatorValue) {
|
|
||||||
newObj.values[value] = values[value];
|
|
||||||
}
|
|
||||||
settings[name] = newObj;
|
|
||||||
} else {
|
|
||||||
settings[name] = generatorValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return settings;
|
|
||||||
},
|
},
|
||||||
presets() {
|
localPresets() {
|
||||||
const filledPresets = {};
|
return this.allLocalPresets[this.generator];
|
||||||
if (presets[this.generator]) {
|
|
||||||
for (const presetName of Object.keys(presets[this.generator])) {
|
|
||||||
const preset = JSON.parse(JSON.stringify(presets[this.generator][presetName]));
|
|
||||||
this.fillPreset(preset);
|
|
||||||
filledPresets[presetName] = preset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filledPresets;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions(usePresetStore, ["deleteLocalPreset", "saveLocalPreset"]),
|
||||||
change() {
|
change() {
|
||||||
if (this.selected && this.selected != "custom") {
|
if (this.selected && this.selected != "custom") {
|
||||||
if (this.selected.startsWith("local_")) {
|
if (this.selected.startsWith("local_")) {
|
||||||
this.$emit("selected", this.localPresets[this.selected.substring(6)]);
|
this.$emit("selected", this.localPresets[this.selected.substring(6)]);
|
||||||
} else {
|
} else {
|
||||||
this.$emit("selected", this.presets[this.selected]);
|
this.$emit("selected", this.globalPresets[this.selected]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
settingsMatch(newSettings, preset) {
|
|
||||||
for (const settingName of Object.keys(newSettings)) {
|
|
||||||
if (settingName == "player_name") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preset[settingName] != newSettings[settingName]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
settingChanged(newSettings) {
|
settingChanged(newSettings) {
|
||||||
for (const presetName of Object.keys(this.presets)) {
|
for (const presetName of Object.keys(this.globalPresets)) {
|
||||||
const preset = this.presets[presetName];
|
const preset = this.globalPresets[presetName];
|
||||||
if (this.settingsMatch(newSettings, preset)) {
|
if (settingsMatch(newSettings, preset)) {
|
||||||
this.selected = presetName;
|
this.selected = presetName;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const [idx, preset] of this.localPresets.entries()) {
|
if (this.localPresets) {
|
||||||
if (this.settingsMatch(newSettings, preset)) {
|
for (const [idx, preset] of this.localPresets.entries()) {
|
||||||
this.selected = `local_${idx}`;
|
if (settingsMatch(newSettings, preset)) {
|
||||||
return;
|
this.selected = `local_${idx}`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.selected = "custom";
|
this.selected = "custom";
|
||||||
@@ -101,31 +76,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
async deleteClicked() {
|
async deleteClicked() {
|
||||||
const idx = this.selected.substring(6);
|
const idx = this.selected.substring(6);
|
||||||
this.localPresets.splice(idx, 1);
|
|
||||||
this.selected = "custom";
|
this.selected = "custom";
|
||||||
await this.updateLocalPresets();
|
await this.deleteLocalPreset(this.generator, idk);
|
||||||
},
|
},
|
||||||
async savePreset(idx, settings) {
|
async savePreset(idx, preset) {
|
||||||
if (idx == null) {
|
idx = await this.saveLocalPreset(this.generator, idx, preset);
|
||||||
idx = this.localPresets.length;
|
|
||||||
this.localPresets.push(settings);
|
|
||||||
} else {
|
|
||||||
this.localPresets[idx] = settings;
|
|
||||||
}
|
|
||||||
this.selected = `local_${idx}`;
|
this.selected = `local_${idx}`;
|
||||||
await this.updateLocalPresets();
|
|
||||||
},
|
|
||||||
async updateLocalPresets() {
|
|
||||||
const copy = JSON.parse(JSON.stringify(this.localPresets));
|
|
||||||
await localforage.setItem(`local_presets_${this.generator}`, copy);
|
|
||||||
},
|
|
||||||
fillPreset(preset) {
|
|
||||||
for (const settingName of Object.keys(this.settings)) {
|
|
||||||
if (preset[settingName] == undefined) {
|
|
||||||
preset[settingName] = this.settings[settingName].default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return preset;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -139,13 +95,13 @@ export default defineComponent({
|
|||||||
<select v-model="selected" class="form-select" id="presetSelector" @change="change">
|
<select v-model="selected" class="form-select" id="presetSelector" @change="change">
|
||||||
<option disabled="true" value="custom">Custom</option>
|
<option disabled="true" value="custom">Custom</option>
|
||||||
<optgroup label="Global Presets">
|
<optgroup label="Global Presets">
|
||||||
<template v-for="name of Object.keys(presets)">
|
<template v-for="name of Object.keys(globalPresets)">
|
||||||
<option :value="name">
|
<option :value="name">
|
||||||
{{ presets[name].display }}
|
{{ globalPresets[name].display }}
|
||||||
</option>
|
</option>
|
||||||
</template>
|
</template>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup v-if="localPresets.length" label="Local Presets">
|
<optgroup v-if="localPresets && localPresets.length" label="Local Presets">
|
||||||
<template v-for="(preset, idx) of localPresets">
|
<template v-for="(preset, idx) of localPresets">
|
||||||
<option :value="`local_${idx}`">
|
<option :value="`local_${idx}`">
|
||||||
{{ preset.display }}
|
{{ preset.display }}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import { mapActions } from "pinia";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Modal } from "bootstrap";
|
import { Modal } from "bootstrap";
|
||||||
@@ -10,6 +11,8 @@ import AccordionItem from "@/components/AccordionItem.vue";
|
|||||||
import PresetPicker from "@/components/PresetPicker.vue";
|
import PresetPicker from "@/components/PresetPicker.vue";
|
||||||
import SettingPicker from "@/components/SettingPicker.vue";
|
import SettingPicker from "@/components/SettingPicker.vue";
|
||||||
|
|
||||||
|
import usePresetStore from "@/stores/preset.js";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
AccordionItem,
|
AccordionItem,
|
||||||
@@ -38,8 +41,10 @@ export default defineComponent({
|
|||||||
return generatorSettings[this.generator];
|
return generatorSettings[this.generator];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
async mounted() {
|
||||||
this.modal = new Modal(document.getElementById("savePresetModal"), {});
|
this.modal = new Modal(this.$refs.savePresetModal, {});
|
||||||
|
await this.fetchLocalPresets();
|
||||||
|
this.$refs.preset.settingChanged(this.set);
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
set: {
|
set: {
|
||||||
@@ -51,6 +56,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions(usePresetStore, ["fetchLocalPresets"]),
|
||||||
async generate(race) {
|
async generate(race) {
|
||||||
const settings = {
|
const settings = {
|
||||||
randomizer: this.generator,
|
randomizer: this.generator,
|
||||||
@@ -94,7 +100,7 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="modal" tabindex="-1" id="savePresetModal">
|
<div class="modal" tabindex="-1" ref="savePresetModal">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@@ -137,7 +143,7 @@ export default defineComponent({
|
|||||||
<div id="settings" class="accordion accordion-flush">
|
<div id="settings" class="accordion accordion-flush">
|
||||||
<AccordionItem>
|
<AccordionItem>
|
||||||
<PresetPicker ref="preset" :generator="generator" @selected="presetSelected"
|
<PresetPicker ref="preset" :generator="generator" @selected="presetSelected"
|
||||||
@save="savePreset" />
|
@save="savePreset" :prefix="prefix" />
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
<AccordionItem :expanded="true">
|
<AccordionItem :expanded="true">
|
||||||
<template #header>
|
<template #header>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
|
import { createPinia } from "pinia";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
|
|
||||||
@@ -14,8 +15,10 @@ import "./assets/main.css";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
axios.defaults.baseURL = import.meta.env.VITE_BACKEND_URL;
|
axios.defaults.baseURL = import.meta.env.VITE_BACKEND_URL;
|
||||||
|
|
||||||
const app = createApp(App)
|
const pinia = createPinia();
|
||||||
|
const app = createApp(App);
|
||||||
|
|
||||||
app.use(router)
|
app.use(router);
|
||||||
|
app.use(pinia);
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app');
|
||||||
|
|||||||
104
src/stores/preset.js
Normal file
104
src/stores/preset.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
import localforage from "localforage";
|
||||||
|
import settingsData from "@/data/settings.yaml";
|
||||||
|
import generatorSettings from "@/data/generator-settings.yaml";
|
||||||
|
import presets from "@/data/presets.yaml";
|
||||||
|
|
||||||
|
function fillPreset(preset, settings) {
|
||||||
|
for (const settingName of Object.keys(settings)) {
|
||||||
|
if (preset[settingName] == undefined) {
|
||||||
|
preset[settingName] = settings[settingName].default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return preset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineStore("preset", {
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
localPresets: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
settings() {
|
||||||
|
const settings = {};
|
||||||
|
for (const generator of Object.keys(generatorSettings)) {
|
||||||
|
settings[generator] = {};
|
||||||
|
|
||||||
|
for (const name of Object.keys(generatorSettings[generator])) {
|
||||||
|
var generatorValue = generatorSettings[generator][name];
|
||||||
|
if (generatorValue == "all") {
|
||||||
|
settings[generator][name] = settingsData[name];
|
||||||
|
} else if (Array.isArray(generatorValue)) {
|
||||||
|
const { values, ...newObj } = settingsData[name];
|
||||||
|
newObj.values = {};
|
||||||
|
for (const value of generatorValue) {
|
||||||
|
newObj.values[value] = values[value];
|
||||||
|
}
|
||||||
|
settings[generator][name] = newObj;
|
||||||
|
} else {
|
||||||
|
settings[generator][name] = generatorValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
},
|
||||||
|
globalPresets() {
|
||||||
|
const filledPresets = {};
|
||||||
|
for (const generator of Object.keys(generatorSettings)) {
|
||||||
|
filledPresets[generator] = {};
|
||||||
|
if (presets[generator]) {
|
||||||
|
for (const presetName of Object.keys(presets[generator])) {
|
||||||
|
const preset = { ...presets[generator][presetName] };
|
||||||
|
fillPreset(preset, this.settings[generator]);
|
||||||
|
filledPresets[generator][presetName] = preset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filledPresets;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
async fetchLocalPresets() {
|
||||||
|
for (const generator of Object.keys(generatorSettings)) {
|
||||||
|
if (this.localPresets[generator]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.cacheLocalPresets(generator);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async cacheLocalPresets(generator) {
|
||||||
|
var generatorPresets = await localforage.getItem(`local_presets_${generator}`);
|
||||||
|
|
||||||
|
if (!Array.isArray(generatorPresets)) {
|
||||||
|
generatorPresets = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const preset of generatorPresets) {
|
||||||
|
fillPreset(preset, this.settings[generator]);
|
||||||
|
}
|
||||||
|
this.localPresets[generator] = generatorPresets;
|
||||||
|
await this.saveLocalPresets(generator);
|
||||||
|
},
|
||||||
|
async deleteLocalPreset(generator, index) {
|
||||||
|
this.localPresets[generator].splice(index, 1);
|
||||||
|
await this.saveLocalPresets(generator);
|
||||||
|
},
|
||||||
|
async saveLocalPreset(generator, index, preset) {
|
||||||
|
if (index == null) {
|
||||||
|
index = this.localPresets[generator].length;
|
||||||
|
this.localPresets[generator].push(preset);
|
||||||
|
} else {
|
||||||
|
this.localPresets[generator][index] = preset;
|
||||||
|
}
|
||||||
|
await this.saveLocalPresets(generator);
|
||||||
|
return index;
|
||||||
|
},
|
||||||
|
async saveLocalPresets(generator) {
|
||||||
|
const copy = JSON.parse(JSON.stringify(this.localPresets[generator]));
|
||||||
|
await localforage.setItem(`local_presets_${generator}`, copy);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -3,7 +3,7 @@ import { defineComponent } from "vue";
|
|||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import localforage from "localforage";
|
import localforage from "localforage";
|
||||||
import { Modal } from "bootstrap";
|
import { Tab } from "bootstrap";
|
||||||
|
|
||||||
import SettingsPage from "@/components/SettingsPage.vue";
|
import SettingsPage from "@/components/SettingsPage.vue";
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
for (var i = 0; i < this.worldCount; i++) {
|
for (var i = 0; i < this.worldCount; i++) {
|
||||||
this.worlds[i].player_name = await localforage.getItem(`${this.prefix}world_${i + 1}_setting_player_name`);
|
this.worlds[i].player_name = await localforage.getItem(`${this.prefix}world_${i + 1}_setting_player_name`);
|
||||||
|
new Tab(this.$refs.tabs[i]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -36,12 +37,17 @@ export default defineComponent({
|
|||||||
this.worlds.push({player_name: newname});
|
this.worlds.push({player_name: newname});
|
||||||
this.worldCount++;
|
this.worldCount++;
|
||||||
|
|
||||||
|
await this.$nextTick();
|
||||||
|
Tab.getOrCreateInstance(this.$refs.tabs[this.worldCount - 1]).show();
|
||||||
|
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise(r => setTimeout(r, 100));
|
||||||
this.worlds[this.worldCount - 1].player_name = newname;
|
this.worlds[this.worldCount - 1].player_name = newname;
|
||||||
},
|
},
|
||||||
async removeWorld() {
|
async removeWorld() {
|
||||||
this.worldCount--;
|
this.worldCount--;
|
||||||
this.worlds.pop();
|
this.worlds.pop();
|
||||||
|
await this.$nextTick();
|
||||||
|
Tab.getOrCreateInstance(this.$refs.tabs[this.worldCount - 1]).show();
|
||||||
},
|
},
|
||||||
async playerNameUpdated(num) {
|
async playerNameUpdated(num) {
|
||||||
await localforage.setItem(`${this.prefix}world_${num + 1}_setting_player_name`, this.worlds[num].player_name);
|
await localforage.setItem(`${this.prefix}world_${num + 1}_setting_player_name`, this.worlds[num].player_name);
|
||||||
@@ -83,17 +89,18 @@ export default defineComponent({
|
|||||||
<ul class="nav nav-tabs ps-3 pt-3 pe-3">
|
<ul class="nav nav-tabs ps-3 pt-3 pe-3">
|
||||||
<li v-for="(n, idx) in worldCount" class="nav-item" role="presentation">
|
<li v-for="(n, idx) in worldCount" class="nav-item" role="presentation">
|
||||||
<button class="nav-link" :class="{active: idx == 0}" data-bs-toggle="tab"
|
<button class="nav-link" :class="{active: idx == 0}" data-bs-toggle="tab"
|
||||||
:data-bs-target="`#world_page_${n}`" type="button" role="tab">
|
:data-bs-target="`#world_page_${n}`" type="button" role="tab" ref="tabs">
|
||||||
<template v-if="worlds[idx] && worlds[idx].player_name && worlds[idx].player_name.length">
|
<template v-if="worlds[idx] && worlds[idx].player_name && worlds[idx].player_name.length">
|
||||||
{{ worlds[idx].player_name }}
|
{{ worlds[idx].player_name }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ n }}
|
{{ n }}
|
||||||
</template>
|
</template>
|
||||||
<button v-if="n == worldCount && n > 2" @click="removeWorld"
|
<div v-if="n == worldCount && n > 2" class="delete-player-button">
|
||||||
class="badge btn rounded-pill text-bg-danger">
|
<button @click="removeWorld" class="badge btn rounded-pill text-bg-danger">
|
||||||
<i class="bi bi-trash"></i>
|
<i class="bi bi-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<button class="nav-link" type="button" role="tab" @click="addWorld">
|
<button class="nav-link" type="button" role="tab" @click="addWorld">
|
||||||
@@ -132,3 +139,10 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.delete-player-button {
|
||||||
|
display: inline;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user