aboutsummaryrefslogtreecommitdiffstats
path: root/components/editor
diff options
context:
space:
mode:
Diffstat (limited to 'components/editor')
-rw-r--r--components/editor/EditorOptionsPanel.vue5
-rw-r--r--components/editor/EditorSidebar.vue41
-rw-r--r--components/editor/EditorSidebarCategory.vue16
-rw-r--r--components/editor/EditorSidebarItem.vue2
-rw-r--r--components/editor/EditorSidebarMainConfiguration.vue6
-rw-r--r--components/editor/EditorSidebarQuest.vue2
-rw-r--r--components/editor/category/EditorCategoryChildrenOptionsPanel.vue3
-rw-r--r--components/editor/category/EditorCategoryOptionsPanel.vue7
-rw-r--r--components/editor/quest/EditorQuestOptionsPanel.vue108
-rw-r--r--components/editor/quest/EditorQuestTasksOptionsPanel.vue32
-rw-r--r--components/editor/quest/modal/EditorQuestModalDelete.vue14
-rw-r--r--components/editor/quest/modal/EditorQuestModalDuplicate.vue12
-rw-r--r--components/editor/quest/modal/EditorQuestModalRename.vue12
-rw-r--r--components/editor/quest/modal/EditorQuestModalYaml.vue23
-rw-r--r--components/editor/task/EditorTaskConfiguration.vue93
-rw-r--r--components/editor/task/EditorTaskConfigurationRow.vue77
-rw-r--r--components/editor/task/modal/EditorTaskModalChange.vue24
-rw-r--r--components/editor/task/modal/EditorTaskModalCreate.vue25
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>