Skip to content

Commit

Permalink
feat: use custom menu
Browse files Browse the repository at this point in the history
  • Loading branch information
kerwanp committed Oct 16, 2024
1 parent f66035d commit 8449eef
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 71 deletions.
5 changes: 4 additions & 1 deletion resources/components/resource-detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ defineProps<{
<div class="flex flex-col gap-8">
<Card>
<template v-for="field of resource.fields.filter((f) => f.type === 'field')">
<div v-if="field.visibility.detail" class="flex border-b dark:border-surface-800">
<div
v-if="field.visibility.detail"
class="flex border-b last:border-none dark:border-surface-800"
>
<div class="w-64 flex items-center py-4">
{{ field.label }}
</div>
Expand Down
5 changes: 4 additions & 1 deletion resources/components/resource-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ const emit = defineEmits<{
<form class="flex flex-col gap-8" @submit.prevent="emit('submit', form.data())">
<Card>
<template v-for="field of resource.fields.filter((f) => f.type === 'field')">
<div v-if="field.visibility[action]" class="flex border-b dark:border-surface-800">
<div
v-if="field.visibility[action]"
class="flex border-b last:border-none dark:border-surface-800"
>
<div class="w-64 flex items-center py-4">
<label :for="field.name" class="cursor-pointer">
{{ field.label }}
Expand Down
33 changes: 19 additions & 14 deletions resources/components/resource-peek.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@ defineProps<{

<template>
<div class="flex flex-col min-w-[300px]">
<template v-for="field of resource.fields.filter((f) => f.type === 'field')">
<div v-if="field.visibility.detail" class="flex border-b dark:border-surface-800">
<div class="w-24 flex items-center py-2">
{{ field.label }}
<div>
<template v-for="field of resource.fields.filter((f) => f.type === 'field')">
<div
v-if="field.visibility.detail"
class="flex border-b last:border-none dark:border-surface-800"
>
<div class="w-24 flex items-center py-2">
{{ field.label }}
</div>
<div class="flex items-center py-2">
<component
:is="field.detailComponent ?? field.indexComponent"
:field="field"
:record="data"
:value="data[field.name]"
/>
</div>
</div>
<div class="flex items-center py-2">
<component
:is="field.detailComponent ?? field.indexComponent"
:field="field"
:record="data"
:value="data[field.name]"
/>
</div>
</div>
</template>
</template>
</div>
<div class="mt-3 flex gap-2">
<EditButton
class="flex-1"
Expand Down
22 changes: 12 additions & 10 deletions resources/components/resource-table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,18 @@ function handleDeleted() {
v-model:selected-rows="selectedRows"
>
<template #rowActions="{ data }">
<DetailButton rounded text label severity="secondary" :record-id="data.id" />
<EditButton rounded text label severity="info" :record-id="data.id" />
<DeleteButton
rounded
text
label
severity="danger"
:record-id="data.id"
@success="handleDeleted"
/>
<div class="flex gap-1 flex-nowrap">
<DetailButton rounded text label severity="secondary" :record-id="data.id" />
<EditButton rounded text label severity="info" :record-id="data.id" />
<DeleteButton
rounded
text
label
severity="danger"
:record-id="data.id"
@success="handleDeleted"
/>
</div>
</template>
</DataTable>
</template>
Expand Down
36 changes: 3 additions & 33 deletions resources/components/sidebar.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
<script setup lang="ts">
import type { InferSerializable } from '../../src/types'
import type { BaseResource } from '../../src/resources/base_resource'
import { MenuItem as PrimeMenuItem } from 'primevue/menuitem'
import { Link } from '@inertiajs/vue3'
import { Ref, ref } from 'vue'
import Menu from 'primevue/menu'
import ThemeSelector from './ui/theme-selector.vue'
import CreateMenu from './resource/create-menu.vue'
import Badge from 'primevue/badge'
import { Menu as MenuData } from '../../src/menu/menu'
import Menu from './ui/menu/index.vue'
const props = defineProps<{
defineProps<{
menu: InferSerializable<MenuData>[]
resources: InferSerializable<BaseResource>[]
}>()
const items: Ref<PrimeMenuItem[]> = ref(props.menu)
</script>

<template>
Expand All @@ -26,29 +19,6 @@ const items: Ref<PrimeMenuItem[]> = ref(props.menu)
<img src="https://adonis-cockpit.com/logo-horizontal.png" />
</div>
<CreateMenu />
<Menu
:model="items"
class="h-full flex flex-col border-none bg-transparent py-4"
:pt="{ list: { class: 'flex-1' } }"
>
<template #submenulabel="{ item }">
<span class="text-muted-color font-semibold text-sm">{{ item.label }}</span>
</template>
<template #item="{ item, props }">
<Link v-if="item.url" :href="item.url" class="flex items-center w-full py-1 px-3 gap-2">
<div class="w-4 h-4" :class="item.icon" />
<div>{{ item.label }}</div>
<Badge v-if="item.badge" class="ml-auto" :value="item.badge" />
<span
v-if="item.shortcut"
class="ml-auto border border-surface rounded bg-emphasis text-muted-color text-xs p-1"
>{{ item.shortcut }}</span
>
</Link>
</template>
<template #end>
<ThemeSelector />
</template>
</Menu>
<Menu :menu="menu" />
</div>
</template>
18 changes: 18 additions & 0 deletions resources/components/ui/menu/category.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts" setup>
import { MenuItem } from '../../../../src/menu/menu_item'
import { InferSerializable } from '../../../../src/types'
import Item from './item.vue'
defineProps<{
item: InferSerializable<MenuItem>
}>()
</script>

<template>
<ul class="mt-4 flex flex-col">
<li class="text-sm text-muted-color font-semibold mb-2">{{ item.label }}</li>
<li v-for="item in item.items">
<Item :item="item" />
</li>
</ul>
</template>
19 changes: 19 additions & 0 deletions resources/components/ui/menu/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang="ts">
import { Menu } from '../../../../src/menu/menu'
import { InferSerializable } from '../../../../src/types'
import MenuCategory from './category.vue'
import MenuItem from './item.vue'
defineProps<{
menu: InferSerializable<Menu>
}>()
</script>

<template>
<ul class="flex flex-col py-6">
<li v-for="item of menu">
<MenuCategory v-if="item.items" :item="item" />
<MenuItem v-else :item="item" />
</li>
</ul>
</template>
33 changes: 33 additions & 0 deletions resources/components/ui/menu/item.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts" setup>
import { Link } from '@inertiajs/vue3'
import { MenuItem } from '../../../../src/menu/menu_item'
import { InferSerializable } from '../../../../src/types'
import { router } from '@inertiajs/vue3'
import { ref } from 'vue'
const props = defineProps<{
item: InferSerializable<MenuItem>
}>()
const isActive = ref<boolean>(false)
router.on('navigate', (event: any) => {
const pathname = event.detail.page.url
if (props.item.prefixMatch) {
isActive.value = pathname.startsWith(props.item.url)
} else {
isActive.value = pathname === props.item.url
}
})
</script>

<template>
<Link
:href="item.url"
class="px-2 py-1 hover:bg-indigo-700/20 aria-selected:bg-indigo-700/60 rounded-md duration-75 mb-1 flex gap-2 items-center"
:aria-selected="isActive"
>
<div class="w-4 h-4" :class="item.icon" />
{{ item.label }}
</Link>
</template>
7 changes: 5 additions & 2 deletions src/menu/menu_category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ export class MenuCategory implements Serializable {
return item
}

/**
* Adds an item from a resource.
*/
resource(resource: (new () => BaseResource) | BaseResource): MenuItem {
const instance = resource instanceof BaseResource ? resource : new resource()
const item = this.item(instance.labelPlural())
.prefixMatch()
.route(`cockpit.resources.index`, { slug: instance.name() })

if (instance.icon) {
item.icon(instance.icon())
}

item.route(`cockpit.resources.index`, { slug: instance.name() })

return item
}

Expand Down
27 changes: 17 additions & 10 deletions src/menu/menu_item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class MenuItem {
#href?: string
#target?: string
#icon?: string
#prefixMatch = false

constructor(label: string) {
this.#label = label
Expand Down Expand Up @@ -36,23 +37,29 @@ export class MenuItem {
return this
}

// public static resource(Resource: Type<BaseResource>): MenuItem {
// const resource = new Resource()
// const item = this.make().label(resource.labelPlural()).href(resource.route('index'))
//
// if (resource.icon) {
// item.icon(resource.icon())
// }
//
// return item
// }
/**
* Make the item active using prefix matching.
*/
prefixMatch(): this {
this.#prefixMatch = true
return this
}

/**
* Make the item active using exact matching.
*/
exactMatch(): this {
this.#prefixMatch = false
return this
}

toJSON(): PrimeMenuItem {
return {
label: this.#label,
url: this.#href,
target: this.#target,
icon: this.#icon,
prefixMatch: this.#prefixMatch,
}
}
}

0 comments on commit 8449eef

Please sign in to comment.