Skip to content
This repository was archived by the owner on Jan 6, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions packages/client/components/AssetListItem.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
<script setup lang="ts">
const props = defineProps<{
asset: AssetInfo
}>()
const props = withDefaults(defineProps<{
item: any
index?: number
modelValue: AssetInfo | undefined
}>(), {
index: 0,
})

const emit = defineEmits<{ (...args: any): void }>()
const model = useVModel(props, 'modelValue', emit, { passive: true })

const isCollection = computed(() => props.item?.children?.length)

const open = ref(true)

const icon = computed(() => {
if (isCollection.value)
return 'i-carbon-folder'
const assets = {
image: 'i-carbon-image',
video: 'i-carbon-video',
Expand All @@ -12,15 +25,33 @@ const icon = computed(() => {
text: 'i-carbon-document',
json: 'i-carbon-json',
}
return assets[props.asset.type] ?? 'i-carbon-document-blank'
return assets[props.item.type] ?? 'i-carbon-document-blank'
})
</script>

<template>
<button flex="~ gap-1" w-full items-center hover="bg-active" rounded px4 py2>
<div :class="icon" />
<div of-hidden truncate ws-nowrap text-center>
{{ asset.path }}
</div>
</button>
<div>
<button
flex="~ gap-2" w-full items-center hover="bg-active" px4 py1
:style="{ paddingLeft: `calc(1rem + ${index * 1.5}em)` }"
:class="{ 'bg-active': !isCollection && model?.filePath === item?.filePath }"
@click="isCollection ? open = !open : model = item"
>
<div :class="icon" />
<span :class="{ 'flex items-center': isCollection }" flex-auto text-start text-sm font-mono>
{{ item.path }}
</span>
<VDIcon v-if="isCollection" icon="carbon:chevron-right" :transform-rotate="open ? 90 : 0" transition />
</button>
<div x-divider />
<slot v-if="open">
<AssetListItem
v-for="subItem in item?.children"
:key="subItem.filepath"
v-model="model"
:item="subItem"
:index="index + 1"
/>
</slot>
</div>
</template>
27 changes: 26 additions & 1 deletion packages/client/pages/assets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@ const byFolders = computed(() => {
return Object.entries(result).sort(([a], [b]) => a.localeCompare(b))
})

const byTree = computed(() => {
const root = { path: 'public', children: [] }
const addToTree = (node: any, pathParts: any, file: AssetInfo) => {
const [currentPart, ...remainingParts] = pathParts
let child = node.children.find((child: any) => child.path === currentPart)
if (!child) {
child = { ...file, path: currentPart, children: [] }
node.children.push(child)
}
if (remainingParts.length > 1)
addToTree(child, remainingParts, file)
else if (remainingParts.length === 1)
child.children.push({ ...file, path: remainingParts[0] })
}
filtered.value.forEach((file) => {
const pathParts = file.path.split('/').filter(part => part !== '')
addToTree(root, pathParts, file)
})
return root.children
})

const selected = ref<AssetInfo>()

const view = ref<'list' | 'grid'>('grid')
Expand Down Expand Up @@ -92,7 +113,11 @@ const navbar = ref<HTMLElement>()
</div>
</template>
<div v-else>
<AssetListItem v-for="a of filtered" :key="a.path" :asset="a" @click="selected = a" />
<AssetListItem
v-for="item, key of byTree" :key="key"
v-model="selected"
:item="item"
/>
</div>
<DrawerRight
:model-value="!!selected"
Expand Down