forked from noxious/client
Added search functionality for tiles and objects, finished object management and added its logic to the zone editor
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
<div class="absolute left-0 bottom-0 w-full h-[1px] bg-cyan-200"></div>
|
||||
</div>
|
||||
<div class="modal-form asset-manager m-2.5 p-2.5 block">
|
||||
<form class="flex gap-2.5 flex-wrap" @submit.prevent>
|
||||
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveObject">
|
||||
<div class="w-full flex flex-col mb-5">
|
||||
<label class="mb-1.5 font-titles" for="name">Name</label>
|
||||
<input v-model="objectName" class="input-cyan" type="text" name="name" placeholder="Wall #1" />
|
||||
@ -18,8 +18,8 @@
|
||||
<label class="mb-1.5 font-titles" for="origin-y">Origin Y</label>
|
||||
<input v-model="objectOriginY" class="input-cyan" type="number" name="origin-y" placeholder="Origin Y" />
|
||||
</div>
|
||||
<button class="btn-cyan px-[15px] py-1.5 min-w-[100px]" type="button" @click="removeObject">Save</button>
|
||||
<button class="btn-bordeaux px-[15px] py-1.5 min-w-[100px]" type="button" @click="removeObject">Remove</button>
|
||||
<button class="btn-cyan px-[15px] py-1.5 min-w-[100px]" type="submit">Save</button>
|
||||
<button class="btn-bordeaux px-[15px] py-1.5 min-w-[100px]" type="button" @click.prevent="removeObject">Remove</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Object } from '@/types'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useAssetManagerStore } from '@/stores/assetManager'
|
||||
import { useSocketStore } from '@/stores/socket'
|
||||
import config from '@/config'
|
||||
@ -50,6 +50,13 @@ if (selectedObject.value) {
|
||||
objectOriginY.value = selectedObject.value.origin_y
|
||||
}
|
||||
|
||||
watch(selectedObject, (object: Object | null) => {
|
||||
if (!object) return
|
||||
objectName.value = object.name
|
||||
objectOriginX.value = object.origin_x
|
||||
objectOriginY.value = object.origin_y
|
||||
})
|
||||
|
||||
function removeObject() {
|
||||
socket.connection.emit('gm:object:remove', { object: selectedObject.value }, (response: boolean) => {
|
||||
if (!response) {
|
||||
@ -67,6 +74,30 @@ function refreshObjectList() {
|
||||
})
|
||||
}
|
||||
|
||||
function saveObject() {
|
||||
if (!selectedObject.value) {
|
||||
console.error('No object selected')
|
||||
return
|
||||
}
|
||||
|
||||
socket.connection.emit(
|
||||
'gm:object:update',
|
||||
{
|
||||
id: selectedObject.value.id,
|
||||
name: objectName.value,
|
||||
origin_x: objectOriginX.value,
|
||||
origin_y: objectOriginY.value
|
||||
},
|
||||
(response: boolean) => {
|
||||
if (!response) {
|
||||
console.error('Failed to save object')
|
||||
return
|
||||
}
|
||||
refreshObjectList()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!selectedObject.value) return
|
||||
})
|
||||
|
@ -4,10 +4,10 @@
|
||||
<input class="hidden" id="upload-asset" ref="objectUploadField" type="file" accept="image/png" multiple @change="handleFileUpload" />
|
||||
Upload object(s)
|
||||
</label>
|
||||
<input class="input-cyan search-field w-full" placeholder="Search..." />
|
||||
<input v-model="searchQuery" class="input-cyan search-field w-full" placeholder="Search..." @input="handleSearch" />
|
||||
<div class="absolute left-0 bottom-0 w-full h-[1px] bg-cyan-200"></div>
|
||||
</div>
|
||||
<a class="asset relative p-2.5 cursor-pointer" :class="{ active: assetManagerStore.selectedObject?.id === object.id }" v-for="(object, index) in assetManagerStore.objectList" :key="index" @click="assetManagerStore.setSelectedObject(object as Object)">
|
||||
<a class="asset relative p-2.5 cursor-pointer" :class="{ active: assetManagerStore.selectedObject?.id === object.id }" v-for="(object, index) in filteredObjects" :key="index" @click="assetManagerStore.setSelectedObject(object as Object)">
|
||||
<div class="asset-details flex items-center gap-2.5">
|
||||
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
|
||||
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/objects/${object.id}.png`" alt="Object" />
|
||||
@ -21,7 +21,7 @@
|
||||
<script setup lang="ts">
|
||||
import config from '@/config'
|
||||
import { useSocketStore } from '@/stores/socket'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { useAssetManagerStore } from '@/stores/assetManager'
|
||||
import { useAssetStore } from '@/stores/assets'
|
||||
import type { Object } from '@/types'
|
||||
@ -31,6 +31,8 @@ const objectUploadField = ref(null)
|
||||
const assetManagerStore = useAssetManagerStore()
|
||||
const assetStore = useAssetStore()
|
||||
|
||||
const searchQuery = ref('')
|
||||
|
||||
const handleFileUpload = (e: Event) => {
|
||||
const files = (e.target as HTMLInputElement).files
|
||||
if (!files) return
|
||||
@ -48,6 +50,20 @@ const handleFileUpload = (e: Event) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
// The filtering is handled by the computed property, so we don't need to do anything here
|
||||
// This function is kept in case you want to add debounce or other functionality later
|
||||
}
|
||||
|
||||
const filteredObjects = computed(() => {
|
||||
if (!searchQuery.value) {
|
||||
return assetManagerStore.objectList
|
||||
}
|
||||
return assetManagerStore.objectList.filter(object =>
|
||||
object.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||
)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
socket.connection.emit('gm:object:list', {}, (response: Object[]) => {
|
||||
if (config.development) console.log(response)
|
||||
|
@ -4,10 +4,10 @@
|
||||
<input class="hidden" id="upload-asset" ref="tileUploadField" type="file" accept="image/png" multiple @change="handleFileUpload" />
|
||||
Upload tile(s)
|
||||
</label>
|
||||
<input class="input-cyan search-field w-full" placeholder="Search..." />
|
||||
<input v-model="searchQuery" class="input-cyan search-field w-full" placeholder="Search..." @input="handleSearch" />
|
||||
<div class="absolute left-0 bottom-0 w-full height-[1px] bg-cyan-200"></div>
|
||||
</div>
|
||||
<a class="asset relative p-2.5 cursor-pointer flex gap-y-2.5 gap-x-5 flex-wrap" :class="{ active: assetManagerStore.selectedTile === tile }" v-for="(tile, index) in assetManagerStore.tileList" :key="index" @click="assetManagerStore.setSelectedTile(tile)">
|
||||
<a class="asset relative p-2.5 cursor-pointer flex gap-y-2.5 gap-x-5 flex-wrap" :class="{ active: assetManagerStore.selectedTile === tile }" v-for="(tile, index) in filteredTiles" :key="index" @click="assetManagerStore.setSelectedTile(tile)">
|
||||
<div class="asset-details flex items-center gap-2.5">
|
||||
<!-- TODO make all img have same width so text aligns nicely -->
|
||||
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/tiles/${tile}.png`" alt="Tile" />
|
||||
@ -20,7 +20,7 @@
|
||||
<script setup lang="ts">
|
||||
import config from '@/config'
|
||||
import { useSocketStore } from '@/stores/socket'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { useAssetManagerStore } from '@/stores/assetManager'
|
||||
import { useAssetStore } from '@/stores/assets'
|
||||
|
||||
@ -29,6 +29,8 @@ const tileUploadField = ref(null)
|
||||
const assetManagerStore = useAssetManagerStore()
|
||||
const assetStore = useAssetStore()
|
||||
|
||||
const searchQuery = ref('')
|
||||
|
||||
const handleFileUpload = (e: Event) => {
|
||||
const files = (e.target as HTMLInputElement).files
|
||||
if (!files) return
|
||||
@ -46,6 +48,20 @@ const handleFileUpload = (e: Event) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
// The filtering is handled by the computed property, so we don't need to do anything here
|
||||
// This function is kept in case you want to add debounce or other functionality later
|
||||
}
|
||||
|
||||
const filteredTiles = computed(() => {
|
||||
if (!searchQuery.value) {
|
||||
return assetManagerStore.tileList
|
||||
}
|
||||
return assetManagerStore.tileList.filter(tile =>
|
||||
tile.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||
)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
socket.connection.emit('gm:tile:list', {}, (response: string[]) => {
|
||||
if (config.development) console.log(response)
|
||||
|
Reference in New Issue
Block a user