diff options
Diffstat (limited to 'components/editor')
18 files changed, 350 insertions, 152 deletions
diff --git a/components/editor/EditorOptionsPanel.vue b/components/editor/EditorOptionsPanel.vue index 7cf8982..05d1f34 100644 --- a/components/editor/EditorOptionsPanel.vue +++ b/components/editor/EditorOptionsPanel.vue @@ -1,5 +1,4 @@ -<script setup lang="ts"> -</script> +<script setup lang="ts"></script> <template> <div id="options-panel"> @@ -16,4 +15,4 @@ padding: 1rem; height: 100%; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/EditorSidebar.vue b/components/editor/EditorSidebar.vue index 7ac4996..9d5818d 100644 --- a/components/editor/EditorSidebar.vue +++ b/components/editor/EditorSidebar.vue @@ -10,19 +10,27 @@ const currentType = ref('quests' as 'quests' | 'items'); const setSelectedType = (type: 'quests' | 'items') => { currentType.value = type; -} +}; </script> <template> <div id="sidebar-container"> <div id="selector"> - <span class="option" @click="setSelectedType('quests')" :class="{ selected: currentType === 'quests' }"> + <span + class="option" + @click="setSelectedType('quests')" + :class="{ selected: currentType === 'quests' }" + > <span> <font-awesome-icon :icon="['far', 'compass']" /> Quests </span> </span> - <span class="option" @click="setSelectedType('items')" :class="{ selected: currentType === 'items' }"> + <span + class="option" + @click="setSelectedType('items')" + :class="{ selected: currentType === 'items' }" + > <span> <font-awesome-icon :icon="['fas', 'cubes']" /> Items @@ -30,13 +38,22 @@ const setSelectedType = (type: 'quests' | 'items') => { </span> </div> <div id="quests" v-if="currentType === 'quests'"> - <EditorSidebarCategory v-for="category in session.categories" :key="category.id" :category="category" /> + <EditorSidebarCategory + v-for="category in session.categories" + :key="category.id" + :category="category" + /> <EditorSidebarQuest - v-for="quest in session.quests.filter((q) => (!session.categories.some((c) => c.id === q.options.category)))" - :key="quest.id" :quest="quest" /> - <p id="count">{{ session.quests.length }} quest{{ session.quests.length === 1 ? '' : 's' }}, {{ - session.categories.length }} - categor{{ session.categories.length === 1 ? 'y' : 'ies' }}</p> + v-for="quest in session.quests.filter( + (q) => !session.categories.some((c) => c.id === q.options.category) + )" + :key="quest.id" + :quest="quest" + /> + <p id="count"> + {{ session.quests.length }} quest{{ session.quests.length === 1 ? '' : 's' }}, + {{ session.categories.length }} categor{{ session.categories.length === 1 ? 'y' : 'ies' }} + </p> </div> <div id="items" v-if="currentType === 'items'"> <EditorSidebarItem v-for="item in session.items" :key="item.id" :item="item" /> @@ -88,7 +105,7 @@ const setSelectedType = (type: 'quests' | 'items') => { transition: color 0.3s; &:hover { - color: var(--color-text) + color: var(--color-text); } } } @@ -105,7 +122,7 @@ const setSelectedType = (type: 'quests' | 'items') => { border-top: 1px solid var(--color-border); position: absolute; bottom: 0; - width: 100% + width: 100%; } #count { @@ -115,4 +132,4 @@ const setSelectedType = (type: 'quests' | 'items') => { color: var(--color-text-mute); } } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/EditorSidebarCategory.vue b/components/editor/EditorSidebarCategory.vue index 27a5ce0..c5adbca 100644 --- a/components/editor/EditorSidebarCategory.vue +++ b/components/editor/EditorSidebarCategory.vue @@ -33,8 +33,11 @@ const selected = computed(() => { <template> <div id="category-container" :class="{ selected: selected }"> <span id="category-title" @click="setSelectedCategory"> - <font-awesome-icon @click.stop="expandCategory" class="category-icon" - :icon="expanded ? ['fas', 'caret-down'] : ['fas', 'caret-up']" /> + <font-awesome-icon + @click.stop="expandCategory" + class="category-icon" + :icon="expanded ? ['fas', 'caret-down'] : ['fas', 'caret-up']" + /> <span id="category-name"> <span id="category-display-name">{{ stripColorCodes(category.display.name) }}</span> <code id="category-display-id">{{ category.id }}</code> @@ -42,7 +45,12 @@ const selected = computed(() => { </span> </div> <div v-if="expanded" id="quests"> - <EditorSidebarQuest class="quest" v-for="quest in questsInCategory" :key="quest.id" :quest="quest" /> + <EditorSidebarQuest + class="quest" + v-for="quest in questsInCategory" + :key="quest.id" + :quest="quest" + /> </div> </template> @@ -91,4 +99,4 @@ const selected = computed(() => { #category-container:hover { background-color: var(--color-hover); } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/EditorSidebarItem.vue b/components/editor/EditorSidebarItem.vue index 55f81d0..0e0040d 100644 --- a/components/editor/EditorSidebarItem.vue +++ b/components/editor/EditorSidebarItem.vue @@ -63,4 +63,4 @@ const selected = computed(() => { #item-container:hover { background-color: var(--color-hover); } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/EditorSidebarMainConfiguration.vue b/components/editor/EditorSidebarMainConfiguration.vue index 9ebef0e..9bc9239 100644 --- a/components/editor/EditorSidebarMainConfiguration.vue +++ b/components/editor/EditorSidebarMainConfiguration.vue @@ -16,9 +16,7 @@ const selected = computed(() => { <div id="container" :class="{ selected: selected }"> <span id="title" @click="setSelected"> <font-awesome-icon class="icon" :icon="['fas', 'wrench']" /> - <span id="name"> - Configuration - </span> + <span id="name"> Configuration </span> </span> </div> </template> @@ -53,4 +51,4 @@ const selected = computed(() => { #container:hover { background-color: var(--color-hover); } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/EditorSidebarQuest.vue b/components/editor/EditorSidebarQuest.vue index fb21042..54814f0 100644 --- a/components/editor/EditorSidebarQuest.vue +++ b/components/editor/EditorSidebarQuest.vue @@ -64,4 +64,4 @@ const selected = computed(() => { #quest-container:hover { background-color: var(--color-hover); } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/category/EditorCategoryChildrenOptionsPanel.vue b/components/editor/category/EditorCategoryChildrenOptionsPanel.vue index 57dcef2..f4a73ff 100644 --- a/components/editor/category/EditorCategoryChildrenOptionsPanel.vue +++ b/components/editor/category/EditorCategoryChildrenOptionsPanel.vue @@ -18,8 +18,7 @@ const category = computed(() => { <div id="options"> <h2>Quests in this category</h2> <p>Drag to reorder.</p> - <div class="option-group"> - </div> + <div class="option-group"></div> </div> </EditorOptionsPanel> </template> diff --git a/components/editor/category/EditorCategoryOptionsPanel.vue b/components/editor/category/EditorCategoryOptionsPanel.vue index 112b063..c543f73 100644 --- a/components/editor/category/EditorCategoryOptionsPanel.vue +++ b/components/editor/category/EditorCategoryOptionsPanel.vue @@ -17,9 +17,12 @@ const category = computed(() => { <EditorOptionsPanel v-if="category"> <div id="options"> <div class="option-group"> - <Checkbox id="category-permissionrequired" label="Require permission for category" + <Checkbox + id="category-permissionrequired" + label="Require permission for category" description="Players must have permission to open and start quests in this category." - v-model="category.permissionRequired" /> + v-model="category.permissionRequired" + /> </div> </div> </EditorOptionsPanel> diff --git a/components/editor/quest/EditorQuestOptionsPanel.vue b/components/editor/quest/EditorQuestOptionsPanel.vue index 6c1c8b1..bc5f7ef 100644 --- a/components/editor/quest/EditorQuestOptionsPanel.vue +++ b/components/editor/quest/EditorQuestOptionsPanel.vue @@ -17,7 +17,6 @@ const knownCategories = computed(() => { const knownQuests = computed(() => { return sessionStore.session.quests.map((quest) => quest.id); }); - </script> <template> @@ -25,87 +24,126 @@ const knownQuests = computed(() => { <div id="options"> <div class="option-group"> <label for="quest-category">Category</label> - <multiselect id="quest-category" v-model="quest.options.category" :options="knownCategories" :searchable="true" - placeholder="No category"></multiselect> + <multiselect + id="quest-category" + v-model="quest.options.category" + :options="knownCategories" + :searchable="true" + placeholder="No category" + ></multiselect> </div> <div class="option-group"> <label for="quest-requirements">Requirements</label> - <multiselect id="quest-requirements" v-model="quest.options.requirements" :options="knownQuests" - :searchable="true" :taggable="true" :multiple="true" placeholder="Add requirement"></multiselect> + <multiselect + id="quest-requirements" + v-model="quest.options.requirements" + :options="knownQuests" + :searchable="true" + :taggable="true" + :multiple="true" + placeholder="Add requirement" + ></multiselect> <p class="description"> - This quest will only be available if the player has completed all of the quests listed above. + This quest will only be available if the player has completed all of the quests listed + above. </p> </div> <h2>Quest options</h2> <div class="option-group"> - <Checkbox id="quest-permissionrequired" label="Require permission to start quest" - description="Players must have permission to start the quest." v-model="quest.options.permissionRequired" /> + <Checkbox + id="quest-permissionrequired" + label="Require permission to start quest" + description="Players must have permission to start the quest." + v-model="quest.options.permissionRequired" + /> </div> <div class="option-group"> - <Checkbox id="quest-cancellable" label="Allow players to cancel quest" - description="Players can cancel the quest after they have started it." v-model="quest.options.cancellable" /> + <Checkbox + id="quest-cancellable" + label="Allow players to cancel quest" + description="Players can cancel the quest after they have started it." + v-model="quest.options.cancellable" + /> </div> <div class="option-group"> - <Checkbox id="quest-countstowardslimit" label="Count towards quest limit" + <Checkbox + id="quest-countstowardslimit" + label="Count towards quest limit" description="Quest will count towards the player's quest started limit." - v-model="quest.options.countsTowardsLimit" /> + v-model="quest.options.countsTowardsLimit" + /> </div> <div class="option-group"> - <Checkbox id="quest-repeatable" label="Allow players to repeat quest" + <Checkbox + id="quest-repeatable" + label="Allow players to repeat quest" description="Quest can be completed again after it has been completed once." - v-model="quest.options.repeatable" /> + v-model="quest.options.repeatable" + /> </div> <div class="option-group"> - <Checkbox id="quest-autostart" label="Automatically start quest" + <Checkbox + id="quest-autostart" + label="Automatically start quest" description="Quest will start automatically when the player has unlocked it." - v-model="quest.options.autostart" /> + v-model="quest.options.autostart" + /> </div> - <h2>Cooldown</h2> <div class="option-group"> - <Checkbox id="quest-cooldown" label="Enable cooldown" + <Checkbox + id="quest-cooldown" + label="Enable cooldown" description="Players will have to wait a certain amount of time before they can start the quest again." - v-model="quest.options.cooldown.enabled" /> + v-model="quest.options.cooldown.enabled" + /> </div> <div class="option-group"> - <label for="quest-cooldown-time"> - Cooldown (in seconds) - </label> - <input id="quest-cooldown-time" type="number" v-model="quest.options.cooldown.time" - :disabled="!quest.options.cooldown.enabled" /> + <label for="quest-cooldown-time"> Cooldown (in seconds) </label> + <input + id="quest-cooldown-time" + type="number" + v-model="quest.options.cooldown.time" + :disabled="!quest.options.cooldown.enabled" + /> <p class="description"> - Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), <code>604800</code> (7 days), - <code>2592000</code> (30 days) + Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), + <code>604800</code> (7 days), <code>2592000</code> (30 days) </p> </div> <h2>Time limit</h2> <div class="option-group"> - <Checkbox id="quest-timelimit" label="Enable time limit" + <Checkbox + id="quest-timelimit" + label="Enable time limit" description="Players will be required to complete the quest within a certain amount of time, otherwise it will be automatically cancelled." - v-model="quest.options.timeLimit.enabled" /> + v-model="quest.options.timeLimit.enabled" + /> </div> <div class="option-group"> - <label for="quest-timelimit-time"> - Time limit (in seconds) - </label> - <input id="quest-timelimit-time" type="number" v-model="quest.options.timeLimit.time" - :disabled="!quest.options.timeLimit.enabled" /> + <label for="quest-timelimit-time"> Time limit (in seconds) </label> + <input + id="quest-timelimit-time" + type="number" + v-model="quest.options.timeLimit.time" + :disabled="!quest.options.timeLimit.enabled" + /> <p class="description"> - Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), <code>604800</code> (7 days), - <code>2592000</code> (30 days) + Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), + <code>604800</code> (7 days), <code>2592000</code> (30 days) </p> </div> </div> diff --git a/components/editor/quest/EditorQuestTasksOptionsPanel.vue b/components/editor/quest/EditorQuestTasksOptionsPanel.vue index cb4b109..a9e3ac3 100644 --- a/components/editor/quest/EditorQuestTasksOptionsPanel.vue +++ b/components/editor/quest/EditorQuestTasksOptionsPanel.vue @@ -29,22 +29,40 @@ const addTask = (newId: string, newType: string) => { <template> <EditorOptionsPanel v-if="quest"> <div id="options"> - <h2>Tasks <code>({{ Object.keys(quest.tasks).length }})</code></h2> + <h2> + Tasks <code>({{ Object.keys(quest.tasks).length }})</code> + </h2> - <p v-if="Object.keys(quest.tasks).length === 0" class="error-text">This quest does not have any tasks.</p> - <EditorTaskConfiguration v-for="(task, taskId) in quest.tasks" :key="taskId" :taskId="String(taskId)" - :quest="quest" /> + <p v-if="Object.keys(quest.tasks).length === 0" class="error-text"> + This quest does not have any tasks. + </p> + <EditorTaskConfiguration + v-for="(task, taskId) in quest.tasks" + :key="taskId" + :taskId="String(taskId)" + :quest="quest" + /> <div id="controls"> - <Button id="add-task" :icon="['fas', 'plus']" type="solid" label="Add task" @click="showAddTaskModal = true" /> + <Button + id="add-task" + :icon="['fas', 'plus']" + type="solid" + label="Add task" + @click="showAddTaskModal = true" + /> </div> </div> </EditorOptionsPanel> - <EditorTaskModalCreate v-if="quest" v-model="showAddTaskModal" :questId="questId" @add="addTask" /> + <EditorTaskModalCreate + v-if="quest" + v-model="showAddTaskModal" + :questId="questId" + @add="addTask" + /> </template> - <style scoped> #options { display: flex; diff --git a/components/editor/quest/modal/EditorQuestModalDelete.vue b/components/editor/quest/modal/EditorQuestModalDelete.vue index e81bcc7..c4e1682 100644 --- a/components/editor/quest/modal/EditorQuestModalDelete.vue +++ b/components/editor/quest/modal/EditorQuestModalDelete.vue @@ -13,10 +13,18 @@ defineProps({ <template v-slot:header> <h2>Really delete quest '{{ questId }}'?</h2> </template> - <p>Are you sure you want to delete this quest? The quests editor does not have undo functionality (yet)! </p> + <p> + Are you sure you want to delete this quest? The quests editor does not have undo functionality + (yet)! + </p> <div id="confirm" class="control-group"> <Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button> - <Button type="solid" :icon="['fas', 'trash']" :label="'Delete'" @click="emit('delete')"></Button> + <Button + type="solid" + :icon="['fas', 'trash']" + :label="'Delete'" + @click="emit('delete')" + ></Button> </div> </Modal> </template> @@ -27,4 +35,4 @@ defineProps({ justify-content: flex-end; margin-top: 1rem; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/quest/modal/EditorQuestModalDuplicate.vue b/components/editor/quest/modal/EditorQuestModalDuplicate.vue index 73a2fd0..6c333fb 100644 --- a/components/editor/quest/modal/EditorQuestModalDuplicate.vue +++ b/components/editor/quest/modal/EditorQuestModalDuplicate.vue @@ -17,7 +17,6 @@ const newQuestId = ref(props.questId); const isDuplicate = computed(() => { return session.getQuestById(newQuestId.value!) !== undefined; }); - </script> <template> @@ -36,8 +35,13 @@ const isDuplicate = computed(() => { <p>A Quest ID must be unique, alphanumeric, and not contain any spaces.</p> <div id="confirm" class="control-group"> <Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button> - <Button type="solid" :icon="['fas', 'check']" :label="'Duplicate'" :disabled="isDuplicate" - @click="emit('duplicate', newQuestId)"></Button> + <Button + type="solid" + :icon="['fas', 'check']" + :label="'Duplicate'" + :disabled="isDuplicate" + @click="emit('duplicate', newQuestId)" + ></Button> </div> </div> </template> @@ -55,4 +59,4 @@ const isDuplicate = computed(() => { flex-direction: column; gap: 0.5rem; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/quest/modal/EditorQuestModalRename.vue b/components/editor/quest/modal/EditorQuestModalRename.vue index 3d846aa..13c4810 100644 --- a/components/editor/quest/modal/EditorQuestModalRename.vue +++ b/components/editor/quest/modal/EditorQuestModalRename.vue @@ -17,7 +17,6 @@ const newQuestId = ref(props.questId); const isDuplicate = computed(() => { return session.getQuestById(newQuestId.value!) !== undefined; }); - </script> <template> @@ -36,8 +35,13 @@ const isDuplicate = computed(() => { <p>A Quest ID must be unique, alphanumeric, and not contain any spaces.</p> <div id="confirm" class="control-group"> <Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button> - <Button type="solid" :icon="['fas', 'check']" :label="'Rename'" :disabled="isDuplicate" - @click="emit('update', newQuestId)"></Button> + <Button + type="solid" + :icon="['fas', 'check']" + :label="'Rename'" + :disabled="isDuplicate" + @click="emit('update', newQuestId)" + ></Button> </div> </div> </template> @@ -55,4 +59,4 @@ const isDuplicate = computed(() => { flex-direction: column; gap: 0.5rem; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/quest/modal/EditorQuestModalYaml.vue b/components/editor/quest/modal/EditorQuestModalYaml.vue index 365055c..c7c4936 100644 --- a/components/editor/quest/modal/EditorQuestModalYaml.vue +++ b/components/editor/quest/modal/EditorQuestModalYaml.vue @@ -6,7 +6,7 @@ const emit = defineEmits(['delete']); const props = defineProps({ questId: { required: true, - type: String + type: String, }, }); @@ -18,16 +18,16 @@ const yamlString = ref(''); const open = () => { const quest = session.getQuestById(props.questId); if (!quest) { - return + return; } const mappedObject = mapJsonQuestToYamlObject(quest); yamlString.value = stringify(mappedObject); showModal.value = true; -} +}; defineExpose({ - open -}) + open, +}); </script> <template> @@ -36,12 +36,19 @@ defineExpose({ <h2>YAML</h2> </template> - <p>YAML file for <code>{{ props.questId }}</code></p> + <p> + YAML file for <code>{{ props.questId }}</code> + </p> <textarea rows="20" :value="yamlString" readonly /> <div id="confirm" class="control-group"> - <Button type="solid" :icon="['fas', 'check']" :label="'Close'" @click="showModal = false"></Button> + <Button + type="solid" + :icon="['fas', 'check']" + :label="'Close'" + @click="showModal = false" + ></Button> </div> </Modal> </template> @@ -56,4 +63,4 @@ defineExpose({ textarea { width: 100%; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/task/EditorTaskConfiguration.vue b/components/editor/task/EditorTaskConfiguration.vue index 5313767..dab5888 100644 --- a/components/editor/task/EditorTaskConfiguration.vue +++ b/components/editor/task/EditorTaskConfiguration.vue @@ -13,14 +13,21 @@ const taskType = computed(() => props.quest.tasks[props.taskId].config.type); const taskDefintion = computed(() => sessionStore.getTaskDefinitionByTaskType(taskType.value)); const taskConfig = computed(() => { - return Object.keys(props.quest.tasks[props.taskId].config).filter((fieldName) => fieldName !== 'type').reduce((acc, fieldName) => { - acc[fieldName] = props.quest.tasks[props.taskId].config[fieldName]; - return acc; - }, {} as { [key: string]: any }); + return Object.keys(props.quest.tasks[props.taskId].config) + .filter((fieldName) => fieldName !== 'type') + .reduce( + (acc, fieldName) => { + acc[fieldName] = props.quest.tasks[props.taskId].config[fieldName]; + return acc; + }, + {} as { [key: string]: any } + ); }); const requiredFields = computed(() => { - return Object.keys(taskDefintion.value.configuration).filter((fieldName) => taskDefintion.value.configuration[fieldName].required); + return Object.keys(taskDefintion.value.configuration).filter( + (fieldName) => taskDefintion.value.configuration[fieldName].required + ); }); // const givenRequiredFields = computed(() => { @@ -32,13 +39,20 @@ const requiredFields = computed(() => { // }); const remainingGivenFields = computed(() => { - return Object.keys(taskConfig.value).filter((fieldName) => !requiredFields.value.includes(fieldName) && fieldName in taskDefintion.value.configuration); + return Object.keys(taskConfig.value).filter( + (fieldName) => + !requiredFields.value.includes(fieldName) && fieldName in taskDefintion.value.configuration + ); }); -const configKeysOptions = computed(() => Object.keys(taskDefintion.value.configuration).filter((key) => !Object.keys(taskConfig.value).some((fieldName) => fieldName === key))); +const configKeysOptions = computed(() => + Object.keys(taskDefintion.value.configuration).filter( + (key) => !Object.keys(taskConfig.value).some((fieldName) => fieldName === key) + ) +); // const configKeysOptions = computed(() => { // const keys = Object.keys(taskDefintion.value.configuration).filter((key) => !Object.keys(taskConfig.value).some((fieldName) => fieldName === key)); -// +// // return keys.map((key) => { // return { // value: key, @@ -49,7 +63,8 @@ const configKeysOptions = computed(() => Object.keys(taskDefintion.value.configu // }); const onAddOption = (option: any) => { - sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config[option] = taskDefintion.value.configuration[option].default || null; + sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config[option] = + taskDefintion.value.configuration[option].default || null; }; const updateValue = (fieldName: string, value: any) => { @@ -64,14 +79,14 @@ const showChangeModal = ref(false); const updateTaskType = (newType: string) => { sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config = { - type: newType + type: newType, }; showChangeModal.value = false; -} +}; const deleteTaskType = (taskId: string) => { delete sessionStore.getQuestById(props.quest.id)!.tasks[taskId]; -} +}; </script> <template> @@ -82,43 +97,68 @@ const deleteTaskType = (taskId: string) => { {{ props.taskId }} </span> <code> - (<font-awesome-icon v-if="taskDefintion" id="task-icon" :icon="[taskDefintion.icon.style, taskDefintion.icon.name]" />{{ taskType }}) + (<font-awesome-icon + v-if="taskDefintion" + id="task-icon" + :icon="[taskDefintion.icon.style, taskDefintion.icon.name]" + />{{ taskType }}) </code> </p> <div id="task-controls" class="control-group"> <Button :icon="['fas', 'pen']" :label="'Change'" @click="showChangeModal = true"></Button> - <Button :icon="['fas', 'trash']" :label="'Delete'" @click="deleteTaskType(props.taskId)"></Button> + <Button + :icon="['fas', 'trash']" + :label="'Delete'" + @click="deleteTaskType(props.taskId)" + ></Button> </div> </div> <div id="task-configuration"> <div v-if="!taskDefintion" class="error"> <font-awesome-icon id="error-icon" :icon="['fas', 'triangle-exclamation']" /> <p id="error-message"> - Unable to edit task <code>{{ props.taskId }}</code>. + Unable to edit task <code>{{ props.taskId }}</code + >. </p> <p id="error-description"> - The quests web editor does not know how to configure task - type <code>{{ taskType }}</code> as it has no task definition. + The quests web editor does not know how to configure task type + <code>{{ taskType }}</code> as it has no task definition. </p> </div> <div v-if="taskDefintion"> - <EditorTaskConfigurationRow v-for="fieldName in [...requiredFields, ...remainingGivenFields]" - :key="`${quest.id}-${props.taskId}-${taskType}-${fieldName}`" :required="requiredFields.includes(fieldName)" - :configKey="fieldName" :initialValue="taskConfig[fieldName]" :taskType="taskType" - :type="(taskDefintion.configuration[fieldName].type as string)" - @update="(newValue: any) => updateValue(fieldName, newValue)" @delete="() => deleteValue(fieldName)" /> + <EditorTaskConfigurationRow + v-for="fieldName in [...requiredFields, ...remainingGivenFields]" + :key="`${quest.id}-${props.taskId}-${taskType}-${fieldName}`" + :required="requiredFields.includes(fieldName)" + :configKey="fieldName" + :initialValue="taskConfig[fieldName]" + :taskType="taskType" + :type="taskDefintion.configuration[fieldName].type as string" + @update="(newValue: any) => updateValue(fieldName, newValue)" + @delete="() => deleteValue(fieldName)" + /> <div id="add-option"> - <multiselect class="configuration-multiselect" :options="configKeysOptions" :searchable="true" - @select="onAddOption" placeholder="Add option..."> + <multiselect + class="configuration-multiselect" + :options="configKeysOptions" + :searchable="true" + @select="onAddOption" + placeholder="Add option..." + > </multiselect> </div> </div> </div> </div> - <EditorTaskModalChange v-model="showChangeModal" :taskId="props.taskId" :currentTaskType="taskType" - :key="`change-task-${props.taskId}`" @update="updateTaskType" /> + <EditorTaskModalChange + v-model="showChangeModal" + :taskId="props.taskId" + :currentTaskType="taskType" + :key="`change-task-${props.taskId}`" + @update="updateTaskType" + /> </template> <style scoped> @@ -133,7 +173,6 @@ const deleteTaskType = (taskId: string) => { #error-message { font-weight: 700; } - } #task-configuration-table { diff --git a/components/editor/task/EditorTaskConfigurationRow.vue b/components/editor/task/EditorTaskConfigurationRow.vue index c00896f..f400292 100644 --- a/components/editor/task/EditorTaskConfigurationRow.vue +++ b/components/editor/task/EditorTaskConfigurationRow.vue @@ -21,27 +21,37 @@ const emit = defineEmits(['update', 'delete']); const sessionStore = useSessionStore(); const definition = computed(() => { - const def = sessionStore.getTaskDefinitionByTaskType(props.taskType).configuration[props.configKey]; + const def = sessionStore.getTaskDefinitionByTaskType(props.taskType).configuration[ + props.configKey + ]; return { description: def.description, note: def.note }; }); const { description, note } = toRefs(definition.value); const showDescription = ref(false); -const currentValue = ref(props.initialValue || - (props.type === 'boolean' - ? false - : (props.type === 'material-list' || props.type === 'string-list' - ? [] - : props.type === 'itemstack' - ? null - : '' - ))); +const currentValue = ref( + props.initialValue || + (props.type === 'boolean' + ? false + : props.type === 'material-list' || props.type === 'string-list' + ? [] + : props.type === 'itemstack' + ? null + : '') +); if (props.initialValue !== currentValue.value) { emit('update', currentValue.value); } -const error = computed(() => currentValue.value === undefined || currentValue.value === null || currentValue.value === '' || (Array.isArray(currentValue.value) && currentValue.value.length === 0) || (typeof currentValue.value === 'object' && Object.keys(currentValue.value).length === 0)); +const error = computed( + () => + currentValue.value === undefined || + currentValue.value === null || + currentValue.value === '' || + (Array.isArray(currentValue.value) && currentValue.value.length === 0) || + (typeof currentValue.value === 'object' && Object.keys(currentValue.value).length === 0) +); const updateValue = (value: any) => { currentValue.value = value; }; @@ -53,7 +63,6 @@ watch(currentValue, () => { const addValue = (searchQuery: any) => { currentValue.value.push(searchQuery); }; - </script> <template> @@ -73,23 +82,49 @@ const addValue = (searchQuery: any) => { <input v-else-if="props.type === 'number'" type="number" v-model="currentValue" /> <!-- Data type 'boolean' --> - <TrueFalseSwitch v-else-if="props.type === 'boolean'" :value="!!currentValue" @update="updateValue" /> + <TrueFalseSwitch + v-else-if="props.type === 'boolean'" + :value="!!currentValue" + @update="updateValue" + /> <!-- Data type 'material-list' --> - <multiselect v-else-if="props.type === 'material-list'" v-model="currentValue" class="configuration-multiselect" - :options="materials" :multiple="true" :taggable="true" :searchable="true" placeholder="Enter material name" /> + <multiselect + v-else-if="props.type === 'material-list'" + v-model="currentValue" + class="configuration-multiselect" + :options="materials" + :multiple="true" + :taggable="true" + :searchable="true" + placeholder="Enter material name" + /> <!-- Data type 'string-list' --> - <multiselect v-else-if="props.type === 'string-list'" v-model="currentValue" class="configuration-multiselect" - :options="[]" @tag="addValue" :multiple="true" :taggable="true" :searchable="true" - placeholder="Enter string" /> + <multiselect + v-else-if="props.type === 'string-list'" + v-model="currentValue" + class="configuration-multiselect" + :options="[]" + @tag="addValue" + :multiple="true" + :taggable="true" + :searchable="true" + placeholder="Enter string" + /> <!-- Data type 'itemstack' --> - <ItemStackPicker v-else-if="props.type === 'itemstack'" :value="currentValue" @update="updateValue" /> + <ItemStackPicker + v-else-if="props.type === 'itemstack'" + :value="currentValue" + @update="updateValue" + /> <div v-if="showDescription || error" id="task-configuration-row-info"> <p v-if="error" class="error">A value is required.</p> - <p>{{ description }} <i>{{ note }}</i></p> + <p> + {{ description }} <i>{{ note }}</i> + </p> </div> </div> </div> @@ -182,4 +217,4 @@ input { .error { color: var(--color-false); } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/task/modal/EditorTaskModalChange.vue b/components/editor/task/modal/EditorTaskModalChange.vue index 8ab5dbc..a6b05b8 100644 --- a/components/editor/task/modal/EditorTaskModalChange.vue +++ b/components/editor/task/modal/EditorTaskModalChange.vue @@ -18,7 +18,9 @@ const knownTaskTypes = computed(() => session.getKnownTaskTypes()); const newType = ref(''); const unknownTaskType = computed(() => !knownTaskTypes.value.includes(newType.value)); const noChange = computed(() => newType.value === props.currentTaskType); -const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(newType.value)?.description); +const newTypeDescription = computed( + () => session.getTaskDefinitionByTaskType(newType.value)?.description +); </script> <template> @@ -31,16 +33,26 @@ const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(ne <div id="body"> <div class="option-group"> <label for="new-type">New type</label> - <multiselect id="new-type" v-model="newType" :options="knownTaskTypes" :searchable="true" - placeholder="Select a new type"></multiselect> + <multiselect + id="new-type" + v-model="newType" + :options="knownTaskTypes" + :searchable="true" + placeholder="Select a new type" + ></multiselect> </div> <p v-if="unknownTaskType" class="error-text">Invalid task type.</p> <p v-if="newTypeDescription">{{ newTypeDescription }}</p> <p>Any configured options for this task will be overwritten.</p> <div id="confirm" class="control-group"> <Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button> - <Button type="solid" :icon="['fas', 'check']" :label="'Change'" :disabled="unknownTaskType || noChange" - @click="emit('update', newType)"></Button> + <Button + type="solid" + :icon="['fas', 'check']" + :label="'Change'" + :disabled="unknownTaskType || noChange" + @click="emit('update', newType)" + ></Button> </div> </div> </template> @@ -58,4 +70,4 @@ const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(ne flex-direction: column; gap: 0.5rem; } -</style>
\ No newline at end of file +</style> diff --git a/components/editor/task/modal/EditorTaskModalCreate.vue b/components/editor/task/modal/EditorTaskModalCreate.vue index e5b2d7a..cdd955f 100644 --- a/components/editor/task/modal/EditorTaskModalCreate.vue +++ b/components/editor/task/modal/EditorTaskModalCreate.vue @@ -24,7 +24,9 @@ const unknownTaskType = computed(() => !knownTaskTypes.value.includes(newType.va const invalidTaskId = computed(() => !validateTaskId(newId.value)); const duplicateTaskId = computed(() => knownTasks.value[newId.value] !== undefined); -const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(newType.value)?.description); +const newTypeDescription = computed( + () => session.getTaskDefinitionByTaskType(newType.value)?.description +); </script> <template> @@ -43,19 +45,26 @@ const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(ne </div> <div class="option-group"> <label for="new-type">Task type</label> - <multiselect id="new-type" v-model="newType" :options="knownTaskTypes" :searchable="true" - placeholder="Select a new type"></multiselect> + <multiselect + id="new-type" + v-model="newType" + :options="knownTaskTypes" + :searchable="true" + placeholder="Select a new type" + ></multiselect> <p v-if="unknownTaskType" class="error-text">Invalid task type.</p> </div> <p v-if="newTypeDescription">{{ newTypeDescription }}</p> <p>A task ID must be unique, alphanumeric, and not contain any spaces.</p> <div id="confirm" class="control-group"> <Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button> - <Button type="solid" :icon="['fas', 'check']" :label="'Confirm'" + <Button + type="solid" + :icon="['fas', 'check']" + :label="'Confirm'" :disabled="unknownTaskType || invalidTaskId || duplicateTaskId" - @click="emit('add', newId, newType)"></Button> - - + @click="emit('add', newId, newType)" + ></Button> </div> </div> </template> @@ -73,4 +82,4 @@ const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(ne flex-direction: column; gap: 0.5rem; } -</style>
\ No newline at end of file +</style> |
