diff options
Diffstat (limited to 'components/loader')
| -rw-r--r-- | components/loader/LoaderFileSystemButton.vue | 40 | ||||
| -rw-r--r-- | components/loader/LoaderFileSystemModal.vue | 81 | ||||
| -rw-r--r-- | components/loader/LoaderTestDataButton.vue | 17 | ||||
| -rw-r--r-- | components/loader/LoaderTestDataModal.vue | 52 |
4 files changed, 190 insertions, 0 deletions
diff --git a/components/loader/LoaderFileSystemButton.vue b/components/loader/LoaderFileSystemButton.vue new file mode 100644 index 0000000..0d02477 --- /dev/null +++ b/components/loader/LoaderFileSystemButton.vue @@ -0,0 +1,40 @@ +<script setup lang="ts"> +import type LoaderFileSystemModal from './LoaderFileSystemModal.vue'; + +const loaderStore = useLoaderStore(); + +const { canUseFsApi } = getBrowserCapabilities(); + +const fileSystemModal = ref<InstanceType<typeof LoaderFileSystemModal> | null>(null); + +const openFileSystemPrompt = async () => { + fileSystemModal.value?.open(); + loaderStore.setFileSystemLoaderStatus('pending'); + const dirHandle = await openFileSystem(); + if (!dirHandle) { + loaderStore.setFileSystemLoaderStatus('inactive'); + return; + } + loaderStore.setPath(dirHandle.name); + loaderStore.setFileSystemLoaderStatus('loaded'); + try { + const { categories, quests, items } = await enumerateQuestDirectory(dirHandle); + loaderStore.setCategories(categories); + loaderStore.setQuests(quests); + loaderStore.setItems(items); + loaderStore.setFileSystemLoaderStatus('valid'); + } catch (e) { + console.error(e); + loaderStore.setFileSystemLoaderStatus('invalid'); + } +} +</script> + +<template> + <ClientOnly> + <Button type="solid" :icon="['fas', 'folder-open']" label="Import from Filesystem" @click="openFileSystemPrompt" + :disabled="!canUseFsApi" /> + + <LoaderFileSystemModal ref="fileSystemModal" /> + </ClientOnly> +</template>
\ No newline at end of file diff --git a/components/loader/LoaderFileSystemModal.vue b/components/loader/LoaderFileSystemModal.vue new file mode 100644 index 0000000..27f4e12 --- /dev/null +++ b/components/loader/LoaderFileSystemModal.vue @@ -0,0 +1,81 @@ +<script setup lang="ts"> +const loader = useLoaderStore(); +const session = useSessionStore(); + +const showModal = ref(false); + +const open = () => { + showModal.value = true; +} + +const confirm = () => { + const categories = loader.getCategories(); + const quests = loader.getQuests(); + const items = loader.getItems(); + + session.setCategories(categories); + session.setQuests(quests); + session.setItems(items); + + showModal.value = false; +} + +const status = computed(() => loader.getFileSystemLoaderStatus()); +const questsCount = computed(() => loader.getQuests().length); +const categoriesCount = computed(() => loader.getCategories().length); +const itemsCount = computed(() => loader.getItems().length); +const path = computed(() => loader.getPath()); + +defineExpose({ + open +}) +</script> + +<template> + <Modal v-model="showModal"> + <template v-slot:header> + <h2>Import from Filesystem</h2> + </template> + + <div v-if="status === 'pending'"> + <p>Select the Quests plugin data directory.</p> + <p>Waiting for selection...</p> + </div> + + <div v-if="status === 'inactive'"> + <p>The request was aborted.</p> + </div> + + <div v-if="status === 'loaded'"> + <p>Parsing files in directory <code>{{ path }}</code>...</p> + </div> + + <div v-if="status === 'invalid'"> + <p>You have selected an invalid directory.</p> + </div> + + <div v-if="status === 'valid'"> + <p>Successfully parsed directory <code>{{ path }}</code>.</p> + <ul> + <li>{{ categoriesCount }} categories loaded</li> + <li>{{ questsCount }} quests loaded</li> + <li>{{ itemsCount }} items loaded</li> + </ul> + <p>You are about to replace your current workspace. Are you sure you want to continue?</p> + </div> + + <div id="controls" class="control-group"> + <Button :icon="['fas', 'xmark']" :label="'Cancel'" @click="showModal = false"></Button> + <Button v-if="status === 'valid'" type="solid" :icon="['fas', 'check']" :label="'Confirm'" + @click="confirm"></Button> + </div> + </Modal> +</template> + +<style scoped> +#controls { + display: flex; + justify-content: flex-end; + margin-top: 1rem; +} +</style>
\ No newline at end of file diff --git a/components/loader/LoaderTestDataButton.vue b/components/loader/LoaderTestDataButton.vue new file mode 100644 index 0000000..b01b0ee --- /dev/null +++ b/components/loader/LoaderTestDataButton.vue @@ -0,0 +1,17 @@ +<script setup lang="ts"> +import type LoaderTestDataModal from './LoaderTestDataModal.vue'; + +const testDataModal = ref<InstanceType<typeof LoaderTestDataModal> | null>(null); + +const openTestDataModal = async () => { + testDataModal.value?.open(); +} +</script> + +<template> + <ClientOnly> + <Button :icon="['fas', 'flask-vial']" label="Demo" @click="openTestDataModal" /> + + <LoaderTestDataModal ref="testDataModal" /> + </ClientOnly> +</template>
\ No newline at end of file diff --git a/components/loader/LoaderTestDataModal.vue b/components/loader/LoaderTestDataModal.vue new file mode 100644 index 0000000..36d2d6d --- /dev/null +++ b/components/loader/LoaderTestDataModal.vue @@ -0,0 +1,52 @@ +<script setup lang="ts"> +import { loadCategoriesFromJson, loadItemsFromJson, loadQuestsFromJson } from '~/lib/questsLoader'; +import testData from '@/data/testData.json'; + +const session = useSessionStore(); + +const showModal = ref(false); + +const open = () => { + showModal.value = true; +} + +const confirm = () => { + const quests = loadQuestsFromJson(testData.quests); + const categories = loadCategoriesFromJson(testData.categories); + const items = loadItemsFromJson(testData.items); + + session.setQuests(quests); + session.setCategories(categories); + session.setItems(items); + + showModal.value = false; +} + +defineExpose({ + open +}) +</script> + +<template> + <Modal v-model="showModal"> + <template v-slot:header> + <h2>Import test data</h2> + </template> + + <p>You can view a demo of the Quests editor by loading test data. This will replace your current workspace. + Do you want to continue?</p> + + <div id="controls" class="control-group"> + <Button :icon="['fas', 'xmark']" :label="'Cancel'" @click="showModal = false"></Button> + <Button type="solid" :icon="['fas', 'check']" :label="'Confirm'" @click="confirm"></Button> + </div> + </Modal> +</template> + +<style scoped> +#controls { + display: flex; + justify-content: flex-end; + margin-top: 1rem; +} +</style>
\ No newline at end of file |
