diff options
Diffstat (limited to 'components/editor/task')
4 files changed, 157 insertions, 62 deletions
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> |
